1 /* 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 17 package com.android.server; 18 19 import com.android.internal.app.IMediaContainerService; 20 import com.android.internal.app.ResolverActivity; 21 import com.android.internal.content.NativeLibraryHelper; 22 import com.android.internal.content.PackageHelper; 23 import com.android.internal.util.FastXmlSerializer; 24 import com.android.internal.util.JournaledFile; 25 import com.android.internal.util.XmlUtils; 26 27 import org.xmlpull.v1.XmlPullParser; 28 import org.xmlpull.v1.XmlPullParserException; 29 import org.xmlpull.v1.XmlSerializer; 30 31 import android.app.ActivityManagerNative; 32 import android.app.IActivityManager; 33 import android.app.admin.IDevicePolicyManager; 34 import android.app.backup.IBackupManager; 35 import android.content.Context; 36 import android.content.ComponentName; 37 import android.content.IIntentReceiver; 38 import android.content.Intent; 39 import android.content.IntentFilter; 40 import android.content.IntentSender; 41 import android.content.ServiceConnection; 42 import android.content.IntentSender.SendIntentException; 43 import android.content.pm.ActivityInfo; 44 import android.content.pm.ApplicationInfo; 45 import android.content.pm.ComponentInfo; 46 import android.content.pm.FeatureInfo; 47 import android.content.pm.IPackageDataObserver; 48 import android.content.pm.IPackageDeleteObserver; 49 import android.content.pm.IPackageInstallObserver; 50 import android.content.pm.IPackageManager; 51 import android.content.pm.IPackageMoveObserver; 52 import android.content.pm.IPackageStatsObserver; 53 import android.content.pm.InstrumentationInfo; 54 import android.content.pm.PackageInfo; 55 import android.content.pm.PackageInfoLite; 56 import android.content.pm.PackageManager; 57 import android.content.pm.PackageStats; 58 import android.content.pm.ParceledListSlice; 59 60 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 61 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 62 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 63 import android.content.pm.PackageParser; 64 import android.content.pm.PermissionInfo; 65 import android.content.pm.PermissionGroupInfo; 66 import android.content.pm.ProviderInfo; 67 import android.content.pm.ResolveInfo; 68 import android.content.pm.ServiceInfo; 69 import android.content.pm.Signature; 70 import android.net.Uri; 71 import android.os.Binder; 72 import android.os.Build; 73 import android.os.Bundle; 74 import android.os.Debug; 75 import android.os.HandlerThread; 76 import android.os.IBinder; 77 import android.os.Looper; 78 import android.os.Message; 79 import android.os.Parcel; 80 import android.os.Parcelable; 81 import android.os.RemoteException; 82 import android.os.Environment; 83 import android.os.FileObserver; 84 import android.os.FileUtils; 85 import android.os.Handler; 86 import android.os.ParcelFileDescriptor; 87 import android.os.Process; 88 import android.os.ServiceManager; 89 import android.os.SystemClock; 90 import android.os.SystemProperties; 91 import android.provider.Settings; 92 import android.security.SystemKeyStore; 93 import android.util.*; 94 import android.view.Display; 95 import android.view.WindowManager; 96 97 import java.io.BufferedOutputStream; 98 import java.io.File; 99 import java.io.FileDescriptor; 100 import java.io.FileInputStream; 101 import java.io.FileNotFoundException; 102 import java.io.FileOutputStream; 103 import java.io.FileReader; 104 import java.io.FilenameFilter; 105 import java.io.IOException; 106 import java.io.InputStream; 107 import java.io.PrintWriter; 108 import java.security.NoSuchAlgorithmException; 109 import java.text.SimpleDateFormat; 110 import java.util.ArrayList; 111 import java.util.Arrays; 112 import java.util.Collection; 113 import java.util.Collections; 114 import java.util.Comparator; 115 import java.util.Date; 116 import java.util.Enumeration; 117 import java.util.HashMap; 118 import java.util.HashSet; 119 import java.util.Iterator; 120 import java.util.LinkedList; 121 import java.util.List; 122 import java.util.Map; 123 import java.util.Set; 124 import java.util.zip.ZipEntry; 125 import java.util.zip.ZipException; 126 import java.util.zip.ZipFile; 127 import java.util.zip.ZipOutputStream; 128 129 /** 130 * Keep track of all those .apks everywhere. 131 * 132 * This is very central to the platform's security; please run the unit 133 * tests whenever making modifications here: 134 * 135 mmm frameworks/base/tests/AndroidTests 136 adb install -r -f out/target/product/passion/data/app/AndroidTests.apk 137 adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner 138 * 139 */ 140 class PackageManagerService extends IPackageManager.Stub { 141 private static final String TAG = "PackageManager"; 142 private static final boolean DEBUG_SETTINGS = false; 143 private static final boolean DEBUG_PREFERRED = false; 144 private static final boolean DEBUG_UPGRADE = false; 145 private static final boolean DEBUG_INSTALL = false; 146 147 private static final boolean MULTIPLE_APPLICATION_UIDS = true; 148 private static final int RADIO_UID = Process.PHONE_UID; 149 private static final int LOG_UID = Process.LOG_UID; 150 private static final int NFC_UID = Process.NFC_UID; 151 private static final int FIRST_APPLICATION_UID = 152 Process.FIRST_APPLICATION_UID; 153 private static final int MAX_APPLICATION_UIDS = 1000; 154 155 private static final boolean SHOW_INFO = false; 156 157 private static final boolean GET_CERTIFICATES = true; 158 159 private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; 160 161 private static final int REMOVE_EVENTS = 162 FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM; 163 private static final int ADD_EVENTS = 164 FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO; 165 166 private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS; 167 // Suffix used during package installation when copying/moving 168 // package apks to install directory. 169 private static final String INSTALL_PACKAGE_SUFFIX = "-"; 170 171 /** 172 * Indicates the state of installation. Used by PackageManager to 173 * figure out incomplete installations. Say a package is being installed 174 * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till 175 * the package installation is successful or unsuccesful lin which case 176 * the PackageManager will no longer maintain state information associated 177 * with the package. If some exception(like device freeze or battery being 178 * pulled out) occurs during installation of a package, the PackageManager 179 * needs this information to clean up the previously failed installation. 180 */ 181 private static final int PKG_INSTALL_INCOMPLETE = 0; 182 private static final int PKG_INSTALL_COMPLETE = 1; 183 184 static final int SCAN_MONITOR = 1<<0; 185 static final int SCAN_NO_DEX = 1<<1; 186 static final int SCAN_FORCE_DEX = 1<<2; 187 static final int SCAN_UPDATE_SIGNATURE = 1<<3; 188 static final int SCAN_NEW_INSTALL = 1<<4; 189 static final int SCAN_NO_PATHS = 1<<5; 190 static final int SCAN_UPDATE_TIME = 1<<6; 191 192 static final int REMOVE_CHATTY = 1<<16; 193 194 static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer"; 195 196 static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( 197 DEFAULT_CONTAINER_PACKAGE, 198 "com.android.defcontainer.DefaultContainerService"); 199 200 private static final String LIB_DIR_NAME = "lib"; 201 202 static final String mTempContainerPrefix = "smdl2tmp"; 203 204 final HandlerThread mHandlerThread = new HandlerThread("PackageManager", 205 Process.THREAD_PRIORITY_BACKGROUND); 206 final PackageHandler mHandler; 207 208 final int mSdkVersion = Build.VERSION.SDK_INT; 209 final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME) 210 ? null : Build.VERSION.CODENAME; 211 212 final Context mContext; 213 final boolean mFactoryTest; 214 final boolean mNoDexOpt; 215 final DisplayMetrics mMetrics; 216 final int mDefParseFlags; 217 final String[] mSeparateProcesses; 218 219 // This is where all application persistent data goes. 220 final File mAppDataDir; 221 222 // If Encrypted File System feature is enabled, all application persistent data 223 // should go here instead. 224 final File mSecureAppDataDir; 225 226 // This is the object monitoring the framework dir. 227 final FileObserver mFrameworkInstallObserver; 228 229 // This is the object monitoring the system app dir. 230 final FileObserver mSystemInstallObserver; 231 232 // This is the object monitoring the system app dir. 233 final FileObserver mVendorInstallObserver; 234 235 // This is the object monitoring mAppInstallDir. 236 final FileObserver mAppInstallObserver; 237 238 // This is the object monitoring mDrmAppPrivateInstallDir. 239 final FileObserver mDrmAppInstallObserver; 240 241 // Used for priviledge escalation. MUST NOT BE CALLED WITH mPackages 242 // LOCK HELD. Can be called with mInstallLock held. 243 final Installer mInstaller; 244 245 final File mFrameworkDir; 246 final File mSystemAppDir; 247 final File mVendorAppDir; 248 final File mAppInstallDir; 249 final File mDalvikCacheDir; 250 251 // Directory containing the private parts (e.g. code and non-resource assets) of forward-locked 252 // apps. 253 final File mDrmAppPrivateInstallDir; 254 255 // ---------------------------------------------------------------- 256 257 // Lock for state used when installing and doing other long running 258 // operations. Methods that must be called with this lock held have 259 // the prefix "LI". 260 final Object mInstallLock = new Object(); 261 262 // These are the directories in the 3rd party applications installed dir 263 // that we have currently loaded packages from. Keys are the application's 264 // installed zip file (absolute codePath), and values are Package. 265 final HashMap<String, PackageParser.Package> mAppDirs = 266 new HashMap<String, PackageParser.Package>(); 267 268 // Information for the parser to write more useful error messages. 269 File mScanningPath; 270 int mLastScanError; 271 272 final int[] mOutPermissions = new int[3]; 273 274 // ---------------------------------------------------------------- 275 276 // Keys are String (package name), values are Package. This also serves 277 // as the lock for the global state. Methods that must be called with 278 // this lock held have the prefix "LP". 279 final HashMap<String, PackageParser.Package> mPackages = 280 new HashMap<String, PackageParser.Package>(); 281 282 final Settings mSettings; 283 boolean mRestoredSettings; 284 285 // Group-ids that are given to all packages as read from etc/permissions/*.xml. 286 int[] mGlobalGids; 287 288 // These are the built-in uid -> permission mappings that were read from the 289 // etc/permissions.xml file. 290 final SparseArray<HashSet<String>> mSystemPermissions = 291 new SparseArray<HashSet<String>>(); 292 293 // These are the built-in shared libraries that were read from the 294 // etc/permissions.xml file. 295 final HashMap<String, String> mSharedLibraries = new HashMap<String, String>(); 296 297 // Temporary for building the final shared libraries for an .apk. 298 String[] mTmpSharedLibraries = null; 299 300 // These are the features this devices supports that were read from the 301 // etc/permissions.xml file. 302 final HashMap<String, FeatureInfo> mAvailableFeatures = 303 new HashMap<String, FeatureInfo>(); 304 305 // All available activities, for your resolving pleasure. 306 final ActivityIntentResolver mActivities = 307 new ActivityIntentResolver(); 308 309 // All available receivers, for your resolving pleasure. 310 final ActivityIntentResolver mReceivers = 311 new ActivityIntentResolver(); 312 313 // All available services, for your resolving pleasure. 314 final ServiceIntentResolver mServices = new ServiceIntentResolver(); 315 316 // Keys are String (provider class name), values are Provider. 317 final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent = 318 new HashMap<ComponentName, PackageParser.Provider>(); 319 320 // Mapping from provider base names (first directory in content URI codePath) 321 // to the provider information. 322 final HashMap<String, PackageParser.Provider> mProviders = 323 new HashMap<String, PackageParser.Provider>(); 324 325 // Mapping from instrumentation class names to info about them. 326 final HashMap<ComponentName, PackageParser.Instrumentation> mInstrumentation = 327 new HashMap<ComponentName, PackageParser.Instrumentation>(); 328 329 // Mapping from permission names to info about them. 330 final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups = 331 new HashMap<String, PackageParser.PermissionGroup>(); 332 333 // Packages whose data we have transfered into another package, thus 334 // should no longer exist. 335 final HashSet<String> mTransferedPackages = new HashSet<String>(); 336 337 // Broadcast actions that are only available to the system. 338 final HashSet<String> mProtectedBroadcasts = new HashSet<String>(); 339 340 boolean mSystemReady; 341 boolean mSafeMode; 342 boolean mHasSystemUidErrors; 343 344 ApplicationInfo mAndroidApplication; 345 final ActivityInfo mResolveActivity = new ActivityInfo(); 346 final ResolveInfo mResolveInfo = new ResolveInfo(); 347 ComponentName mResolveComponentName; 348 PackageParser.Package mPlatformPackage; 349 350 // Set of pending broadcasts for aggregating enable/disable of components. 351 final HashMap<String, ArrayList<String>> mPendingBroadcasts 352 = new HashMap<String, ArrayList<String>>(); 353 // Service Connection to remote media container service to copy 354 // package uri's from external media onto secure containers 355 // or internal storage. 356 private IMediaContainerService mContainerService = null; 357 358 static final int SEND_PENDING_BROADCAST = 1; 359 static final int MCS_BOUND = 3; 360 static final int END_COPY = 4; 361 static final int INIT_COPY = 5; 362 static final int MCS_UNBIND = 6; 363 static final int START_CLEANING_PACKAGE = 7; 364 static final int FIND_INSTALL_LOC = 8; 365 static final int POST_INSTALL = 9; 366 static final int MCS_RECONNECT = 10; 367 static final int MCS_GIVE_UP = 11; 368 static final int UPDATED_MEDIA_STATUS = 12; 369 static final int WRITE_SETTINGS = 13; 370 371 static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds 372 373 // Delay time in millisecs 374 static final int BROADCAST_DELAY = 10 * 1000; 375 final private DefaultContainerConnection mDefContainerConn = 376 new DefaultContainerConnection(); 377 class DefaultContainerConnection implements ServiceConnection { 378 public void onServiceConnected(ComponentName name, IBinder service) { 379 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceConnected"); 380 IMediaContainerService imcs = 381 IMediaContainerService.Stub.asInterface(service); 382 mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, imcs)); 383 } 384 385 public void onServiceDisconnected(ComponentName name) { 386 if (DEBUG_SD_INSTALL) Log.i(TAG, "onServiceDisconnected"); 387 } 388 }; 389 390 // Recordkeeping of restore-after-install operations that are currently in flight 391 // between the Package Manager and the Backup Manager 392 class PostInstallData { 393 public InstallArgs args; 394 public PackageInstalledInfo res; 395 396 PostInstallData(InstallArgs _a, PackageInstalledInfo _r) { 397 args = _a; 398 res = _r; 399 } 400 }; 401 final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>(); 402 int mNextInstallToken = 1; // nonzero; will be wrapped back to 1 when ++ overflows 403 404 class PackageHandler extends Handler { 405 private boolean mBound = false; 406 final ArrayList<HandlerParams> mPendingInstalls = 407 new ArrayList<HandlerParams>(); 408 409 private boolean connectToService() { 410 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to bind to" + 411 " DefaultContainerService"); 412 Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT); 413 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 414 if (mContext.bindService(service, mDefContainerConn, 415 Context.BIND_AUTO_CREATE)) { 416 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 417 mBound = true; 418 return true; 419 } 420 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 421 return false; 422 } 423 424 private void disconnectService() { 425 mContainerService = null; 426 mBound = false; 427 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 428 mContext.unbindService(mDefContainerConn); 429 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 430 } 431 432 PackageHandler(Looper looper) { 433 super(looper); 434 } 435 436 public void handleMessage(Message msg) { 437 try { 438 doHandleMessage(msg); 439 } finally { 440 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 441 } 442 } 443 444 void doHandleMessage(Message msg) { 445 switch (msg.what) { 446 case INIT_COPY: { 447 if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy"); 448 HandlerParams params = (HandlerParams) msg.obj; 449 int idx = mPendingInstalls.size(); 450 if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx); 451 // If a bind was already initiated we dont really 452 // need to do anything. The pending install 453 // will be processed later on. 454 if (!mBound) { 455 // If this is the only one pending we might 456 // have to bind to the service again. 457 if (!connectToService()) { 458 Slog.e(TAG, "Failed to bind to media container service"); 459 params.serviceError(); 460 return; 461 } else { 462 // Once we bind to the service, the first 463 // pending request will be processed. 464 mPendingInstalls.add(idx, params); 465 } 466 } else { 467 mPendingInstalls.add(idx, params); 468 // Already bound to the service. Just make 469 // sure we trigger off processing the first request. 470 if (idx == 0) { 471 mHandler.sendEmptyMessage(MCS_BOUND); 472 } 473 } 474 break; 475 } 476 case MCS_BOUND: { 477 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound"); 478 if (msg.obj != null) { 479 mContainerService = (IMediaContainerService) msg.obj; 480 } 481 if (mContainerService == null) { 482 // Something seriously wrong. Bail out 483 Slog.e(TAG, "Cannot bind to media container service"); 484 for (HandlerParams params : mPendingInstalls) { 485 mPendingInstalls.remove(0); 486 // Indicate service bind error 487 params.serviceError(); 488 } 489 mPendingInstalls.clear(); 490 } else if (mPendingInstalls.size() > 0) { 491 HandlerParams params = mPendingInstalls.get(0); 492 if (params != null) { 493 params.startCopy(); 494 } 495 } else { 496 // Should never happen ideally. 497 Slog.w(TAG, "Empty queue"); 498 } 499 break; 500 } 501 case MCS_RECONNECT : { 502 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect"); 503 if (mPendingInstalls.size() > 0) { 504 if (mBound) { 505 disconnectService(); 506 } 507 if (!connectToService()) { 508 Slog.e(TAG, "Failed to bind to media container service"); 509 for (HandlerParams params : mPendingInstalls) { 510 mPendingInstalls.remove(0); 511 // Indicate service bind error 512 params.serviceError(); 513 } 514 mPendingInstalls.clear(); 515 } 516 } 517 break; 518 } 519 case MCS_UNBIND : { 520 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind"); 521 // Delete pending install 522 if (mPendingInstalls.size() > 0) { 523 mPendingInstalls.remove(0); 524 } 525 if (mPendingInstalls.size() == 0) { 526 if (mBound) { 527 disconnectService(); 528 } 529 } else { 530 // There are more pending requests in queue. 531 // Just post MCS_BOUND message to trigger processing 532 // of next pending install. 533 mHandler.sendEmptyMessage(MCS_BOUND); 534 } 535 break; 536 } 537 case MCS_GIVE_UP: { 538 if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries"); 539 HandlerParams params = mPendingInstalls.remove(0); 540 break; 541 } 542 case SEND_PENDING_BROADCAST : { 543 String packages[]; 544 ArrayList components[]; 545 int size = 0; 546 int uids[]; 547 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 548 synchronized (mPackages) { 549 if (mPendingBroadcasts == null) { 550 return; 551 } 552 size = mPendingBroadcasts.size(); 553 if (size <= 0) { 554 // Nothing to be done. Just return 555 return; 556 } 557 packages = new String[size]; 558 components = new ArrayList[size]; 559 uids = new int[size]; 560 Iterator<HashMap.Entry<String, ArrayList<String>>> 561 it = mPendingBroadcasts.entrySet().iterator(); 562 int i = 0; 563 while (it.hasNext() && i < size) { 564 HashMap.Entry<String, ArrayList<String>> ent = it.next(); 565 packages[i] = ent.getKey(); 566 components[i] = ent.getValue(); 567 PackageSetting ps = mSettings.mPackages.get(ent.getKey()); 568 uids[i] = (ps != null) ? ps.userId : -1; 569 i++; 570 } 571 size = i; 572 mPendingBroadcasts.clear(); 573 } 574 // Send broadcasts 575 for (int i = 0; i < size; i++) { 576 sendPackageChangedBroadcast(packages[i], true, 577 (ArrayList<String>)components[i], uids[i]); 578 } 579 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 580 break; 581 } 582 case START_CLEANING_PACKAGE: { 583 String packageName = (String)msg.obj; 584 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 585 synchronized (mPackages) { 586 if (!mSettings.mPackagesToBeCleaned.contains(packageName)) { 587 mSettings.mPackagesToBeCleaned.add(packageName); 588 } 589 } 590 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 591 startCleaningPackages(); 592 } break; 593 case POST_INSTALL: { 594 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1); 595 PostInstallData data = mRunningInstalls.get(msg.arg1); 596 mRunningInstalls.delete(msg.arg1); 597 boolean deleteOld = false; 598 599 if (data != null) { 600 InstallArgs args = data.args; 601 PackageInstalledInfo res = data.res; 602 603 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { 604 res.removedInfo.sendBroadcast(false, true); 605 Bundle extras = new Bundle(1); 606 extras.putInt(Intent.EXTRA_UID, res.uid); 607 final boolean update = res.removedInfo.removedPackage != null; 608 if (update) { 609 extras.putBoolean(Intent.EXTRA_REPLACING, true); 610 } 611 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, 612 res.pkg.applicationInfo.packageName, 613 extras, null); 614 if (update) { 615 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, 616 res.pkg.applicationInfo.packageName, 617 extras, null); 618 } 619 if (res.removedInfo.args != null) { 620 // Remove the replaced package's older resources safely now 621 deleteOld = true; 622 } 623 } 624 // Force a gc to clear up things 625 Runtime.getRuntime().gc(); 626 // We delete after a gc for applications on sdcard. 627 if (deleteOld) { 628 synchronized (mInstallLock) { 629 res.removedInfo.args.doPostDeleteLI(true); 630 } 631 } 632 if (args.observer != null) { 633 try { 634 args.observer.packageInstalled(res.name, res.returnCode); 635 } catch (RemoteException e) { 636 Slog.i(TAG, "Observer no longer exists."); 637 } 638 } 639 } else { 640 Slog.e(TAG, "Bogus post-install token " + msg.arg1); 641 } 642 } break; 643 case UPDATED_MEDIA_STATUS: { 644 if (DEBUG_SD_INSTALL) Log.i(TAG, "Got message UPDATED_MEDIA_STATUS"); 645 boolean reportStatus = msg.arg1 == 1; 646 boolean doGc = msg.arg2 == 1; 647 if (DEBUG_SD_INSTALL) Log.i(TAG, "reportStatus=" + reportStatus + ", doGc = " + doGc); 648 if (doGc) { 649 // Force a gc to clear up stale containers. 650 Runtime.getRuntime().gc(); 651 } 652 if (msg.obj != null) { 653 Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj; 654 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers"); 655 // Unload containers 656 unloadAllContainers(args); 657 } 658 if (reportStatus) { 659 try { 660 if (DEBUG_SD_INSTALL) Log.i(TAG, "Invoking MountService call back"); 661 PackageHelper.getMountService().finishMediaUpdate(); 662 } catch (RemoteException e) { 663 Log.e(TAG, "MountService not running?"); 664 } 665 } 666 } break; 667 case WRITE_SETTINGS: { 668 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); 669 synchronized (mPackages) { 670 removeMessages(WRITE_SETTINGS); 671 mSettings.writeLP(); 672 } 673 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 674 } break; 675 } 676 } 677 } 678 679 void scheduleWriteSettingsLocked() { 680 if (!mHandler.hasMessages(WRITE_SETTINGS)) { 681 mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY); 682 } 683 } 684 685 static boolean installOnSd(int flags) { 686 if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) || 687 ((flags & PackageManager.INSTALL_INTERNAL) != 0)) { 688 return false; 689 } 690 if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) { 691 return true; 692 } 693 return false; 694 } 695 696 public static final IPackageManager main(Context context, boolean factoryTest) { 697 PackageManagerService m = new PackageManagerService(context, factoryTest); 698 ServiceManager.addService("package", m); 699 return m; 700 } 701 702 static String[] splitString(String str, char sep) { 703 int count = 1; 704 int i = 0; 705 while ((i=str.indexOf(sep, i)) >= 0) { 706 count++; 707 i++; 708 } 709 710 String[] res = new String[count]; 711 i=0; 712 count = 0; 713 int lastI=0; 714 while ((i=str.indexOf(sep, i)) >= 0) { 715 res[count] = str.substring(lastI, i); 716 count++; 717 i++; 718 lastI = i; 719 } 720 res[count] = str.substring(lastI, str.length()); 721 return res; 722 } 723 724 public PackageManagerService(Context context, boolean factoryTest) { 725 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, 726 SystemClock.uptimeMillis()); 727 728 if (mSdkVersion <= 0) { 729 Slog.w(TAG, "**** ro.build.version.sdk not set!"); 730 } 731 732 mContext = context; 733 mFactoryTest = factoryTest; 734 mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type")); 735 mMetrics = new DisplayMetrics(); 736 mSettings = new Settings(); 737 mSettings.addSharedUserLP("android.uid.system", 738 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM); 739 mSettings.addSharedUserLP("android.uid.phone", 740 MULTIPLE_APPLICATION_UIDS 741 ? RADIO_UID : FIRST_APPLICATION_UID, 742 ApplicationInfo.FLAG_SYSTEM); 743 mSettings.addSharedUserLP("android.uid.log", 744 MULTIPLE_APPLICATION_UIDS 745 ? LOG_UID : FIRST_APPLICATION_UID, 746 ApplicationInfo.FLAG_SYSTEM); 747 mSettings.addSharedUserLP("android.uid.nfc", 748 MULTIPLE_APPLICATION_UIDS 749 ? NFC_UID : FIRST_APPLICATION_UID, 750 ApplicationInfo.FLAG_SYSTEM); 751 752 String separateProcesses = SystemProperties.get("debug.separate_processes"); 753 if (separateProcesses != null && separateProcesses.length() > 0) { 754 if ("*".equals(separateProcesses)) { 755 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES; 756 mSeparateProcesses = null; 757 Slog.w(TAG, "Running with debug.separate_processes: * (ALL)"); 758 } else { 759 mDefParseFlags = 0; 760 mSeparateProcesses = separateProcesses.split(","); 761 Slog.w(TAG, "Running with debug.separate_processes: " 762 + separateProcesses); 763 } 764 } else { 765 mDefParseFlags = 0; 766 mSeparateProcesses = null; 767 } 768 769 Installer installer = new Installer(); 770 // Little hacky thing to check if installd is here, to determine 771 // whether we are running on the simulator and thus need to take 772 // care of building the /data file structure ourself. 773 // (apparently the sim now has a working installer) 774 if (installer.ping() && Process.supportsProcesses()) { 775 mInstaller = installer; 776 } else { 777 mInstaller = null; 778 } 779 780 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 781 Display d = wm.getDefaultDisplay(); 782 d.getMetrics(mMetrics); 783 784 synchronized (mInstallLock) { 785 synchronized (mPackages) { 786 mHandlerThread.start(); 787 mHandler = new PackageHandler(mHandlerThread.getLooper()); 788 789 File dataDir = Environment.getDataDirectory(); 790 mAppDataDir = new File(dataDir, "data"); 791 mSecureAppDataDir = new File(dataDir, "secure/data"); 792 mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); 793 794 if (mInstaller == null) { 795 // Make sure these dirs exist, when we are running in 796 // the simulator. 797 // Make a wide-open directory for random misc stuff. 798 File miscDir = new File(dataDir, "misc"); 799 miscDir.mkdirs(); 800 mAppDataDir.mkdirs(); 801 mSecureAppDataDir.mkdirs(); 802 mDrmAppPrivateInstallDir.mkdirs(); 803 } 804 805 readPermissions(); 806 807 mRestoredSettings = mSettings.readLP(); 808 long startTime = SystemClock.uptimeMillis(); 809 810 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, 811 startTime); 812 813 // Set flag to monitor and not change apk file paths when 814 // scanning install directories. 815 int scanMode = SCAN_MONITOR | SCAN_NO_PATHS; 816 if (mNoDexOpt) { 817 Slog.w(TAG, "Running ENG build: no pre-dexopt!"); 818 scanMode |= SCAN_NO_DEX; 819 } 820 821 final HashSet<String> libFiles = new HashSet<String>(); 822 823 mFrameworkDir = new File(Environment.getRootDirectory(), "framework"); 824 mDalvikCacheDir = new File(dataDir, "dalvik-cache"); 825 826 if (mInstaller != null) { 827 boolean didDexOpt = false; 828 829 /** 830 * Out of paranoia, ensure that everything in the boot class 831 * path has been dexed. 832 */ 833 String bootClassPath = System.getProperty("java.boot.class.path"); 834 if (bootClassPath != null) { 835 String[] paths = splitString(bootClassPath, ':'); 836 for (int i=0; i<paths.length; i++) { 837 try { 838 if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) { 839 libFiles.add(paths[i]); 840 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true); 841 didDexOpt = true; 842 } 843 } catch (FileNotFoundException e) { 844 Slog.w(TAG, "Boot class path not found: " + paths[i]); 845 } catch (IOException e) { 846 Slog.w(TAG, "Exception reading boot class path: " + paths[i], e); 847 } 848 } 849 } else { 850 Slog.w(TAG, "No BOOTCLASSPATH found!"); 851 } 852 853 /** 854 * Also ensure all external libraries have had dexopt run on them. 855 */ 856 if (mSharedLibraries.size() > 0) { 857 Iterator<String> libs = mSharedLibraries.values().iterator(); 858 while (libs.hasNext()) { 859 String lib = libs.next(); 860 try { 861 if (dalvik.system.DexFile.isDexOptNeeded(lib)) { 862 libFiles.add(lib); 863 mInstaller.dexopt(lib, Process.SYSTEM_UID, true); 864 didDexOpt = true; 865 } 866 } catch (FileNotFoundException e) { 867 Slog.w(TAG, "Library not found: " + lib); 868 } catch (IOException e) { 869 Slog.w(TAG, "Exception reading library: " + lib, e); 870 } 871 } 872 } 873 874 // Gross hack for now: we know this file doesn't contain any 875 // code, so don't dexopt it to avoid the resulting log spew. 876 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk"); 877 878 /** 879 * And there are a number of commands implemented in Java, which 880 * we currently need to do the dexopt on so that they can be 881 * run from a non-root shell. 882 */ 883 String[] frameworkFiles = mFrameworkDir.list(); 884 if (frameworkFiles != null) { 885 for (int i=0; i<frameworkFiles.length; i++) { 886 File libPath = new File(mFrameworkDir, frameworkFiles[i]); 887 String path = libPath.getPath(); 888 // Skip the file if we alrady did it. 889 if (libFiles.contains(path)) { 890 continue; 891 } 892 // Skip the file if it is not a type we want to dexopt. 893 if (!path.endsWith(".apk") && !path.endsWith(".jar")) { 894 continue; 895 } 896 try { 897 if (dalvik.system.DexFile.isDexOptNeeded(path)) { 898 mInstaller.dexopt(path, Process.SYSTEM_UID, true); 899 didDexOpt = true; 900 } 901 } catch (FileNotFoundException e) { 902 Slog.w(TAG, "Jar not found: " + path); 903 } catch (IOException e) { 904 Slog.w(TAG, "Exception reading jar: " + path, e); 905 } 906 } 907 } 908 909 if (didDexOpt) { 910 // If we had to do a dexopt of one of the previous 911 // things, then something on the system has changed. 912 // Consider this significant, and wipe away all other 913 // existing dexopt files to ensure we don't leave any 914 // dangling around. 915 String[] files = mDalvikCacheDir.list(); 916 if (files != null) { 917 for (int i=0; i<files.length; i++) { 918 String fn = files[i]; 919 if (fn.startsWith("data@app@") 920 || fn.startsWith("data@app-private@")) { 921 Slog.i(TAG, "Pruning dalvik file: " + fn); 922 (new File(mDalvikCacheDir, fn)).delete(); 923 } 924 } 925 } 926 } 927 } 928 929 // Find base frameworks (resource packages without code). 930 mFrameworkInstallObserver = new AppDirObserver( 931 mFrameworkDir.getPath(), OBSERVER_EVENTS, true); 932 mFrameworkInstallObserver.startWatching(); 933 scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM 934 | PackageParser.PARSE_IS_SYSTEM_DIR, 935 scanMode | SCAN_NO_DEX, 0); 936 937 // Collect all system packages. 938 mSystemAppDir = new File(Environment.getRootDirectory(), "app"); 939 mSystemInstallObserver = new AppDirObserver( 940 mSystemAppDir.getPath(), OBSERVER_EVENTS, true); 941 mSystemInstallObserver.startWatching(); 942 scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM 943 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); 944 945 // Collect all vendor packages. 946 mVendorAppDir = new File("/vendor/app"); 947 mVendorInstallObserver = new AppDirObserver( 948 mVendorAppDir.getPath(), OBSERVER_EVENTS, true); 949 mVendorInstallObserver.startWatching(); 950 scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM 951 | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0); 952 953 if (mInstaller != null) { 954 if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands"); 955 mInstaller.moveFiles(); 956 } 957 958 // Prune any system packages that no longer exist. 959 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); 960 while (psit.hasNext()) { 961 PackageSetting ps = psit.next(); 962 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 963 && !mPackages.containsKey(ps.name) 964 && !mSettings.mDisabledSysPackages.containsKey(ps.name)) { 965 psit.remove(); 966 String msg = "System package " + ps.name 967 + " no longer exists; wiping its data"; 968 reportSettingsProblem(Log.WARN, msg); 969 if (mInstaller != null) { 970 // XXX how to set useEncryptedFSDir for packages that 971 // are not encrypted? 972 mInstaller.remove(ps.name, true); 973 } 974 } 975 } 976 977 mAppInstallDir = new File(dataDir, "app"); 978 if (mInstaller == null) { 979 // Make sure these dirs exist, when we are running in 980 // the simulator. 981 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists 982 } 983 //look for any incomplete package installations 984 ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackages(); 985 //clean up list 986 for(int i = 0; i < deletePkgsList.size(); i++) { 987 //clean up here 988 cleanupInstallFailedPackage(deletePkgsList.get(i)); 989 } 990 //delete tmp files 991 deleteTempPackageFiles(); 992 993 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, 994 SystemClock.uptimeMillis()); 995 mAppInstallObserver = new AppDirObserver( 996 mAppInstallDir.getPath(), OBSERVER_EVENTS, false); 997 mAppInstallObserver.startWatching(); 998 scanDirLI(mAppInstallDir, 0, scanMode, 0); 999 1000 mDrmAppInstallObserver = new AppDirObserver( 1001 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false); 1002 mDrmAppInstallObserver.startWatching(); 1003 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, 1004 scanMode, 0); 1005 1006 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, 1007 SystemClock.uptimeMillis()); 1008 Slog.i(TAG, "Time to scan packages: " 1009 + ((SystemClock.uptimeMillis()-startTime)/1000f) 1010 + " seconds"); 1011 1012 // If the platform SDK has changed since the last time we booted, 1013 // we need to re-grant app permission to catch any new ones that 1014 // appear. This is really a hack, and means that apps can in some 1015 // cases get permissions that the user didn't initially explicitly 1016 // allow... it would be nice to have some better way to handle 1017 // this situation. 1018 final boolean regrantPermissions = mSettings.mInternalSdkPlatform 1019 != mSdkVersion; 1020 if (regrantPermissions) Slog.i(TAG, "Platform changed from " 1021 + mSettings.mInternalSdkPlatform + " to " + mSdkVersion 1022 + "; regranting permissions for internal storage"); 1023 mSettings.mInternalSdkPlatform = mSdkVersion; 1024 1025 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions); 1026 1027 mSettings.writeLP(); 1028 1029 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, 1030 SystemClock.uptimeMillis()); 1031 1032 // Now after opening every single application zip, make sure they 1033 // are all flushed. Not really needed, but keeps things nice and 1034 // tidy. 1035 Runtime.getRuntime().gc(); 1036 } // synchronized (mPackages) 1037 } // synchronized (mInstallLock) 1038 } 1039 1040 @Override 1041 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 1042 throws RemoteException { 1043 try { 1044 return super.onTransact(code, data, reply, flags); 1045 } catch (RuntimeException e) { 1046 if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) { 1047 Slog.e(TAG, "Package Manager Crash", e); 1048 } 1049 throw e; 1050 } 1051 } 1052 1053 void cleanupInstallFailedPackage(PackageSetting ps) { 1054 Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name); 1055 if (mInstaller != null) { 1056 boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg); 1057 int retCode = mInstaller.remove(ps.name, useSecureFS); 1058 if (retCode < 0) { 1059 Slog.w(TAG, "Couldn't remove app data directory for package: " 1060 + ps.name + ", retcode=" + retCode); 1061 } 1062 } else { 1063 //for emulator 1064 PackageParser.Package pkg = mPackages.get(ps.name); 1065 File dataDir = new File(pkg.applicationInfo.dataDir); 1066 dataDir.delete(); 1067 } 1068 if (ps.codePath != null) { 1069 if (!ps.codePath.delete()) { 1070 Slog.w(TAG, "Unable to remove old code file: " + ps.codePath); 1071 } 1072 } 1073 if (ps.resourcePath != null) { 1074 if (!ps.resourcePath.delete() && !ps.resourcePath.equals(ps.codePath)) { 1075 Slog.w(TAG, "Unable to remove old code file: " + ps.resourcePath); 1076 } 1077 } 1078 mSettings.removePackageLP(ps.name); 1079 } 1080 1081 void readPermissions() { 1082 // Read permissions from .../etc/permission directory. 1083 File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions"); 1084 if (!libraryDir.exists() || !libraryDir.isDirectory()) { 1085 Slog.w(TAG, "No directory " + libraryDir + ", skipping"); 1086 return; 1087 } 1088 if (!libraryDir.canRead()) { 1089 Slog.w(TAG, "Directory " + libraryDir + " cannot be read"); 1090 return; 1091 } 1092 1093 // Iterate over the files in the directory and scan .xml files 1094 for (File f : libraryDir.listFiles()) { 1095 // We'll read platform.xml last 1096 if (f.getPath().endsWith("etc/permissions/platform.xml")) { 1097 continue; 1098 } 1099 1100 if (!f.getPath().endsWith(".xml")) { 1101 Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring"); 1102 continue; 1103 } 1104 if (!f.canRead()) { 1105 Slog.w(TAG, "Permissions library file " + f + " cannot be read"); 1106 continue; 1107 } 1108 1109 readPermissionsFromXml(f); 1110 } 1111 1112 // Read permissions from .../etc/permissions/platform.xml last so it will take precedence 1113 final File permFile = new File(Environment.getRootDirectory(), 1114 "etc/permissions/platform.xml"); 1115 readPermissionsFromXml(permFile); 1116 } 1117 1118 private void readPermissionsFromXml(File permFile) { 1119 FileReader permReader = null; 1120 try { 1121 permReader = new FileReader(permFile); 1122 } catch (FileNotFoundException e) { 1123 Slog.w(TAG, "Couldn't find or open permissions file " + permFile); 1124 return; 1125 } 1126 1127 try { 1128 XmlPullParser parser = Xml.newPullParser(); 1129 parser.setInput(permReader); 1130 1131 XmlUtils.beginDocument(parser, "permissions"); 1132 1133 while (true) { 1134 XmlUtils.nextElement(parser); 1135 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) { 1136 break; 1137 } 1138 1139 String name = parser.getName(); 1140 if ("group".equals(name)) { 1141 String gidStr = parser.getAttributeValue(null, "gid"); 1142 if (gidStr != null) { 1143 int gid = Integer.parseInt(gidStr); 1144 mGlobalGids = appendInt(mGlobalGids, gid); 1145 } else { 1146 Slog.w(TAG, "<group> without gid at " 1147 + parser.getPositionDescription()); 1148 } 1149 1150 XmlUtils.skipCurrentTag(parser); 1151 continue; 1152 } else if ("permission".equals(name)) { 1153 String perm = parser.getAttributeValue(null, "name"); 1154 if (perm == null) { 1155 Slog.w(TAG, "<permission> without name at " 1156 + parser.getPositionDescription()); 1157 XmlUtils.skipCurrentTag(parser); 1158 continue; 1159 } 1160 perm = perm.intern(); 1161 readPermission(parser, perm); 1162 1163 } else if ("assign-permission".equals(name)) { 1164 String perm = parser.getAttributeValue(null, "name"); 1165 if (perm == null) { 1166 Slog.w(TAG, "<assign-permission> without name at " 1167 + parser.getPositionDescription()); 1168 XmlUtils.skipCurrentTag(parser); 1169 continue; 1170 } 1171 String uidStr = parser.getAttributeValue(null, "uid"); 1172 if (uidStr == null) { 1173 Slog.w(TAG, "<assign-permission> without uid at " 1174 + parser.getPositionDescription()); 1175 XmlUtils.skipCurrentTag(parser); 1176 continue; 1177 } 1178 int uid = Process.getUidForName(uidStr); 1179 if (uid < 0) { 1180 Slog.w(TAG, "<assign-permission> with unknown uid \"" 1181 + uidStr + "\" at " 1182 + parser.getPositionDescription()); 1183 XmlUtils.skipCurrentTag(parser); 1184 continue; 1185 } 1186 perm = perm.intern(); 1187 HashSet<String> perms = mSystemPermissions.get(uid); 1188 if (perms == null) { 1189 perms = new HashSet<String>(); 1190 mSystemPermissions.put(uid, perms); 1191 } 1192 perms.add(perm); 1193 XmlUtils.skipCurrentTag(parser); 1194 1195 } else if ("library".equals(name)) { 1196 String lname = parser.getAttributeValue(null, "name"); 1197 String lfile = parser.getAttributeValue(null, "file"); 1198 if (lname == null) { 1199 Slog.w(TAG, "<library> without name at " 1200 + parser.getPositionDescription()); 1201 } else if (lfile == null) { 1202 Slog.w(TAG, "<library> without file at " 1203 + parser.getPositionDescription()); 1204 } else { 1205 //Log.i(TAG, "Got library " + lname + " in " + lfile); 1206 mSharedLibraries.put(lname, lfile); 1207 } 1208 XmlUtils.skipCurrentTag(parser); 1209 continue; 1210 1211 } else if ("feature".equals(name)) { 1212 String fname = parser.getAttributeValue(null, "name"); 1213 if (fname == null) { 1214 Slog.w(TAG, "<feature> without name at " 1215 + parser.getPositionDescription()); 1216 } else { 1217 //Log.i(TAG, "Got feature " + fname); 1218 FeatureInfo fi = new FeatureInfo(); 1219 fi.name = fname; 1220 mAvailableFeatures.put(fname, fi); 1221 } 1222 XmlUtils.skipCurrentTag(parser); 1223 continue; 1224 1225 } else { 1226 XmlUtils.skipCurrentTag(parser); 1227 continue; 1228 } 1229 1230 } 1231 } catch (XmlPullParserException e) { 1232 Slog.w(TAG, "Got execption parsing permissions.", e); 1233 } catch (IOException e) { 1234 Slog.w(TAG, "Got execption parsing permissions.", e); 1235 } 1236 } 1237 1238 void readPermission(XmlPullParser parser, String name) 1239 throws IOException, XmlPullParserException { 1240 1241 name = name.intern(); 1242 1243 BasePermission bp = mSettings.mPermissions.get(name); 1244 if (bp == null) { 1245 bp = new BasePermission(name, null, BasePermission.TYPE_BUILTIN); 1246 mSettings.mPermissions.put(name, bp); 1247 } 1248 int outerDepth = parser.getDepth(); 1249 int type; 1250 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 1251 && (type != XmlPullParser.END_TAG 1252 || parser.getDepth() > outerDepth)) { 1253 if (type == XmlPullParser.END_TAG 1254 || type == XmlPullParser.TEXT) { 1255 continue; 1256 } 1257 1258 String tagName = parser.getName(); 1259 if ("group".equals(tagName)) { 1260 String gidStr = parser.getAttributeValue(null, "gid"); 1261 if (gidStr != null) { 1262 int gid = Process.getGidForName(gidStr); 1263 bp.gids = appendInt(bp.gids, gid); 1264 } else { 1265 Slog.w(TAG, "<group> without gid at " 1266 + parser.getPositionDescription()); 1267 } 1268 } 1269 XmlUtils.skipCurrentTag(parser); 1270 } 1271 } 1272 1273 static int[] appendInt(int[] cur, int val) { 1274 if (cur == null) { 1275 return new int[] { val }; 1276 } 1277 final int N = cur.length; 1278 for (int i=0; i<N; i++) { 1279 if (cur[i] == val) { 1280 return cur; 1281 } 1282 } 1283 int[] ret = new int[N+1]; 1284 System.arraycopy(cur, 0, ret, 0, N); 1285 ret[N] = val; 1286 return ret; 1287 } 1288 1289 static int[] appendInts(int[] cur, int[] add) { 1290 if (add == null) return cur; 1291 if (cur == null) return add; 1292 final int N = add.length; 1293 for (int i=0; i<N; i++) { 1294 cur = appendInt(cur, add[i]); 1295 } 1296 return cur; 1297 } 1298 1299 static int[] removeInt(int[] cur, int val) { 1300 if (cur == null) { 1301 return null; 1302 } 1303 final int N = cur.length; 1304 for (int i=0; i<N; i++) { 1305 if (cur[i] == val) { 1306 int[] ret = new int[N-1]; 1307 if (i > 0) { 1308 System.arraycopy(cur, 0, ret, 0, i); 1309 } 1310 if (i < (N-1)) { 1311 System.arraycopy(cur, i + 1, ret, i, N - i - 1); 1312 } 1313 return ret; 1314 } 1315 } 1316 return cur; 1317 } 1318 1319 static int[] removeInts(int[] cur, int[] rem) { 1320 if (rem == null) return cur; 1321 if (cur == null) return cur; 1322 final int N = rem.length; 1323 for (int i=0; i<N; i++) { 1324 cur = removeInt(cur, rem[i]); 1325 } 1326 return cur; 1327 } 1328 1329 PackageInfo generatePackageInfo(PackageParser.Package p, int flags) { 1330 if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { 1331 // The package has been uninstalled but has retained data and resources. 1332 return PackageParser.generatePackageInfo(p, null, flags, 0, 0); 1333 } 1334 final PackageSetting ps = (PackageSetting)p.mExtras; 1335 if (ps == null) { 1336 return null; 1337 } 1338 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps; 1339 return PackageParser.generatePackageInfo(p, gp.gids, flags, 1340 ps.firstInstallTime, ps.lastUpdateTime); 1341 } 1342 1343 public PackageInfo getPackageInfo(String packageName, int flags) { 1344 synchronized (mPackages) { 1345 PackageParser.Package p = mPackages.get(packageName); 1346 if (Config.LOGV) Log.v( 1347 TAG, "getPackageInfo " + packageName 1348 + ": " + p); 1349 if (p != null) { 1350 return generatePackageInfo(p, flags); 1351 } 1352 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { 1353 return generatePackageInfoFromSettingsLP(packageName, flags); 1354 } 1355 } 1356 return null; 1357 } 1358 1359 public String[] currentToCanonicalPackageNames(String[] names) { 1360 String[] out = new String[names.length]; 1361 synchronized (mPackages) { 1362 for (int i=names.length-1; i>=0; i--) { 1363 PackageSetting ps = mSettings.mPackages.get(names[i]); 1364 out[i] = ps != null && ps.realName != null ? ps.realName : names[i]; 1365 } 1366 } 1367 return out; 1368 } 1369 1370 public String[] canonicalToCurrentPackageNames(String[] names) { 1371 String[] out = new String[names.length]; 1372 synchronized (mPackages) { 1373 for (int i=names.length-1; i>=0; i--) { 1374 String cur = mSettings.mRenamedPackages.get(names[i]); 1375 out[i] = cur != null ? cur : names[i]; 1376 } 1377 } 1378 return out; 1379 } 1380 1381 public int getPackageUid(String packageName) { 1382 synchronized (mPackages) { 1383 PackageParser.Package p = mPackages.get(packageName); 1384 if(p != null) { 1385 return p.applicationInfo.uid; 1386 } 1387 PackageSetting ps = mSettings.mPackages.get(packageName); 1388 if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) { 1389 return -1; 1390 } 1391 p = ps.pkg; 1392 return p != null ? p.applicationInfo.uid : -1; 1393 } 1394 } 1395 1396 public int[] getPackageGids(String packageName) { 1397 synchronized (mPackages) { 1398 PackageParser.Package p = mPackages.get(packageName); 1399 if (Config.LOGV) Log.v( 1400 TAG, "getPackageGids" + packageName 1401 + ": " + p); 1402 if (p != null) { 1403 final PackageSetting ps = (PackageSetting)p.mExtras; 1404 final SharedUserSetting suid = ps.sharedUser; 1405 return suid != null ? suid.gids : ps.gids; 1406 } 1407 } 1408 // stupid thing to indicate an error. 1409 return new int[0]; 1410 } 1411 1412 static final PermissionInfo generatePermissionInfo( 1413 BasePermission bp, int flags) { 1414 if (bp.perm != null) { 1415 return PackageParser.generatePermissionInfo(bp.perm, flags); 1416 } 1417 PermissionInfo pi = new PermissionInfo(); 1418 pi.name = bp.name; 1419 pi.packageName = bp.sourcePackage; 1420 pi.nonLocalizedLabel = bp.name; 1421 pi.protectionLevel = bp.protectionLevel; 1422 return pi; 1423 } 1424 1425 public PermissionInfo getPermissionInfo(String name, int flags) { 1426 synchronized (mPackages) { 1427 final BasePermission p = mSettings.mPermissions.get(name); 1428 if (p != null) { 1429 return generatePermissionInfo(p, flags); 1430 } 1431 return null; 1432 } 1433 } 1434 1435 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) { 1436 synchronized (mPackages) { 1437 ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10); 1438 for (BasePermission p : mSettings.mPermissions.values()) { 1439 if (group == null) { 1440 if (p.perm == null || p.perm.info.group == null) { 1441 out.add(generatePermissionInfo(p, flags)); 1442 } 1443 } else { 1444 if (p.perm != null && group.equals(p.perm.info.group)) { 1445 out.add(PackageParser.generatePermissionInfo(p.perm, flags)); 1446 } 1447 } 1448 } 1449 1450 if (out.size() > 0) { 1451 return out; 1452 } 1453 return mPermissionGroups.containsKey(group) ? out : null; 1454 } 1455 } 1456 1457 public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) { 1458 synchronized (mPackages) { 1459 return PackageParser.generatePermissionGroupInfo( 1460 mPermissionGroups.get(name), flags); 1461 } 1462 } 1463 1464 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 1465 synchronized (mPackages) { 1466 final int N = mPermissionGroups.size(); 1467 ArrayList<PermissionGroupInfo> out 1468 = new ArrayList<PermissionGroupInfo>(N); 1469 for (PackageParser.PermissionGroup pg : mPermissionGroups.values()) { 1470 out.add(PackageParser.generatePermissionGroupInfo(pg, flags)); 1471 } 1472 return out; 1473 } 1474 } 1475 1476 private ApplicationInfo generateApplicationInfoFromSettingsLP(String packageName, int flags) { 1477 PackageSetting ps = mSettings.mPackages.get(packageName); 1478 if(ps != null) { 1479 if(ps.pkg == null) { 1480 PackageInfo pInfo = generatePackageInfoFromSettingsLP(packageName, flags); 1481 if(pInfo != null) { 1482 return pInfo.applicationInfo; 1483 } 1484 return null; 1485 } 1486 return PackageParser.generateApplicationInfo(ps.pkg, flags); 1487 } 1488 return null; 1489 } 1490 1491 private PackageInfo generatePackageInfoFromSettingsLP(String packageName, int flags) { 1492 PackageSetting ps = mSettings.mPackages.get(packageName); 1493 if(ps != null) { 1494 if(ps.pkg == null) { 1495 ps.pkg = new PackageParser.Package(packageName); 1496 ps.pkg.applicationInfo.packageName = packageName; 1497 ps.pkg.applicationInfo.flags = ps.pkgFlags; 1498 ps.pkg.applicationInfo.publicSourceDir = ps.resourcePathString; 1499 ps.pkg.applicationInfo.sourceDir = ps.codePathString; 1500 ps.pkg.applicationInfo.dataDir = getDataPathForPackage(ps.pkg).getPath(); 1501 ps.pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString; 1502 ps.pkg.mSetEnabled = ps.enabled; 1503 } 1504 return generatePackageInfo(ps.pkg, flags); 1505 } 1506 return null; 1507 } 1508 1509 public ApplicationInfo getApplicationInfo(String packageName, int flags) { 1510 synchronized (mPackages) { 1511 PackageParser.Package p = mPackages.get(packageName); 1512 if (Config.LOGV) Log.v( 1513 TAG, "getApplicationInfo " + packageName 1514 + ": " + p); 1515 if (p != null) { 1516 // Note: isEnabledLP() does not apply here - always return info 1517 return PackageParser.generateApplicationInfo(p, flags); 1518 } 1519 if ("android".equals(packageName)||"system".equals(packageName)) { 1520 return mAndroidApplication; 1521 } 1522 if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { 1523 return generateApplicationInfoFromSettingsLP(packageName, flags); 1524 } 1525 } 1526 return null; 1527 } 1528 1529 1530 public void freeStorageAndNotify(final long freeStorageSize, final IPackageDataObserver observer) { 1531 mContext.enforceCallingOrSelfPermission( 1532 android.Manifest.permission.CLEAR_APP_CACHE, null); 1533 // Queue up an async operation since clearing cache may take a little while. 1534 mHandler.post(new Runnable() { 1535 public void run() { 1536 mHandler.removeCallbacks(this); 1537 int retCode = -1; 1538 if (mInstaller != null) { 1539 retCode = mInstaller.freeCache(freeStorageSize); 1540 if (retCode < 0) { 1541 Slog.w(TAG, "Couldn't clear application caches"); 1542 } 1543 } //end if mInstaller 1544 if (observer != null) { 1545 try { 1546 observer.onRemoveCompleted(null, (retCode >= 0)); 1547 } catch (RemoteException e) { 1548 Slog.w(TAG, "RemoveException when invoking call back"); 1549 } 1550 } 1551 } 1552 }); 1553 } 1554 1555 public void freeStorage(final long freeStorageSize, final IntentSender pi) { 1556 mContext.enforceCallingOrSelfPermission( 1557 android.Manifest.permission.CLEAR_APP_CACHE, null); 1558 // Queue up an async operation since clearing cache may take a little while. 1559 mHandler.post(new Runnable() { 1560 public void run() { 1561 mHandler.removeCallbacks(this); 1562 int retCode = -1; 1563 if (mInstaller != null) { 1564 retCode = mInstaller.freeCache(freeStorageSize); 1565 if (retCode < 0) { 1566 Slog.w(TAG, "Couldn't clear application caches"); 1567 } 1568 } 1569 if(pi != null) { 1570 try { 1571 // Callback via pending intent 1572 int code = (retCode >= 0) ? 1 : 0; 1573 pi.sendIntent(null, code, null, 1574 null, null); 1575 } catch (SendIntentException e1) { 1576 Slog.i(TAG, "Failed to send pending intent"); 1577 } 1578 } 1579 } 1580 }); 1581 } 1582 1583 public ActivityInfo getActivityInfo(ComponentName component, int flags) { 1584 synchronized (mPackages) { 1585 PackageParser.Activity a = mActivities.mActivities.get(component); 1586 1587 if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a); 1588 if (a != null && mSettings.isEnabledLP(a.info, flags)) { 1589 return PackageParser.generateActivityInfo(a, flags); 1590 } 1591 if (mResolveComponentName.equals(component)) { 1592 return mResolveActivity; 1593 } 1594 } 1595 return null; 1596 } 1597 1598 public ActivityInfo getReceiverInfo(ComponentName component, int flags) { 1599 synchronized (mPackages) { 1600 PackageParser.Activity a = mReceivers.mActivities.get(component); 1601 if (Config.LOGV) Log.v( 1602 TAG, "getReceiverInfo " + component + ": " + a); 1603 if (a != null && mSettings.isEnabledLP(a.info, flags)) { 1604 return PackageParser.generateActivityInfo(a, flags); 1605 } 1606 } 1607 return null; 1608 } 1609 1610 public ServiceInfo getServiceInfo(ComponentName component, int flags) { 1611 synchronized (mPackages) { 1612 PackageParser.Service s = mServices.mServices.get(component); 1613 if (Config.LOGV) Log.v( 1614 TAG, "getServiceInfo " + component + ": " + s); 1615 if (s != null && mSettings.isEnabledLP(s.info, flags)) { 1616 return PackageParser.generateServiceInfo(s, flags); 1617 } 1618 } 1619 return null; 1620 } 1621 1622 public ProviderInfo getProviderInfo(ComponentName component, int flags) { 1623 synchronized (mPackages) { 1624 PackageParser.Provider p = mProvidersByComponent.get(component); 1625 if (Config.LOGV) Log.v( 1626 TAG, "getProviderInfo " + component + ": " + p); 1627 if (p != null && mSettings.isEnabledLP(p.info, flags)) { 1628 return PackageParser.generateProviderInfo(p, flags); 1629 } 1630 } 1631 return null; 1632 } 1633 1634 public String[] getSystemSharedLibraryNames() { 1635 Set<String> libSet; 1636 synchronized (mPackages) { 1637 libSet = mSharedLibraries.keySet(); 1638 int size = libSet.size(); 1639 if (size > 0) { 1640 String[] libs = new String[size]; 1641 libSet.toArray(libs); 1642 return libs; 1643 } 1644 } 1645 return null; 1646 } 1647 1648 public FeatureInfo[] getSystemAvailableFeatures() { 1649 Collection<FeatureInfo> featSet; 1650 synchronized (mPackages) { 1651 featSet = mAvailableFeatures.values(); 1652 int size = featSet.size(); 1653 if (size > 0) { 1654 FeatureInfo[] features = new FeatureInfo[size+1]; 1655 featSet.toArray(features); 1656 FeatureInfo fi = new FeatureInfo(); 1657 fi.reqGlEsVersion = SystemProperties.getInt("ro.opengles.version", 1658 FeatureInfo.GL_ES_VERSION_UNDEFINED); 1659 features[size] = fi; 1660 return features; 1661 } 1662 } 1663 return null; 1664 } 1665 1666 public boolean hasSystemFeature(String name) { 1667 synchronized (mPackages) { 1668 return mAvailableFeatures.containsKey(name); 1669 } 1670 } 1671 1672 public int checkPermission(String permName, String pkgName) { 1673 synchronized (mPackages) { 1674 PackageParser.Package p = mPackages.get(pkgName); 1675 if (p != null && p.mExtras != null) { 1676 PackageSetting ps = (PackageSetting)p.mExtras; 1677 if (ps.sharedUser != null) { 1678 if (ps.sharedUser.grantedPermissions.contains(permName)) { 1679 return PackageManager.PERMISSION_GRANTED; 1680 } 1681 } else if (ps.grantedPermissions.contains(permName)) { 1682 return PackageManager.PERMISSION_GRANTED; 1683 } 1684 } 1685 } 1686 return PackageManager.PERMISSION_DENIED; 1687 } 1688 1689 public int checkUidPermission(String permName, int uid) { 1690 synchronized (mPackages) { 1691 Object obj = mSettings.getUserIdLP(uid); 1692 if (obj != null) { 1693 GrantedPermissions gp = (GrantedPermissions)obj; 1694 if (gp.grantedPermissions.contains(permName)) { 1695 return PackageManager.PERMISSION_GRANTED; 1696 } 1697 } else { 1698 HashSet<String> perms = mSystemPermissions.get(uid); 1699 if (perms != null && perms.contains(permName)) { 1700 return PackageManager.PERMISSION_GRANTED; 1701 } 1702 } 1703 } 1704 return PackageManager.PERMISSION_DENIED; 1705 } 1706 1707 private BasePermission findPermissionTreeLP(String permName) { 1708 for(BasePermission bp : mSettings.mPermissionTrees.values()) { 1709 if (permName.startsWith(bp.name) && 1710 permName.length() > bp.name.length() && 1711 permName.charAt(bp.name.length()) == '.') { 1712 return bp; 1713 } 1714 } 1715 return null; 1716 } 1717 1718 private BasePermission checkPermissionTreeLP(String permName) { 1719 if (permName != null) { 1720 BasePermission bp = findPermissionTreeLP(permName); 1721 if (bp != null) { 1722 if (bp.uid == Binder.getCallingUid()) { 1723 return bp; 1724 } 1725 throw new SecurityException("Calling uid " 1726 + Binder.getCallingUid() 1727 + " is not allowed to add to permission tree " 1728 + bp.name + " owned by uid " + bp.uid); 1729 } 1730 } 1731 throw new SecurityException("No permission tree found for " + permName); 1732 } 1733 1734 static boolean compareStrings(CharSequence s1, CharSequence s2) { 1735 if (s1 == null) { 1736 return s2 == null; 1737 } 1738 if (s2 == null) { 1739 return false; 1740 } 1741 if (s1.getClass() != s2.getClass()) { 1742 return false; 1743 } 1744 return s1.equals(s2); 1745 } 1746 1747 static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) { 1748 if (pi1.icon != pi2.icon) return false; 1749 if (pi1.logo != pi2.logo) return false; 1750 if (pi1.protectionLevel != pi2.protectionLevel) return false; 1751 if (!compareStrings(pi1.name, pi2.name)) return false; 1752 if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; 1753 // We'll take care of setting this one. 1754 if (!compareStrings(pi1.packageName, pi2.packageName)) return false; 1755 // These are not currently stored in settings. 1756 //if (!compareStrings(pi1.group, pi2.group)) return false; 1757 //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; 1758 //if (pi1.labelRes != pi2.labelRes) return false; 1759 //if (pi1.descriptionRes != pi2.descriptionRes) return false; 1760 return true; 1761 } 1762 1763 boolean addPermissionLocked(PermissionInfo info, boolean async) { 1764 if (info.labelRes == 0 && info.nonLocalizedLabel == null) { 1765 throw new SecurityException("Label must be specified in permission"); 1766 } 1767 BasePermission tree = checkPermissionTreeLP(info.name); 1768 BasePermission bp = mSettings.mPermissions.get(info.name); 1769 boolean added = bp == null; 1770 boolean changed = true; 1771 if (added) { 1772 bp = new BasePermission(info.name, tree.sourcePackage, 1773 BasePermission.TYPE_DYNAMIC); 1774 } else if (bp.type != BasePermission.TYPE_DYNAMIC) { 1775 throw new SecurityException( 1776 "Not allowed to modify non-dynamic permission " 1777 + info.name); 1778 } else { 1779 if (bp.protectionLevel == info.protectionLevel 1780 && bp.perm.owner.equals(tree.perm.owner) 1781 && bp.uid == tree.uid 1782 && comparePermissionInfos(bp.perm.info, info)) { 1783 changed = false; 1784 } 1785 } 1786 bp.protectionLevel = info.protectionLevel; 1787 bp.perm = new PackageParser.Permission(tree.perm.owner, 1788 new PermissionInfo(info)); 1789 bp.perm.info.packageName = tree.perm.info.packageName; 1790 bp.uid = tree.uid; 1791 if (added) { 1792 mSettings.mPermissions.put(info.name, bp); 1793 } 1794 if (changed) { 1795 if (!async) { 1796 mSettings.writeLP(); 1797 } else { 1798 scheduleWriteSettingsLocked(); 1799 } 1800 } 1801 return added; 1802 } 1803 1804 public boolean addPermission(PermissionInfo info) { 1805 synchronized (mPackages) { 1806 return addPermissionLocked(info, false); 1807 } 1808 } 1809 1810 public boolean addPermissionAsync(PermissionInfo info) { 1811 synchronized (mPackages) { 1812 return addPermissionLocked(info, true); 1813 } 1814 } 1815 1816 public void removePermission(String name) { 1817 synchronized (mPackages) { 1818 checkPermissionTreeLP(name); 1819 BasePermission bp = mSettings.mPermissions.get(name); 1820 if (bp != null) { 1821 if (bp.type != BasePermission.TYPE_DYNAMIC) { 1822 throw new SecurityException( 1823 "Not allowed to modify non-dynamic permission " 1824 + name); 1825 } 1826 mSettings.mPermissions.remove(name); 1827 mSettings.writeLP(); 1828 } 1829 } 1830 } 1831 1832 public boolean isProtectedBroadcast(String actionName) { 1833 synchronized (mPackages) { 1834 return mProtectedBroadcasts.contains(actionName); 1835 } 1836 } 1837 1838 public int checkSignatures(String pkg1, String pkg2) { 1839 synchronized (mPackages) { 1840 PackageParser.Package p1 = mPackages.get(pkg1); 1841 PackageParser.Package p2 = mPackages.get(pkg2); 1842 if (p1 == null || p1.mExtras == null 1843 || p2 == null || p2.mExtras == null) { 1844 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 1845 } 1846 return checkSignaturesLP(p1.mSignatures, p2.mSignatures); 1847 } 1848 } 1849 1850 public int checkUidSignatures(int uid1, int uid2) { 1851 synchronized (mPackages) { 1852 Signature[] s1; 1853 Signature[] s2; 1854 Object obj = mSettings.getUserIdLP(uid1); 1855 if (obj != null) { 1856 if (obj instanceof SharedUserSetting) { 1857 s1 = ((SharedUserSetting)obj).signatures.mSignatures; 1858 } else if (obj instanceof PackageSetting) { 1859 s1 = ((PackageSetting)obj).signatures.mSignatures; 1860 } else { 1861 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 1862 } 1863 } else { 1864 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 1865 } 1866 obj = mSettings.getUserIdLP(uid2); 1867 if (obj != null) { 1868 if (obj instanceof SharedUserSetting) { 1869 s2 = ((SharedUserSetting)obj).signatures.mSignatures; 1870 } else if (obj instanceof PackageSetting) { 1871 s2 = ((PackageSetting)obj).signatures.mSignatures; 1872 } else { 1873 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 1874 } 1875 } else { 1876 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; 1877 } 1878 return checkSignaturesLP(s1, s2); 1879 } 1880 } 1881 1882 int checkSignaturesLP(Signature[] s1, Signature[] s2) { 1883 if (s1 == null) { 1884 return s2 == null 1885 ? PackageManager.SIGNATURE_NEITHER_SIGNED 1886 : PackageManager.SIGNATURE_FIRST_NOT_SIGNED; 1887 } 1888 if (s2 == null) { 1889 return PackageManager.SIGNATURE_SECOND_NOT_SIGNED; 1890 } 1891 HashSet<Signature> set1 = new HashSet<Signature>(); 1892 for (Signature sig : s1) { 1893 set1.add(sig); 1894 } 1895 HashSet<Signature> set2 = new HashSet<Signature>(); 1896 for (Signature sig : s2) { 1897 set2.add(sig); 1898 } 1899 // Make sure s2 contains all signatures in s1. 1900 if (set1.equals(set2)) { 1901 return PackageManager.SIGNATURE_MATCH; 1902 } 1903 return PackageManager.SIGNATURE_NO_MATCH; 1904 } 1905 1906 public String[] getPackagesForUid(int uid) { 1907 synchronized (mPackages) { 1908 Object obj = mSettings.getUserIdLP(uid); 1909 if (obj instanceof SharedUserSetting) { 1910 SharedUserSetting sus = (SharedUserSetting)obj; 1911 final int N = sus.packages.size(); 1912 String[] res = new String[N]; 1913 Iterator<PackageSetting> it = sus.packages.iterator(); 1914 int i=0; 1915 while (it.hasNext()) { 1916 res[i++] = it.next().name; 1917 } 1918 return res; 1919 } else if (obj instanceof PackageSetting) { 1920 PackageSetting ps = (PackageSetting)obj; 1921 return new String[] { ps.name }; 1922 } 1923 } 1924 return null; 1925 } 1926 1927 public String getNameForUid(int uid) { 1928 synchronized (mPackages) { 1929 Object obj = mSettings.getUserIdLP(uid); 1930 if (obj instanceof SharedUserSetting) { 1931 SharedUserSetting sus = (SharedUserSetting)obj; 1932 return sus.name + ":" + sus.userId; 1933 } else if (obj instanceof PackageSetting) { 1934 PackageSetting ps = (PackageSetting)obj; 1935 return ps.name; 1936 } 1937 } 1938 return null; 1939 } 1940 1941 public int getUidForSharedUser(String sharedUserName) { 1942 if(sharedUserName == null) { 1943 return -1; 1944 } 1945 synchronized (mPackages) { 1946 SharedUserSetting suid = mSettings.getSharedUserLP(sharedUserName, 0, false); 1947 if(suid == null) { 1948 return -1; 1949 } 1950 return suid.userId; 1951 } 1952 } 1953 1954 public ResolveInfo resolveIntent(Intent intent, String resolvedType, 1955 int flags) { 1956 List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags); 1957 return chooseBestActivity(intent, resolvedType, flags, query); 1958 } 1959 1960 private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, 1961 int flags, List<ResolveInfo> query) { 1962 if (query != null) { 1963 final int N = query.size(); 1964 if (N == 1) { 1965 return query.get(0); 1966 } else if (N > 1) { 1967 // If there is more than one activity with the same priority, 1968 // then let the user decide between them. 1969 ResolveInfo r0 = query.get(0); 1970 ResolveInfo r1 = query.get(1); 1971 if (false) { 1972 System.out.println(r0.activityInfo.name + 1973 "=" + r0.priority + " vs " + 1974 r1.activityInfo.name + 1975 "=" + r1.priority); 1976 } 1977 // If the first activity has a higher priority, or a different 1978 // default, then it is always desireable to pick it. 1979 if (r0.priority != r1.priority 1980 || r0.preferredOrder != r1.preferredOrder 1981 || r0.isDefault != r1.isDefault) { 1982 return query.get(0); 1983 } 1984 // If we have saved a preference for a preferred activity for 1985 // this Intent, use that. 1986 ResolveInfo ri = findPreferredActivity(intent, resolvedType, 1987 flags, query, r0.priority); 1988 if (ri != null) { 1989 return ri; 1990 } 1991 return mResolveInfo; 1992 } 1993 } 1994 return null; 1995 } 1996 1997 ResolveInfo findPreferredActivity(Intent intent, String resolvedType, 1998 int flags, List<ResolveInfo> query, int priority) { 1999 synchronized (mPackages) { 2000 if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION); 2001 List<PreferredActivity> prefs = 2002 mSettings.mPreferredActivities.queryIntent(intent, resolvedType, 2003 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0); 2004 if (prefs != null && prefs.size() > 0) { 2005 // First figure out how good the original match set is. 2006 // We will only allow preferred activities that came 2007 // from the same match quality. 2008 int match = 0; 2009 final int N = query.size(); 2010 if (DEBUG_PREFERRED) Log.v(TAG, "Figuring out best match..."); 2011 for (int j=0; j<N; j++) { 2012 ResolveInfo ri = query.get(j); 2013 if (DEBUG_PREFERRED) Log.v(TAG, "Match for " + ri.activityInfo 2014 + ": 0x" + Integer.toHexString(match)); 2015 if (ri.match > match) match = ri.match; 2016 } 2017 if (DEBUG_PREFERRED) Log.v(TAG, "Best match: 0x" 2018 + Integer.toHexString(match)); 2019 match &= IntentFilter.MATCH_CATEGORY_MASK; 2020 final int M = prefs.size(); 2021 for (int i=0; i<M; i++) { 2022 PreferredActivity pa = prefs.get(i); 2023 if (pa.mMatch != match) { 2024 continue; 2025 } 2026 ActivityInfo ai = getActivityInfo(pa.mActivity, flags); 2027 if (DEBUG_PREFERRED) { 2028 Log.v(TAG, "Got preferred activity:"); 2029 if (ai != null) { 2030 ai.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 2031 } else { 2032 Log.v(TAG, " null"); 2033 } 2034 } 2035 if (ai != null) { 2036 for (int j=0; j<N; j++) { 2037 ResolveInfo ri = query.get(j); 2038 if (!ri.activityInfo.applicationInfo.packageName 2039 .equals(ai.applicationInfo.packageName)) { 2040 continue; 2041 } 2042 if (!ri.activityInfo.name.equals(ai.name)) { 2043 continue; 2044 } 2045 2046 // Okay we found a previously set preferred app. 2047 // If the result set is different from when this 2048 // was created, we need to clear it and re-ask the 2049 // user their preference. 2050 if (!pa.sameSet(query, priority)) { 2051 Slog.i(TAG, "Result set changed, dropping preferred activity for " 2052 + intent + " type " + resolvedType); 2053 mSettings.mPreferredActivities.removeFilter(pa); 2054 return null; 2055 } 2056 2057 // Yay! 2058 return ri; 2059 } 2060 } 2061 } 2062 } 2063 } 2064 return null; 2065 } 2066 2067 public List<ResolveInfo> queryIntentActivities(Intent intent, 2068 String resolvedType, int flags) { 2069 ComponentName comp = intent.getComponent(); 2070 if (comp != null) { 2071 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); 2072 ActivityInfo ai = getActivityInfo(comp, flags); 2073 if (ai != null) { 2074 ResolveInfo ri = new ResolveInfo(); 2075 ri.activityInfo = ai; 2076 list.add(ri); 2077 } 2078 return list; 2079 } 2080 2081 synchronized (mPackages) { 2082 String pkgName = intent.getPackage(); 2083 if (pkgName == null) { 2084 return (List<ResolveInfo>)mActivities.queryIntent(intent, 2085 resolvedType, flags); 2086 } 2087 PackageParser.Package pkg = mPackages.get(pkgName); 2088 if (pkg != null) { 2089 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent, 2090 resolvedType, flags, pkg.activities); 2091 } 2092 return null; 2093 } 2094 } 2095 2096 public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, 2097 Intent[] specifics, String[] specificTypes, Intent intent, 2098 String resolvedType, int flags) { 2099 final String resultsAction = intent.getAction(); 2100 2101 List<ResolveInfo> results = queryIntentActivities( 2102 intent, resolvedType, flags|PackageManager.GET_RESOLVED_FILTER); 2103 if (Config.LOGV) Log.v(TAG, "Query " + intent + ": " + results); 2104 2105 int specificsPos = 0; 2106 int N; 2107 2108 // todo: note that the algorithm used here is O(N^2). This 2109 // isn't a problem in our current environment, but if we start running 2110 // into situations where we have more than 5 or 10 matches then this 2111 // should probably be changed to something smarter... 2112 2113 // First we go through and resolve each of the specific items 2114 // that were supplied, taking care of removing any corresponding 2115 // duplicate items in the generic resolve list. 2116 if (specifics != null) { 2117 for (int i=0; i<specifics.length; i++) { 2118 final Intent sintent = specifics[i]; 2119 if (sintent == null) { 2120 continue; 2121 } 2122 2123 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + sintent); 2124 String action = sintent.getAction(); 2125 if (resultsAction != null && resultsAction.equals(action)) { 2126 // If this action was explicitly requested, then don't 2127 // remove things that have it. 2128 action = null; 2129 } 2130 ComponentName comp = sintent.getComponent(); 2131 ResolveInfo ri = null; 2132 ActivityInfo ai = null; 2133 if (comp == null) { 2134 ri = resolveIntent( 2135 sintent, 2136 specificTypes != null ? specificTypes[i] : null, 2137 flags); 2138 if (ri == null) { 2139 continue; 2140 } 2141 if (ri == mResolveInfo) { 2142 // ACK! Must do something better with this. 2143 } 2144 ai = ri.activityInfo; 2145 comp = new ComponentName(ai.applicationInfo.packageName, 2146 ai.name); 2147 } else { 2148 ai = getActivityInfo(comp, flags); 2149 if (ai == null) { 2150 continue; 2151 } 2152 } 2153 2154 // Look for any generic query activities that are duplicates 2155 // of this specific one, and remove them from the results. 2156 if (Config.LOGV) Log.v(TAG, "Specific #" + i + ": " + ai); 2157 N = results.size(); 2158 int j; 2159 for (j=specificsPos; j<N; j++) { 2160 ResolveInfo sri = results.get(j); 2161 if ((sri.activityInfo.name.equals(comp.getClassName()) 2162 && sri.activityInfo.applicationInfo.packageName.equals( 2163 comp.getPackageName())) 2164 || (action != null && sri.filter.matchAction(action))) { 2165 results.remove(j); 2166 if (Config.LOGV) Log.v( 2167 TAG, "Removing duplicate item from " + j 2168 + " due to specific " + specificsPos); 2169 if (ri == null) { 2170 ri = sri; 2171 } 2172 j--; 2173 N--; 2174 } 2175 } 2176 2177 // Add this specific item to its proper place. 2178 if (ri == null) { 2179 ri = new ResolveInfo(); 2180 ri.activityInfo = ai; 2181 } 2182 results.add(specificsPos, ri); 2183 ri.specificIndex = i; 2184 specificsPos++; 2185 } 2186 } 2187 2188 // Now we go through the remaining generic results and remove any 2189 // duplicate actions that are found here. 2190 N = results.size(); 2191 for (int i=specificsPos; i<N-1; i++) { 2192 final ResolveInfo rii = results.get(i); 2193 if (rii.filter == null) { 2194 continue; 2195 } 2196 2197 // Iterate over all of the actions of this result's intent 2198 // filter... typically this should be just one. 2199 final Iterator<String> it = rii.filter.actionsIterator(); 2200 if (it == null) { 2201 continue; 2202 } 2203 while (it.hasNext()) { 2204 final String action = it.next(); 2205 if (resultsAction != null && resultsAction.equals(action)) { 2206 // If this action was explicitly requested, then don't 2207 // remove things that have it. 2208 continue; 2209 } 2210 for (int j=i+1; j<N; j++) { 2211 final ResolveInfo rij = results.get(j); 2212 if (rij.filter != null && rij.filter.hasAction(action)) { 2213 results.remove(j); 2214 if (Config.LOGV) Log.v( 2215 TAG, "Removing duplicate item from " + j 2216 + " due to action " + action + " at " + i); 2217 j--; 2218 N--; 2219 } 2220 } 2221 } 2222 2223 // If the caller didn't request filter information, drop it now 2224 // so we don't have to marshall/unmarshall it. 2225 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) { 2226 rii.filter = null; 2227 } 2228 } 2229 2230 // Filter out the caller activity if so requested. 2231 if (caller != null) { 2232 N = results.size(); 2233 for (int i=0; i<N; i++) { 2234 ActivityInfo ainfo = results.get(i).activityInfo; 2235 if (caller.getPackageName().equals(ainfo.applicationInfo.packageName) 2236 && caller.getClassName().equals(ainfo.name)) { 2237 results.remove(i); 2238 break; 2239 } 2240 } 2241 } 2242 2243 // If the caller didn't request filter information, 2244 // drop them now so we don't have to 2245 // marshall/unmarshall it. 2246 if ((flags&PackageManager.GET_RESOLVED_FILTER) == 0) { 2247 N = results.size(); 2248 for (int i=0; i<N; i++) { 2249 results.get(i).filter = null; 2250 } 2251 } 2252 2253 if (Config.LOGV) Log.v(TAG, "Result: " + results); 2254 return results; 2255 } 2256 2257 public List<ResolveInfo> queryIntentReceivers(Intent intent, 2258 String resolvedType, int flags) { 2259 ComponentName comp = intent.getComponent(); 2260 if (comp != null) { 2261 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); 2262 ActivityInfo ai = getReceiverInfo(comp, flags); 2263 if (ai != null) { 2264 ResolveInfo ri = new ResolveInfo(); 2265 ri.activityInfo = ai; 2266 list.add(ri); 2267 } 2268 return list; 2269 } 2270 2271 synchronized (mPackages) { 2272 String pkgName = intent.getPackage(); 2273 if (pkgName == null) { 2274 return (List<ResolveInfo>)mReceivers.queryIntent(intent, 2275 resolvedType, flags); 2276 } 2277 PackageParser.Package pkg = mPackages.get(pkgName); 2278 if (pkg != null) { 2279 return (List<ResolveInfo>) mReceivers.queryIntentForPackage(intent, 2280 resolvedType, flags, pkg.receivers); 2281 } 2282 return null; 2283 } 2284 } 2285 2286 public ResolveInfo resolveService(Intent intent, String resolvedType, 2287 int flags) { 2288 List<ResolveInfo> query = queryIntentServices(intent, resolvedType, 2289 flags); 2290 if (query != null) { 2291 if (query.size() >= 1) { 2292 // If there is more than one service with the same priority, 2293 // just arbitrarily pick the first one. 2294 return query.get(0); 2295 } 2296 } 2297 return null; 2298 } 2299 2300 public List<ResolveInfo> queryIntentServices(Intent intent, 2301 String resolvedType, int flags) { 2302 ComponentName comp = intent.getComponent(); 2303 if (comp != null) { 2304 List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); 2305 ServiceInfo si = getServiceInfo(comp, flags); 2306 if (si != null) { 2307 ResolveInfo ri = new ResolveInfo(); 2308 ri.serviceInfo = si; 2309 list.add(ri); 2310 } 2311 return list; 2312 } 2313 2314 synchronized (mPackages) { 2315 String pkgName = intent.getPackage(); 2316 if (pkgName == null) { 2317 return (List<ResolveInfo>)mServices.queryIntent(intent, 2318 resolvedType, flags); 2319 } 2320 PackageParser.Package pkg = mPackages.get(pkgName); 2321 if (pkg != null) { 2322 return (List<ResolveInfo>)mServices.queryIntentForPackage(intent, 2323 resolvedType, flags, pkg.services); 2324 } 2325 return null; 2326 } 2327 } 2328 2329 private static final int getContinuationPoint(final String[] keys, final String key) { 2330 final int index; 2331 if (key == null) { 2332 index = 0; 2333 } else { 2334 final int insertPoint = Arrays.binarySearch(keys, key); 2335 if (insertPoint < 0) { 2336 index = -insertPoint; 2337 } else { 2338 index = insertPoint + 1; 2339 } 2340 } 2341 return index; 2342 } 2343 2344 public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) { 2345 final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>(); 2346 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; 2347 final String[] keys; 2348 2349 synchronized (mPackages) { 2350 if (listUninstalled) { 2351 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]); 2352 } else { 2353 keys = mPackages.keySet().toArray(new String[mPackages.size()]); 2354 } 2355 2356 Arrays.sort(keys); 2357 int i = getContinuationPoint(keys, lastRead); 2358 final int N = keys.length; 2359 2360 while (i < N) { 2361 final String packageName = keys[i++]; 2362 2363 PackageInfo pi = null; 2364 if (listUninstalled) { 2365 final PackageSetting ps = mSettings.mPackages.get(packageName); 2366 if (ps != null) { 2367 pi = generatePackageInfoFromSettingsLP(ps.name, flags); 2368 } 2369 } else { 2370 final PackageParser.Package p = mPackages.get(packageName); 2371 if (p != null) { 2372 pi = generatePackageInfo(p, flags); 2373 } 2374 } 2375 2376 if (pi != null && !list.append(pi)) { 2377 break; 2378 } 2379 } 2380 2381 if (i == N) { 2382 list.setLastSlice(true); 2383 } 2384 } 2385 2386 return list; 2387 } 2388 2389 public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, 2390 String lastRead) { 2391 final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>(); 2392 final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; 2393 final String[] keys; 2394 2395 synchronized (mPackages) { 2396 if (listUninstalled) { 2397 keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]); 2398 } else { 2399 keys = mPackages.keySet().toArray(new String[mPackages.size()]); 2400 } 2401 2402 Arrays.sort(keys); 2403 int i = getContinuationPoint(keys, lastRead); 2404 final int N = keys.length; 2405 2406 while (i < N) { 2407 final String packageName = keys[i++]; 2408 2409 ApplicationInfo ai = null; 2410 if (listUninstalled) { 2411 final PackageSetting ps = mSettings.mPackages.get(packageName); 2412 if (ps != null) { 2413 ai = generateApplicationInfoFromSettingsLP(ps.name, flags); 2414 } 2415 } else { 2416 final PackageParser.Package p = mPackages.get(packageName); 2417 if (p != null) { 2418 ai = PackageParser.generateApplicationInfo(p, flags); 2419 } 2420 } 2421 2422 if (ai != null && !list.append(ai)) { 2423 break; 2424 } 2425 } 2426 2427 if (i == N) { 2428 list.setLastSlice(true); 2429 } 2430 } 2431 2432 return list; 2433 } 2434 2435 public List<ApplicationInfo> getPersistentApplications(int flags) { 2436 ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>(); 2437 2438 synchronized (mPackages) { 2439 Iterator<PackageParser.Package> i = mPackages.values().iterator(); 2440 while (i.hasNext()) { 2441 PackageParser.Package p = i.next(); 2442 if (p.applicationInfo != null 2443 && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0 2444 && (!mSafeMode || isSystemApp(p))) { 2445 finalList.add(PackageParser.generateApplicationInfo(p, flags)); 2446 } 2447 } 2448 } 2449 2450 return finalList; 2451 } 2452 2453 public ProviderInfo resolveContentProvider(String name, int flags) { 2454 synchronized (mPackages) { 2455 final PackageParser.Provider provider = mProviders.get(name); 2456 return provider != null 2457 && mSettings.isEnabledLP(provider.info, flags) 2458 && (!mSafeMode || (provider.info.applicationInfo.flags 2459 &ApplicationInfo.FLAG_SYSTEM) != 0) 2460 ? PackageParser.generateProviderInfo(provider, flags) 2461 : null; 2462 } 2463 } 2464 2465 /** 2466 * @deprecated 2467 */ 2468 public void querySyncProviders(List outNames, List outInfo) { 2469 synchronized (mPackages) { 2470 Iterator<Map.Entry<String, PackageParser.Provider>> i 2471 = mProviders.entrySet().iterator(); 2472 2473 while (i.hasNext()) { 2474 Map.Entry<String, PackageParser.Provider> entry = i.next(); 2475 PackageParser.Provider p = entry.getValue(); 2476 2477 if (p.syncable 2478 && (!mSafeMode || (p.info.applicationInfo.flags 2479 &ApplicationInfo.FLAG_SYSTEM) != 0)) { 2480 outNames.add(entry.getKey()); 2481 outInfo.add(PackageParser.generateProviderInfo(p, 0)); 2482 } 2483 } 2484 } 2485 } 2486 2487 public List<ProviderInfo> queryContentProviders(String processName, 2488 int uid, int flags) { 2489 ArrayList<ProviderInfo> finalList = null; 2490 2491 synchronized (mPackages) { 2492 Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator(); 2493 while (i.hasNext()) { 2494 PackageParser.Provider p = i.next(); 2495 if (p.info.authority != null 2496 && (processName == null || 2497 (p.info.processName.equals(processName) 2498 && p.info.applicationInfo.uid == uid)) 2499 && mSettings.isEnabledLP(p.info, flags) 2500 && (!mSafeMode || (p.info.applicationInfo.flags 2501 &ApplicationInfo.FLAG_SYSTEM) != 0)) { 2502 if (finalList == null) { 2503 finalList = new ArrayList<ProviderInfo>(3); 2504 } 2505 finalList.add(PackageParser.generateProviderInfo(p, 2506 flags)); 2507 } 2508 } 2509 } 2510 2511 if (finalList != null) { 2512 Collections.sort(finalList, mProviderInitOrderSorter); 2513 } 2514 2515 return finalList; 2516 } 2517 2518 public InstrumentationInfo getInstrumentationInfo(ComponentName name, 2519 int flags) { 2520 synchronized (mPackages) { 2521 final PackageParser.Instrumentation i = mInstrumentation.get(name); 2522 return PackageParser.generateInstrumentationInfo(i, flags); 2523 } 2524 } 2525 2526 public List<InstrumentationInfo> queryInstrumentation(String targetPackage, 2527 int flags) { 2528 ArrayList<InstrumentationInfo> finalList = 2529 new ArrayList<InstrumentationInfo>(); 2530 2531 synchronized (mPackages) { 2532 Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator(); 2533 while (i.hasNext()) { 2534 PackageParser.Instrumentation p = i.next(); 2535 if (targetPackage == null 2536 || targetPackage.equals(p.info.targetPackage)) { 2537 finalList.add(PackageParser.generateInstrumentationInfo(p, 2538 flags)); 2539 } 2540 } 2541 } 2542 2543 return finalList; 2544 } 2545 2546 private void scanDirLI(File dir, int flags, int scanMode, long currentTime) { 2547 String[] files = dir.list(); 2548 if (files == null) { 2549 Log.d(TAG, "No files in app dir " + dir); 2550 return; 2551 } 2552 2553 if (false) { 2554 Log.d(TAG, "Scanning app dir " + dir); 2555 } 2556 2557 int i; 2558 for (i=0; i<files.length; i++) { 2559 File file = new File(dir, files[i]); 2560 if (!isPackageFilename(files[i])) { 2561 // Ignore entries which are not apk's 2562 continue; 2563 } 2564 PackageParser.Package pkg = scanPackageLI(file, 2565 flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime); 2566 // Don't mess around with apps in system partition. 2567 if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 && 2568 mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) { 2569 // Delete the apk 2570 Slog.w(TAG, "Cleaning up failed install of " + file); 2571 file.delete(); 2572 } 2573 } 2574 } 2575 2576 private static File getSettingsProblemFile() { 2577 File dataDir = Environment.getDataDirectory(); 2578 File systemDir = new File(dataDir, "system"); 2579 File fname = new File(systemDir, "uiderrors.txt"); 2580 return fname; 2581 } 2582 2583 private static void reportSettingsProblem(int priority, String msg) { 2584 try { 2585 File fname = getSettingsProblemFile(); 2586 FileOutputStream out = new FileOutputStream(fname, true); 2587 PrintWriter pw = new PrintWriter(out); 2588 SimpleDateFormat formatter = new SimpleDateFormat(); 2589 String dateString = formatter.format(new Date(System.currentTimeMillis())); 2590 pw.println(dateString + ": " + msg); 2591 pw.close(); 2592 FileUtils.setPermissions( 2593 fname.toString(), 2594 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IROTH, 2595 -1, -1); 2596 } catch (java.io.IOException e) { 2597 } 2598 Slog.println(priority, TAG, msg); 2599 } 2600 2601 private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps, 2602 PackageParser.Package pkg, File srcFile, int parseFlags) { 2603 if (GET_CERTIFICATES) { 2604 if (ps != null 2605 && ps.codePath.equals(srcFile) 2606 && ps.timeStamp == srcFile.lastModified()) { 2607 if (ps.signatures.mSignatures != null 2608 && ps.signatures.mSignatures.length != 0) { 2609 // Optimization: reuse the existing cached certificates 2610 // if the package appears to be unchanged. 2611 pkg.mSignatures = ps.signatures.mSignatures; 2612 return true; 2613 } 2614 2615 Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them."); 2616 } else { 2617 Log.i(TAG, srcFile.toString() + " changed; collecting certs"); 2618 } 2619 2620 if (!pp.collectCertificates(pkg, parseFlags)) { 2621 mLastScanError = pp.getParseError(); 2622 return false; 2623 } 2624 } 2625 return true; 2626 } 2627 2628 /* 2629 * Scan a package and return the newly parsed package. 2630 * Returns null in case of errors and the error code is stored in mLastScanError 2631 */ 2632 private PackageParser.Package scanPackageLI(File scanFile, 2633 int parseFlags, int scanMode, long currentTime) { 2634 mLastScanError = PackageManager.INSTALL_SUCCEEDED; 2635 String scanPath = scanFile.getPath(); 2636 parseFlags |= mDefParseFlags; 2637 PackageParser pp = new PackageParser(scanPath); 2638 pp.setSeparateProcesses(mSeparateProcesses); 2639 final PackageParser.Package pkg = pp.parsePackage(scanFile, 2640 scanPath, mMetrics, parseFlags); 2641 if (pkg == null) { 2642 mLastScanError = pp.getParseError(); 2643 return null; 2644 } 2645 PackageSetting ps = null; 2646 PackageSetting updatedPkg; 2647 synchronized (mPackages) { 2648 // Look to see if we already know about this package. 2649 String oldName = mSettings.mRenamedPackages.get(pkg.packageName); 2650 if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) { 2651 // This package has been renamed to its original name. Let's 2652 // use that. 2653 ps = mSettings.peekPackageLP(oldName); 2654 } 2655 // If there was no original package, see one for the real package name. 2656 if (ps == null) { 2657 ps = mSettings.peekPackageLP(pkg.packageName); 2658 } 2659 // Check to see if this package could be hiding/updating a system 2660 // package. Must look for it either under the original or real 2661 // package name depending on our state. 2662 updatedPkg = mSettings.mDisabledSysPackages.get( 2663 ps != null ? ps.name : pkg.packageName); 2664 } 2665 // First check if this is a system package that may involve an update 2666 if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) { 2667 if (ps != null && !ps.codePath.equals(scanFile)) { 2668 // The path has changed from what was last scanned... check the 2669 // version of the new path against what we have stored to determine 2670 // what to do. 2671 if (pkg.mVersionCode < ps.versionCode) { 2672 // The system package has been updated and the code path does not match 2673 // Ignore entry. Skip it. 2674 Log.i(TAG, "Package " + ps.name + " at " + scanFile 2675 + " ignored: updated version " + ps.versionCode 2676 + " better than this " + pkg.mVersionCode); 2677 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE; 2678 return null; 2679 } else { 2680 // The current app on the system partion is better than 2681 // what we have updated to on the data partition; switch 2682 // back to the system partition version. 2683 // At this point, its safely assumed that package installation for 2684 // apps in system partition will go through. If not there won't be a working 2685 // version of the app 2686 synchronized (mPackages) { 2687 // Just remove the loaded entries from package lists. 2688 mPackages.remove(ps.name); 2689 } 2690 Slog.w(TAG, "Package " + ps.name + " at " + scanFile 2691 + "reverting from " + ps.codePathString 2692 + ": new version " + pkg.mVersionCode 2693 + " better than installed " + ps.versionCode); 2694 InstallArgs args = new FileInstallArgs(ps.codePathString, 2695 ps.resourcePathString, ps.nativeLibraryPathString); 2696 args.cleanUpResourcesLI(); 2697 mSettings.enableSystemPackageLP(ps.name); 2698 } 2699 } 2700 } 2701 if (updatedPkg != null) { 2702 // An updated system app will not have the PARSE_IS_SYSTEM flag set initially 2703 parseFlags |= PackageParser.PARSE_IS_SYSTEM; 2704 } 2705 // Verify certificates against what was last scanned 2706 if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) { 2707 Slog.w(TAG, "Failed verifying certificates for package:" + pkg.packageName); 2708 return null; 2709 } 2710 // The apk is forward locked (not public) if its code and resources 2711 // are kept in different files. 2712 // TODO grab this value from PackageSettings 2713 if (ps != null && !ps.codePath.equals(ps.resourcePath)) { 2714 parseFlags |= PackageParser.PARSE_FORWARD_LOCK; 2715 } 2716 2717 String codePath = null; 2718 String resPath = null; 2719 if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) { 2720 if (ps != null && ps.resourcePathString != null) { 2721 resPath = ps.resourcePathString; 2722 } else { 2723 // Should not happen at all. Just log an error. 2724 Slog.e(TAG, "Resource path not set for pkg : " + pkg.packageName); 2725 } 2726 } else { 2727 resPath = pkg.mScanPath; 2728 } 2729 codePath = pkg.mScanPath; 2730 // Set application objects path explicitly. 2731 setApplicationInfoPaths(pkg, codePath, resPath); 2732 // Note that we invoke the following method only if we are about to unpack an application 2733 return scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime); 2734 } 2735 2736 private static void setApplicationInfoPaths(PackageParser.Package pkg, String destCodePath, 2737 String destResPath) { 2738 pkg.mPath = pkg.mScanPath = destCodePath; 2739 pkg.applicationInfo.sourceDir = destCodePath; 2740 pkg.applicationInfo.publicSourceDir = destResPath; 2741 } 2742 2743 private static String fixProcessName(String defProcessName, 2744 String processName, int uid) { 2745 if (processName == null) { 2746 return defProcessName; 2747 } 2748 return processName; 2749 } 2750 2751 private boolean verifySignaturesLP(PackageSetting pkgSetting, 2752 PackageParser.Package pkg) { 2753 if (pkgSetting.signatures.mSignatures != null) { 2754 // Already existing package. Make sure signatures match 2755 if (checkSignaturesLP(pkgSetting.signatures.mSignatures, pkg.mSignatures) != 2756 PackageManager.SIGNATURE_MATCH) { 2757 Slog.e(TAG, "Package " + pkg.packageName 2758 + " signatures do not match the previously installed version; ignoring!"); 2759 mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE; 2760 return false; 2761 } 2762 } 2763 // Check for shared user signatures 2764 if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) { 2765 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures, 2766 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { 2767 Slog.e(TAG, "Package " + pkg.packageName 2768 + " has no signatures that match those in shared user " 2769 + pkgSetting.sharedUser.name + "; ignoring!"); 2770 mLastScanError = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE; 2771 return false; 2772 } 2773 } 2774 return true; 2775 } 2776 2777 public boolean performDexOpt(String packageName) { 2778 if (!mNoDexOpt) { 2779 return false; 2780 } 2781 2782 PackageParser.Package p; 2783 synchronized (mPackages) { 2784 p = mPackages.get(packageName); 2785 if (p == null || p.mDidDexOpt) { 2786 return false; 2787 } 2788 } 2789 synchronized (mInstallLock) { 2790 return performDexOptLI(p, false) == DEX_OPT_PERFORMED; 2791 } 2792 } 2793 2794 static final int DEX_OPT_SKIPPED = 0; 2795 static final int DEX_OPT_PERFORMED = 1; 2796 static final int DEX_OPT_FAILED = -1; 2797 2798 private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) { 2799 boolean performed = false; 2800 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0 && mInstaller != null) { 2801 String path = pkg.mScanPath; 2802 int ret = 0; 2803 try { 2804 if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) { 2805 ret = mInstaller.dexopt(path, pkg.applicationInfo.uid, 2806 !isForwardLocked(pkg)); 2807 pkg.mDidDexOpt = true; 2808 performed = true; 2809 } 2810 } catch (FileNotFoundException e) { 2811 Slog.w(TAG, "Apk not found for dexopt: " + path); 2812 ret = -1; 2813 } catch (IOException e) { 2814 Slog.w(TAG, "IOException reading apk: " + path, e); 2815 ret = -1; 2816 } catch (dalvik.system.StaleDexCacheError e) { 2817 Slog.w(TAG, "StaleDexCacheError when reading apk: " + path, e); 2818 ret = -1; 2819 } catch (Exception e) { 2820 Slog.w(TAG, "Exception when doing dexopt : ", e); 2821 ret = -1; 2822 } 2823 if (ret < 0) { 2824 //error from installer 2825 return DEX_OPT_FAILED; 2826 } 2827 } 2828 2829 return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED; 2830 } 2831 2832 private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) { 2833 return Environment.isEncryptedFilesystemEnabled() && 2834 ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0); 2835 } 2836 2837 private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) { 2838 if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { 2839 Slog.w(TAG, "Unable to update from " + oldPkg.name 2840 + " to " + newPkg.packageName 2841 + ": old package not in system partition"); 2842 return false; 2843 } else if (mPackages.get(oldPkg.name) != null) { 2844 Slog.w(TAG, "Unable to update from " + oldPkg.name 2845 + " to " + newPkg.packageName 2846 + ": old package still exists"); 2847 return false; 2848 } 2849 return true; 2850 } 2851 2852 private File getDataPathForPackage(PackageParser.Package pkg) { 2853 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); 2854 File dataPath; 2855 if (useEncryptedFSDir) { 2856 dataPath = new File(mSecureAppDataDir, pkg.packageName); 2857 } else { 2858 dataPath = new File(mAppDataDir, pkg.packageName); 2859 } 2860 return dataPath; 2861 } 2862 2863 private PackageParser.Package scanPackageLI(PackageParser.Package pkg, 2864 int parseFlags, int scanMode, long currentTime) { 2865 File scanFile = new File(pkg.mScanPath); 2866 if (scanFile == null || pkg.applicationInfo.sourceDir == null || 2867 pkg.applicationInfo.publicSourceDir == null) { 2868 // Bail out. The resource and code paths haven't been set. 2869 Slog.w(TAG, " Code and resource paths haven't been set correctly"); 2870 mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK; 2871 return null; 2872 } 2873 mScanningPath = scanFile; 2874 if (pkg == null) { 2875 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 2876 return null; 2877 } 2878 2879 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) { 2880 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; 2881 } 2882 2883 if (pkg.packageName.equals("android")) { 2884 synchronized (mPackages) { 2885 if (mAndroidApplication != null) { 2886 Slog.w(TAG, "*************************************************"); 2887 Slog.w(TAG, "Core android package being redefined. Skipping."); 2888 Slog.w(TAG, " file=" + mScanningPath); 2889 Slog.w(TAG, "*************************************************"); 2890 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE; 2891 return null; 2892 } 2893 2894 // Set up information for our fall-back user intent resolution 2895 // activity. 2896 mPlatformPackage = pkg; 2897 pkg.mVersionCode = mSdkVersion; 2898 mAndroidApplication = pkg.applicationInfo; 2899 mResolveActivity.applicationInfo = mAndroidApplication; 2900 mResolveActivity.name = ResolverActivity.class.getName(); 2901 mResolveActivity.packageName = mAndroidApplication.packageName; 2902 mResolveActivity.processName = mAndroidApplication.processName; 2903 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; 2904 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; 2905 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert; 2906 mResolveActivity.exported = true; 2907 mResolveActivity.enabled = true; 2908 mResolveInfo.activityInfo = mResolveActivity; 2909 mResolveInfo.priority = 0; 2910 mResolveInfo.preferredOrder = 0; 2911 mResolveInfo.match = 0; 2912 mResolveComponentName = new ComponentName( 2913 mAndroidApplication.packageName, mResolveActivity.name); 2914 } 2915 } 2916 2917 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d( 2918 TAG, "Scanning package " + pkg.packageName); 2919 if (mPackages.containsKey(pkg.packageName) 2920 || mSharedLibraries.containsKey(pkg.packageName)) { 2921 Slog.w(TAG, "Application package " + pkg.packageName 2922 + " already installed. Skipping duplicate."); 2923 mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE; 2924 return null; 2925 } 2926 2927 // Initialize package source and resource directories 2928 File destCodeFile = new File(pkg.applicationInfo.sourceDir); 2929 File destResourceFile = new File(pkg.applicationInfo.publicSourceDir); 2930 2931 SharedUserSetting suid = null; 2932 PackageSetting pkgSetting = null; 2933 2934 if (!isSystemApp(pkg)) { 2935 // Only system apps can use these features. 2936 pkg.mOriginalPackages = null; 2937 pkg.mRealPackage = null; 2938 pkg.mAdoptPermissions = null; 2939 } 2940 2941 synchronized (mPackages) { 2942 // Check all shared libraries and map to their actual file path. 2943 if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) { 2944 if (mTmpSharedLibraries == null || 2945 mTmpSharedLibraries.length < mSharedLibraries.size()) { 2946 mTmpSharedLibraries = new String[mSharedLibraries.size()]; 2947 } 2948 int num = 0; 2949 int N = pkg.usesLibraries != null ? pkg.usesLibraries.size() : 0; 2950 for (int i=0; i<N; i++) { 2951 String file = mSharedLibraries.get(pkg.usesLibraries.get(i)); 2952 if (file == null) { 2953 Slog.e(TAG, "Package " + pkg.packageName 2954 + " requires unavailable shared library " 2955 + pkg.usesLibraries.get(i) + "; failing!"); 2956 mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY; 2957 return null; 2958 } 2959 mTmpSharedLibraries[num] = file; 2960 num++; 2961 } 2962 N = pkg.usesOptionalLibraries != null ? pkg.usesOptionalLibraries.size() : 0; 2963 for (int i=0; i<N; i++) { 2964 String file = mSharedLibraries.get(pkg.usesOptionalLibraries.get(i)); 2965 if (file == null) { 2966 Slog.w(TAG, "Package " + pkg.packageName 2967 + " desires unavailable shared library " 2968 + pkg.usesOptionalLibraries.get(i) + "; ignoring!"); 2969 } else { 2970 mTmpSharedLibraries[num] = file; 2971 num++; 2972 } 2973 } 2974 if (num > 0) { 2975 pkg.usesLibraryFiles = new String[num]; 2976 System.arraycopy(mTmpSharedLibraries, 0, 2977 pkg.usesLibraryFiles, 0, num); 2978 } 2979 } 2980 2981 if (pkg.mSharedUserId != null) { 2982 suid = mSettings.getSharedUserLP(pkg.mSharedUserId, 2983 pkg.applicationInfo.flags, true); 2984 if (suid == null) { 2985 Slog.w(TAG, "Creating application package " + pkg.packageName 2986 + " for shared user failed"); 2987 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 2988 return null; 2989 } 2990 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) { 2991 Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" 2992 + suid.userId + "): packages=" + suid.packages); 2993 } 2994 } 2995 2996 if (false) { 2997 if (pkg.mOriginalPackages != null) { 2998 Log.w(TAG, "WAITING FOR DEBUGGER"); 2999 Debug.waitForDebugger(); 3000 Log.i(TAG, "Package " + pkg.packageName + " from original packages" 3001 + pkg.mOriginalPackages); 3002 } 3003 } 3004 3005 // Check if we are renaming from an original package name. 3006 PackageSetting origPackage = null; 3007 String realName = null; 3008 if (pkg.mOriginalPackages != null) { 3009 // This package may need to be renamed to a previously 3010 // installed name. Let's check on that... 3011 String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage); 3012 if (pkg.mOriginalPackages.contains(renamed)) { 3013 // This package had originally been installed as the 3014 // original name, and we have already taken care of 3015 // transitioning to the new one. Just update the new 3016 // one to continue using the old name. 3017 realName = pkg.mRealPackage; 3018 if (!pkg.packageName.equals(renamed)) { 3019 // Callers into this function may have already taken 3020 // care of renaming the package; only do it here if 3021 // it is not already done. 3022 pkg.setPackageName(renamed); 3023 } 3024 3025 } else { 3026 for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) { 3027 if ((origPackage=mSettings.peekPackageLP( 3028 pkg.mOriginalPackages.get(i))) != null) { 3029 // We do have the package already installed under its 3030 // original name... should we use it? 3031 if (!verifyPackageUpdate(origPackage, pkg)) { 3032 // New package is not compatible with original. 3033 origPackage = null; 3034 continue; 3035 } else if (origPackage.sharedUser != null) { 3036 // Make sure uid is compatible between packages. 3037 if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) { 3038 Slog.w(TAG, "Unable to migrate data from " + origPackage.name 3039 + " to " + pkg.packageName + ": old uid " 3040 + origPackage.sharedUser.name 3041 + " differs from " + pkg.mSharedUserId); 3042 origPackage = null; 3043 continue; 3044 } 3045 } else { 3046 if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package " 3047 + pkg.packageName + " to old name " + origPackage.name); 3048 } 3049 break; 3050 } 3051 } 3052 } 3053 } 3054 3055 if (mTransferedPackages.contains(pkg.packageName)) { 3056 Slog.w(TAG, "Package " + pkg.packageName 3057 + " was transferred to another, but its .apk remains"); 3058 } 3059 3060 // Just create the setting, don't add it yet. For already existing packages 3061 // the PkgSetting exists already and doesn't have to be created. 3062 pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile, 3063 destResourceFile, pkg.applicationInfo.nativeLibraryDir, 3064 pkg.applicationInfo.flags, true, false); 3065 if (pkgSetting == null) { 3066 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed"); 3067 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 3068 return null; 3069 } 3070 3071 if (pkgSetting.origPackage != null) { 3072 // If we are first transitioning from an original package, 3073 // fix up the new package's name now. We need to do this after 3074 // looking up the package under its new name, so getPackageLP 3075 // can take care of fiddling things correctly. 3076 pkg.setPackageName(origPackage.name); 3077 3078 // File a report about this. 3079 String msg = "New package " + pkgSetting.realName 3080 + " renamed to replace old package " + pkgSetting.name; 3081 reportSettingsProblem(Log.WARN, msg); 3082 3083 // Make a note of it. 3084 mTransferedPackages.add(origPackage.name); 3085 3086 // No longer need to retain this. 3087 pkgSetting.origPackage = null; 3088 } 3089 3090 if (realName != null) { 3091 // Make a note of it. 3092 mTransferedPackages.add(pkg.packageName); 3093 } 3094 3095 if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) { 3096 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; 3097 } 3098 3099 pkg.applicationInfo.uid = pkgSetting.userId; 3100 pkg.mExtras = pkgSetting; 3101 3102 if (!verifySignaturesLP(pkgSetting, pkg)) { 3103 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { 3104 return null; 3105 } 3106 // The signature has changed, but this package is in the system 3107 // image... let's recover! 3108 pkgSetting.signatures.mSignatures = pkg.mSignatures; 3109 // However... if this package is part of a shared user, but it 3110 // doesn't match the signature of the shared user, let's fail. 3111 // What this means is that you can't change the signatures 3112 // associated with an overall shared user, which doesn't seem all 3113 // that unreasonable. 3114 if (pkgSetting.sharedUser != null) { 3115 if (checkSignaturesLP(pkgSetting.sharedUser.signatures.mSignatures, 3116 pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) { 3117 Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser); 3118 mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; 3119 return null; 3120 } 3121 } 3122 // File a report about this. 3123 String msg = "System package " + pkg.packageName 3124 + " signature changed; retaining data."; 3125 reportSettingsProblem(Log.WARN, msg); 3126 } 3127 3128 // Verify that this new package doesn't have any content providers 3129 // that conflict with existing packages. Only do this if the 3130 // package isn't already installed, since we don't want to break 3131 // things that are installed. 3132 if ((scanMode&SCAN_NEW_INSTALL) != 0) { 3133 int N = pkg.providers.size(); 3134 int i; 3135 for (i=0; i<N; i++) { 3136 PackageParser.Provider p = pkg.providers.get(i); 3137 if (p.info.authority != null) { 3138 String names[] = p.info.authority.split(";"); 3139 for (int j = 0; j < names.length; j++) { 3140 if (mProviders.containsKey(names[j])) { 3141 PackageParser.Provider other = mProviders.get(names[j]); 3142 Slog.w(TAG, "Can't install because provider name " + names[j] + 3143 " (in package " + pkg.applicationInfo.packageName + 3144 ") is already used by " 3145 + ((other != null && other.getComponentName() != null) 3146 ? other.getComponentName().getPackageName() : "?")); 3147 mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER; 3148 return null; 3149 } 3150 } 3151 } 3152 } 3153 } 3154 } 3155 3156 final String pkgName = pkg.packageName; 3157 3158 if (pkg.mAdoptPermissions != null) { 3159 // This package wants to adopt ownership of permissions from 3160 // another package. 3161 for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) { 3162 String origName = pkg.mAdoptPermissions.get(i); 3163 PackageSetting orig = mSettings.peekPackageLP(origName); 3164 if (orig != null) { 3165 if (verifyPackageUpdate(orig, pkg)) { 3166 Slog.i(TAG, "Adopting permissions from " 3167 + origName + " to " + pkg.packageName); 3168 mSettings.transferPermissions(origName, pkg.packageName); 3169 } 3170 } 3171 } 3172 } 3173 3174 final long scanFileTime = scanFile.lastModified(); 3175 final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0; 3176 final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.timeStamp; 3177 pkg.applicationInfo.processName = fixProcessName( 3178 pkg.applicationInfo.packageName, 3179 pkg.applicationInfo.processName, 3180 pkg.applicationInfo.uid); 3181 3182 File dataPath; 3183 if (mPlatformPackage == pkg) { 3184 // The system package is special. 3185 dataPath = new File (Environment.getDataDirectory(), "system"); 3186 pkg.applicationInfo.dataDir = dataPath.getPath(); 3187 } else { 3188 // This is a normal package, need to make its data directory. 3189 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg); 3190 dataPath = getDataPathForPackage(pkg); 3191 3192 boolean uidError = false; 3193 3194 if (dataPath.exists()) { 3195 mOutPermissions[1] = 0; 3196 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions); 3197 3198 // If we have mismatched owners for the data path, we have a 3199 // problem (unless we're running in the simulator.) 3200 if (mOutPermissions[1] != pkg.applicationInfo.uid && Process.supportsProcesses()) { 3201 boolean recovered = false; 3202 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) { 3203 // If this is a system app, we can at least delete its 3204 // current data so the application will still work. 3205 if (mInstaller != null) { 3206 int ret = mInstaller.remove(pkgName, useEncryptedFSDir); 3207 if (ret >= 0) { 3208 // Old data gone! 3209 String msg = "System package " + pkg.packageName 3210 + " has changed from uid: " 3211 + mOutPermissions[1] + " to " 3212 + pkg.applicationInfo.uid + "; old data erased"; 3213 reportSettingsProblem(Log.WARN, msg); 3214 recovered = true; 3215 3216 // And now re-install the app. 3217 ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, 3218 pkg.applicationInfo.uid); 3219 if (ret == -1) { 3220 // Ack should not happen! 3221 msg = "System package " + pkg.packageName 3222 + " could not have data directory re-created after delete."; 3223 reportSettingsProblem(Log.WARN, msg); 3224 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 3225 return null; 3226 } 3227 } 3228 } 3229 if (!recovered) { 3230 mHasSystemUidErrors = true; 3231 } 3232 } 3233 if (!recovered) { 3234 pkg.applicationInfo.dataDir = "/mismatched_uid/settings_" 3235 + pkg.applicationInfo.uid + "/fs_" 3236 + mOutPermissions[1]; 3237 pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir; 3238 String msg = "Package " + pkg.packageName 3239 + " has mismatched uid: " 3240 + mOutPermissions[1] + " on disk, " 3241 + pkg.applicationInfo.uid + " in settings"; 3242 synchronized (mPackages) { 3243 mSettings.mReadMessages.append(msg); 3244 mSettings.mReadMessages.append('\n'); 3245 uidError = true; 3246 if (!pkgSetting.uidError) { 3247 reportSettingsProblem(Log.ERROR, msg); 3248 } 3249 } 3250 } 3251 } 3252 pkg.applicationInfo.dataDir = dataPath.getPath(); 3253 } else { 3254 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV) 3255 Log.v(TAG, "Want this data dir: " + dataPath); 3256 //invoke installer to do the actual installation 3257 if (mInstaller != null) { 3258 int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid, 3259 pkg.applicationInfo.uid); 3260 if(ret < 0) { 3261 // Error from installer 3262 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 3263 return null; 3264 } 3265 } else { 3266 dataPath.mkdirs(); 3267 if (dataPath.exists()) { 3268 FileUtils.setPermissions( 3269 dataPath.toString(), 3270 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 3271 pkg.applicationInfo.uid, pkg.applicationInfo.uid); 3272 } 3273 } 3274 if (dataPath.exists()) { 3275 pkg.applicationInfo.dataDir = dataPath.getPath(); 3276 } else { 3277 Slog.w(TAG, "Unable to create data directory: " + dataPath); 3278 pkg.applicationInfo.dataDir = null; 3279 } 3280 } 3281 3282 /* 3283 * Set the data dir to the default "/data/data/<package name>/lib" 3284 * if we got here without anyone telling us different (e.g., apps 3285 * stored on SD card have their native libraries stored in the ASEC 3286 * container with the APK). 3287 * 3288 * This happens during an upgrade from a package settings file that 3289 * doesn't have a native library path attribute at all. 3290 */ 3291 if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { 3292 if (pkgSetting.nativeLibraryPathString == null) { 3293 final String nativeLibraryPath = new File(dataPath, LIB_DIR_NAME).getPath(); 3294 pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath; 3295 pkgSetting.nativeLibraryPathString = nativeLibraryPath; 3296 } else { 3297 pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString; 3298 } 3299 } 3300 3301 pkgSetting.uidError = uidError; 3302 } 3303 3304 // If we're running in the simulator, we don't need to unpack anything. 3305 if (mInstaller != null) { 3306 String path = scanFile.getPath(); 3307 /* Note: We don't want to unpack the native binaries for 3308 * system applications, unless they have been updated 3309 * (the binaries are already under /system/lib). 3310 * Also, don't unpack libs for apps on the external card 3311 * since they should have their libraries in the ASEC 3312 * container already. 3313 * 3314 * In other words, we're going to unpack the binaries 3315 * only for non-system apps and system app upgrades. 3316 */ 3317 if (pkg.applicationInfo.nativeLibraryDir != null) { 3318 final File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir); 3319 final String dataPathString = dataPath.getPath(); 3320 3321 if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) { 3322 /* 3323 * Upgrading from a previous version of the OS sometimes 3324 * leaves native libraries in the /data/data/<app>/lib 3325 * directory for system apps even when they shouldn't be. 3326 * Recent changes in the JNI library search path 3327 * necessitates we remove those to match previous behavior. 3328 */ 3329 if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) { 3330 Log.i(TAG, "removed obsolete native libraries for system package " + path); 3331 } 3332 } else if (nativeLibraryDir.getParent().equals(dataPathString)) { 3333 /* 3334 * If this is an internal application or our 3335 * nativeLibraryPath points to our data directory, unpack 3336 * the libraries. The native library path pointing to the 3337 * data directory for an application in an ASEC container 3338 * can happen for older apps that existed before an OTA to 3339 * Gingerbread. 3340 */ 3341 Slog.i(TAG, "Unpacking native libraries for " + path); 3342 mInstaller.unlinkNativeLibraryDirectory(dataPathString); 3343 NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir); 3344 } else { 3345 Slog.i(TAG, "Linking native library dir for " + path); 3346 mInstaller.linkNativeLibraryDirectory(dataPathString, 3347 pkg.applicationInfo.nativeLibraryDir); 3348 } 3349 } 3350 pkg.mScanPath = path; 3351 3352 if ((scanMode&SCAN_NO_DEX) == 0) { 3353 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) { 3354 mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT; 3355 return null; 3356 } 3357 } 3358 } 3359 3360 if (mFactoryTest && pkg.requestedPermissions.contains( 3361 android.Manifest.permission.FACTORY_TEST)) { 3362 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST; 3363 } 3364 3365 // Request the ActivityManager to kill the process(only for existing packages) 3366 // so that we do not end up in a confused state while the user is still using the older 3367 // version of the application while the new one gets installed. 3368 if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { 3369 killApplication(pkg.applicationInfo.packageName, 3370 pkg.applicationInfo.uid); 3371 } 3372 3373 synchronized (mPackages) { 3374 // We don't expect installation to fail beyond this point, 3375 if ((scanMode&SCAN_MONITOR) != 0) { 3376 mAppDirs.put(pkg.mPath, pkg); 3377 } 3378 // Add the new setting to mSettings 3379 mSettings.insertPackageSettingLP(pkgSetting, pkg); 3380 // Add the new setting to mPackages 3381 mPackages.put(pkg.applicationInfo.packageName, pkg); 3382 // Make sure we don't accidentally delete its data. 3383 mSettings.mPackagesToBeCleaned.remove(pkgName); 3384 3385 // Take care of first install / last update times. 3386 if (currentTime != 0) { 3387 if (pkgSetting.firstInstallTime == 0) { 3388 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime; 3389 } else if ((scanMode&SCAN_UPDATE_TIME) != 0) { 3390 pkgSetting.lastUpdateTime = currentTime; 3391 } 3392 } else if (pkgSetting.firstInstallTime == 0) { 3393 // We need *something*. Take time time stamp of the file. 3394 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime; 3395 } else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) { 3396 if (scanFileTime != pkgSetting.timeStamp) { 3397 // A package on the system image has changed; consider this 3398 // to be an update. 3399 pkgSetting.lastUpdateTime = scanFileTime; 3400 } 3401 } 3402 3403 int N = pkg.providers.size(); 3404 StringBuilder r = null; 3405 int i; 3406 for (i=0; i<N; i++) { 3407 PackageParser.Provider p = pkg.providers.get(i); 3408 p.info.processName = fixProcessName(pkg.applicationInfo.processName, 3409 p.info.processName, pkg.applicationInfo.uid); 3410 mProvidersByComponent.put(new ComponentName(p.info.packageName, 3411 p.info.name), p); 3412 p.syncable = p.info.isSyncable; 3413 if (p.info.authority != null) { 3414 String names[] = p.info.authority.split(";"); 3415 p.info.authority = null; 3416 for (int j = 0; j < names.length; j++) { 3417 if (j == 1 && p.syncable) { 3418 // We only want the first authority for a provider to possibly be 3419 // syncable, so if we already added this provider using a different 3420 // authority clear the syncable flag. We copy the provider before 3421 // changing it because the mProviders object contains a reference 3422 // to a provider that we don't want to change. 3423 // Only do this for the second authority since the resulting provider 3424 // object can be the same for all future authorities for this provider. 3425 p = new PackageParser.Provider(p); 3426 p.syncable = false; 3427 } 3428 if (!mProviders.containsKey(names[j])) { 3429 mProviders.put(names[j], p); 3430 if (p.info.authority == null) { 3431 p.info.authority = names[j]; 3432 } else { 3433 p.info.authority = p.info.authority + ";" + names[j]; 3434 } 3435 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) 3436 Log.d(TAG, "Registered content provider: " + names[j] + 3437 ", className = " + p.info.name + 3438 ", isSyncable = " + p.info.isSyncable); 3439 } else { 3440 PackageParser.Provider other = mProviders.get(names[j]); 3441 Slog.w(TAG, "Skipping provider name " + names[j] + 3442 " (in package " + pkg.applicationInfo.packageName + 3443 "): name already used by " 3444 + ((other != null && other.getComponentName() != null) 3445 ? other.getComponentName().getPackageName() : "?")); 3446 } 3447 } 3448 } 3449 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3450 if (r == null) { 3451 r = new StringBuilder(256); 3452 } else { 3453 r.append(' '); 3454 } 3455 r.append(p.info.name); 3456 } 3457 } 3458 if (r != null) { 3459 if (Config.LOGD) Log.d(TAG, " Providers: " + r); 3460 } 3461 3462 N = pkg.services.size(); 3463 r = null; 3464 for (i=0; i<N; i++) { 3465 PackageParser.Service s = pkg.services.get(i); 3466 s.info.processName = fixProcessName(pkg.applicationInfo.processName, 3467 s.info.processName, pkg.applicationInfo.uid); 3468 mServices.addService(s); 3469 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3470 if (r == null) { 3471 r = new StringBuilder(256); 3472 } else { 3473 r.append(' '); 3474 } 3475 r.append(s.info.name); 3476 } 3477 } 3478 if (r != null) { 3479 if (Config.LOGD) Log.d(TAG, " Services: " + r); 3480 } 3481 3482 N = pkg.receivers.size(); 3483 r = null; 3484 for (i=0; i<N; i++) { 3485 PackageParser.Activity a = pkg.receivers.get(i); 3486 a.info.processName = fixProcessName(pkg.applicationInfo.processName, 3487 a.info.processName, pkg.applicationInfo.uid); 3488 mReceivers.addActivity(a, "receiver"); 3489 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3490 if (r == null) { 3491 r = new StringBuilder(256); 3492 } else { 3493 r.append(' '); 3494 } 3495 r.append(a.info.name); 3496 } 3497 } 3498 if (r != null) { 3499 if (Config.LOGD) Log.d(TAG, " Receivers: " + r); 3500 } 3501 3502 N = pkg.activities.size(); 3503 r = null; 3504 for (i=0; i<N; i++) { 3505 PackageParser.Activity a = pkg.activities.get(i); 3506 a.info.processName = fixProcessName(pkg.applicationInfo.processName, 3507 a.info.processName, pkg.applicationInfo.uid); 3508 mActivities.addActivity(a, "activity"); 3509 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3510 if (r == null) { 3511 r = new StringBuilder(256); 3512 } else { 3513 r.append(' '); 3514 } 3515 r.append(a.info.name); 3516 } 3517 } 3518 if (r != null) { 3519 if (Config.LOGD) Log.d(TAG, " Activities: " + r); 3520 } 3521 3522 N = pkg.permissionGroups.size(); 3523 r = null; 3524 for (i=0; i<N; i++) { 3525 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i); 3526 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name); 3527 if (cur == null) { 3528 mPermissionGroups.put(pg.info.name, pg); 3529 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3530 if (r == null) { 3531 r = new StringBuilder(256); 3532 } else { 3533 r.append(' '); 3534 } 3535 r.append(pg.info.name); 3536 } 3537 } else { 3538 Slog.w(TAG, "Permission group " + pg.info.name + " from package " 3539 + pg.info.packageName + " ignored: original from " 3540 + cur.info.packageName); 3541 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3542 if (r == null) { 3543 r = new StringBuilder(256); 3544 } else { 3545 r.append(' '); 3546 } 3547 r.append("DUP:"); 3548 r.append(pg.info.name); 3549 } 3550 } 3551 } 3552 if (r != null) { 3553 if (Config.LOGD) Log.d(TAG, " Permission Groups: " + r); 3554 } 3555 3556 N = pkg.permissions.size(); 3557 r = null; 3558 for (i=0; i<N; i++) { 3559 PackageParser.Permission p = pkg.permissions.get(i); 3560 HashMap<String, BasePermission> permissionMap = 3561 p.tree ? mSettings.mPermissionTrees 3562 : mSettings.mPermissions; 3563 p.group = mPermissionGroups.get(p.info.group); 3564 if (p.info.group == null || p.group != null) { 3565 BasePermission bp = permissionMap.get(p.info.name); 3566 if (bp == null) { 3567 bp = new BasePermission(p.info.name, p.info.packageName, 3568 BasePermission.TYPE_NORMAL); 3569 permissionMap.put(p.info.name, bp); 3570 } 3571 if (bp.perm == null) { 3572 if (bp.sourcePackage == null 3573 || bp.sourcePackage.equals(p.info.packageName)) { 3574 BasePermission tree = findPermissionTreeLP(p.info.name); 3575 if (tree == null 3576 || tree.sourcePackage.equals(p.info.packageName)) { 3577 bp.packageSetting = pkgSetting; 3578 bp.perm = p; 3579 bp.uid = pkg.applicationInfo.uid; 3580 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3581 if (r == null) { 3582 r = new StringBuilder(256); 3583 } else { 3584 r.append(' '); 3585 } 3586 r.append(p.info.name); 3587 } 3588 } else { 3589 Slog.w(TAG, "Permission " + p.info.name + " from package " 3590 + p.info.packageName + " ignored: base tree " 3591 + tree.name + " is from package " 3592 + tree.sourcePackage); 3593 } 3594 } else { 3595 Slog.w(TAG, "Permission " + p.info.name + " from package " 3596 + p.info.packageName + " ignored: original from " 3597 + bp.sourcePackage); 3598 } 3599 } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3600 if (r == null) { 3601 r = new StringBuilder(256); 3602 } else { 3603 r.append(' '); 3604 } 3605 r.append("DUP:"); 3606 r.append(p.info.name); 3607 } 3608 if (bp.perm == p) { 3609 bp.protectionLevel = p.info.protectionLevel; 3610 } 3611 } else { 3612 Slog.w(TAG, "Permission " + p.info.name + " from package " 3613 + p.info.packageName + " ignored: no group " 3614 + p.group); 3615 } 3616 } 3617 if (r != null) { 3618 if (Config.LOGD) Log.d(TAG, " Permissions: " + r); 3619 } 3620 3621 N = pkg.instrumentation.size(); 3622 r = null; 3623 for (i=0; i<N; i++) { 3624 PackageParser.Instrumentation a = pkg.instrumentation.get(i); 3625 a.info.packageName = pkg.applicationInfo.packageName; 3626 a.info.sourceDir = pkg.applicationInfo.sourceDir; 3627 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir; 3628 a.info.dataDir = pkg.applicationInfo.dataDir; 3629 a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir; 3630 mInstrumentation.put(a.getComponentName(), a); 3631 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) { 3632 if (r == null) { 3633 r = new StringBuilder(256); 3634 } else { 3635 r.append(' '); 3636 } 3637 r.append(a.info.name); 3638 } 3639 } 3640 if (r != null) { 3641 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r); 3642 } 3643 3644 if (pkg.protectedBroadcasts != null) { 3645 N = pkg.protectedBroadcasts.size(); 3646 for (i=0; i<N; i++) { 3647 mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); 3648 } 3649 } 3650 3651 pkgSetting.setTimeStamp(scanFileTime); 3652 } 3653 3654 return pkg; 3655 } 3656 3657 private void killApplication(String pkgName, int uid) { 3658 // Request the ActivityManager to kill the process(only for existing packages) 3659 // so that we do not end up in a confused state while the user is still using the older 3660 // version of the application while the new one gets installed. 3661 IActivityManager am = ActivityManagerNative.getDefault(); 3662 if (am != null) { 3663 try { 3664 am.killApplicationWithUid(pkgName, uid); 3665 } catch (RemoteException e) { 3666 } 3667 } 3668 } 3669 3670 // Return the path of the directory that will contain the native binaries 3671 // of a given installed package. This is relative to the data path. 3672 // 3673 private File getNativeBinaryDirForPackage(PackageParser.Package pkg) { 3674 final String nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir; 3675 if (nativeLibraryDir != null) { 3676 return new File(nativeLibraryDir); 3677 } else { 3678 // Fall back for old packages 3679 return new File(pkg.applicationInfo.dataDir, LIB_DIR_NAME); 3680 } 3681 } 3682 3683 void removePackageLI(PackageParser.Package pkg, boolean chatty) { 3684 if (chatty && Config.LOGD) Log.d( 3685 TAG, "Removing package " + pkg.applicationInfo.packageName ); 3686 3687 synchronized (mPackages) { 3688 clearPackagePreferredActivitiesLP(pkg.packageName); 3689 3690 mPackages.remove(pkg.applicationInfo.packageName); 3691 if (pkg.mPath != null) { 3692 mAppDirs.remove(pkg.mPath); 3693 } 3694 3695 int N = pkg.providers.size(); 3696 StringBuilder r = null; 3697 int i; 3698 for (i=0; i<N; i++) { 3699 PackageParser.Provider p = pkg.providers.get(i); 3700 mProvidersByComponent.remove(new ComponentName(p.info.packageName, 3701 p.info.name)); 3702 if (p.info.authority == null) { 3703 3704 /* The is another ContentProvider with this authority when 3705 * this app was installed so this authority is null, 3706 * Ignore it as we don't have to unregister the provider. 3707 */ 3708 continue; 3709 } 3710 String names[] = p.info.authority.split(";"); 3711 for (int j = 0; j < names.length; j++) { 3712 if (mProviders.get(names[j]) == p) { 3713 mProviders.remove(names[j]); 3714 if (chatty && Config.LOGD) Log.d( 3715 TAG, "Unregistered content provider: " + names[j] + 3716 ", className = " + p.info.name + 3717 ", isSyncable = " + p.info.isSyncable); 3718 } 3719 } 3720 if (chatty) { 3721 if (r == null) { 3722 r = new StringBuilder(256); 3723 } else { 3724 r.append(' '); 3725 } 3726 r.append(p.info.name); 3727 } 3728 } 3729 if (r != null) { 3730 if (Config.LOGD) Log.d(TAG, " Providers: " + r); 3731 } 3732 3733 N = pkg.services.size(); 3734 r = null; 3735 for (i=0; i<N; i++) { 3736 PackageParser.Service s = pkg.services.get(i); 3737 mServices.removeService(s); 3738 if (chatty) { 3739 if (r == null) { 3740 r = new StringBuilder(256); 3741 } else { 3742 r.append(' '); 3743 } 3744 r.append(s.info.name); 3745 } 3746 } 3747 if (r != null) { 3748 if (Config.LOGD) Log.d(TAG, " Services: " + r); 3749 } 3750 3751 N = pkg.receivers.size(); 3752 r = null; 3753 for (i=0; i<N; i++) { 3754 PackageParser.Activity a = pkg.receivers.get(i); 3755 mReceivers.removeActivity(a, "receiver"); 3756 if (chatty) { 3757 if (r == null) { 3758 r = new StringBuilder(256); 3759 } else { 3760 r.append(' '); 3761 } 3762 r.append(a.info.name); 3763 } 3764 } 3765 if (r != null) { 3766 if (Config.LOGD) Log.d(TAG, " Receivers: " + r); 3767 } 3768 3769 N = pkg.activities.size(); 3770 r = null; 3771 for (i=0; i<N; i++) { 3772 PackageParser.Activity a = pkg.activities.get(i); 3773 mActivities.removeActivity(a, "activity"); 3774 if (chatty) { 3775 if (r == null) { 3776 r = new StringBuilder(256); 3777 } else { 3778 r.append(' '); 3779 } 3780 r.append(a.info.name); 3781 } 3782 } 3783 if (r != null) { 3784 if (Config.LOGD) Log.d(TAG, " Activities: " + r); 3785 } 3786 3787 N = pkg.permissions.size(); 3788 r = null; 3789 for (i=0; i<N; i++) { 3790 PackageParser.Permission p = pkg.permissions.get(i); 3791 boolean tree = false; 3792 BasePermission bp = mSettings.mPermissions.get(p.info.name); 3793 if (bp == null) { 3794 tree = true; 3795 bp = mSettings.mPermissionTrees.get(p.info.name); 3796 } 3797 if (bp != null && bp.perm == p) { 3798 bp.perm = null; 3799 if (chatty) { 3800 if (r == null) { 3801 r = new StringBuilder(256); 3802 } else { 3803 r.append(' '); 3804 } 3805 r.append(p.info.name); 3806 } 3807 } 3808 } 3809 if (r != null) { 3810 if (Config.LOGD) Log.d(TAG, " Permissions: " + r); 3811 } 3812 3813 N = pkg.instrumentation.size(); 3814 r = null; 3815 for (i=0; i<N; i++) { 3816 PackageParser.Instrumentation a = pkg.instrumentation.get(i); 3817 mInstrumentation.remove(a.getComponentName()); 3818 if (chatty) { 3819 if (r == null) { 3820 r = new StringBuilder(256); 3821 } else { 3822 r.append(' '); 3823 } 3824 r.append(a.info.name); 3825 } 3826 } 3827 if (r != null) { 3828 if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r); 3829 } 3830 } 3831 } 3832 3833 private static final boolean isPackageFilename(String name) { 3834 return name != null && name.endsWith(".apk"); 3835 } 3836 3837 private static boolean hasPermission(PackageParser.Package pkgInfo, String perm) { 3838 for (int i=pkgInfo.permissions.size()-1; i>=0; i--) { 3839 if (pkgInfo.permissions.get(i).info.name.equals(perm)) { 3840 return true; 3841 } 3842 } 3843 return false; 3844 } 3845 3846 private void updatePermissionsLP(String changingPkg, 3847 PackageParser.Package pkgInfo, boolean grantPermissions, 3848 boolean replace, boolean replaceAll) { 3849 // Make sure there are no dangling permission trees. 3850 Iterator<BasePermission> it = mSettings.mPermissionTrees 3851 .values().iterator(); 3852 while (it.hasNext()) { 3853 BasePermission bp = it.next(); 3854 if (bp.packageSetting == null) { 3855 // We may not yet have parsed the package, so just see if 3856 // we still know about its settings. 3857 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage); 3858 } 3859 if (bp.packageSetting == null) { 3860 Slog.w(TAG, "Removing dangling permission tree: " + bp.name 3861 + " from package " + bp.sourcePackage); 3862 it.remove(); 3863 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) { 3864 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) { 3865 Slog.i(TAG, "Removing old permission tree: " + bp.name 3866 + " from package " + bp.sourcePackage); 3867 grantPermissions = true; 3868 it.remove(); 3869 } 3870 } 3871 } 3872 3873 // Make sure all dynamic permissions have been assigned to a package, 3874 // and make sure there are no dangling permissions. 3875 it = mSettings.mPermissions.values().iterator(); 3876 while (it.hasNext()) { 3877 BasePermission bp = it.next(); 3878 if (bp.type == BasePermission.TYPE_DYNAMIC) { 3879 if (DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name=" 3880 + bp.name + " pkg=" + bp.sourcePackage 3881 + " info=" + bp.pendingInfo); 3882 if (bp.packageSetting == null && bp.pendingInfo != null) { 3883 BasePermission tree = findPermissionTreeLP(bp.name); 3884 if (tree != null) { 3885 bp.packageSetting = tree.packageSetting; 3886 bp.perm = new PackageParser.Permission(tree.perm.owner, 3887 new PermissionInfo(bp.pendingInfo)); 3888 bp.perm.info.packageName = tree.perm.info.packageName; 3889 bp.perm.info.name = bp.name; 3890 bp.uid = tree.uid; 3891 } 3892 } 3893 } 3894 if (bp.packageSetting == null) { 3895 // We may not yet have parsed the package, so just see if 3896 // we still know about its settings. 3897 bp.packageSetting = mSettings.mPackages.get(bp.sourcePackage); 3898 } 3899 if (bp.packageSetting == null) { 3900 Slog.w(TAG, "Removing dangling permission: " + bp.name 3901 + " from package " + bp.sourcePackage); 3902 it.remove(); 3903 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) { 3904 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) { 3905 Slog.i(TAG, "Removing old permission: " + bp.name 3906 + " from package " + bp.sourcePackage); 3907 grantPermissions = true; 3908 it.remove(); 3909 } 3910 } 3911 } 3912 3913 // Now update the permissions for all packages, in particular 3914 // replace the granted permissions of the system packages. 3915 if (grantPermissions) { 3916 for (PackageParser.Package pkg : mPackages.values()) { 3917 if (pkg != pkgInfo) { 3918 grantPermissionsLP(pkg, replaceAll); 3919 } 3920 } 3921 } 3922 3923 if (pkgInfo != null) { 3924 grantPermissionsLP(pkgInfo, replace); 3925 } 3926 } 3927 3928 private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) { 3929 final PackageSetting ps = (PackageSetting)pkg.mExtras; 3930 if (ps == null) { 3931 return; 3932 } 3933 final GrantedPermissions gp = ps.sharedUser != null ? ps.sharedUser : ps; 3934 boolean changedPermission = false; 3935 3936 if (replace) { 3937 ps.permissionsFixed = false; 3938 if (gp == ps) { 3939 gp.grantedPermissions.clear(); 3940 gp.gids = mGlobalGids; 3941 } 3942 } 3943 3944 if (gp.gids == null) { 3945 gp.gids = mGlobalGids; 3946 } 3947 3948 final int N = pkg.requestedPermissions.size(); 3949 for (int i=0; i<N; i++) { 3950 String name = pkg.requestedPermissions.get(i); 3951 BasePermission bp = mSettings.mPermissions.get(name); 3952 if (false) { 3953 if (gp != ps) { 3954 Log.i(TAG, "Package " + pkg.packageName + " checking " + name 3955 + ": " + bp); 3956 } 3957 } 3958 if (bp != null && bp.packageSetting != null) { 3959 final String perm = bp.name; 3960 boolean allowed; 3961 boolean allowedSig = false; 3962 if (bp.protectionLevel == PermissionInfo.PROTECTION_NORMAL 3963 || bp.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) { 3964 allowed = true; 3965 } else if (bp.packageSetting == null) { 3966 // This permission is invalid; skip it. 3967 allowed = false; 3968 } else if (bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE 3969 || bp.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) { 3970 allowed = (checkSignaturesLP( 3971 bp.packageSetting.signatures.mSignatures, pkg.mSignatures) 3972 == PackageManager.SIGNATURE_MATCH) 3973 || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures) 3974 == PackageManager.SIGNATURE_MATCH); 3975 if (!allowed && bp.protectionLevel 3976 == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) { 3977 if (isSystemApp(pkg)) { 3978 // For updated system applications, the signatureOrSystem permission 3979 // is granted only if it had been defined by the original application. 3980 if (isUpdatedSystemApp(pkg)) { 3981 PackageSetting sysPs = mSettings.getDisabledSystemPkg( 3982 pkg.packageName); 3983 final GrantedPermissions origGp = sysPs.sharedUser != null 3984 ? sysPs.sharedUser : sysPs; 3985 if (origGp.grantedPermissions.contains(perm)) { 3986 allowed = true; 3987 } else { 3988 allowed = false; 3989 } 3990 } else { 3991 allowed = true; 3992 } 3993 } 3994 } 3995 if (allowed) { 3996 allowedSig = true; 3997 } 3998 } else { 3999 allowed = false; 4000 } 4001 if (false) { 4002 if (gp != ps) { 4003 Log.i(TAG, "Package " + pkg.packageName + " granting " + perm); 4004 } 4005 } 4006 if (allowed) { 4007 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0 4008 && ps.permissionsFixed) { 4009 // If this is an existing, non-system package, then 4010 // we can't add any new permissions to it. 4011 if (!allowedSig && !gp.grantedPermissions.contains(perm)) { 4012 allowed = false; 4013 // Except... if this is a permission that was added 4014 // to the platform (note: need to only do this when 4015 // updating the platform). 4016 final int NP = PackageParser.NEW_PERMISSIONS.length; 4017 for (int ip=0; ip<NP; ip++) { 4018 final PackageParser.NewPermissionInfo npi 4019 = PackageParser.NEW_PERMISSIONS[ip]; 4020 if (npi.name.equals(perm) 4021 && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) { 4022 allowed = true; 4023 Log.i(TAG, "Auto-granting " + perm + " to old pkg " 4024 + pkg.packageName); 4025 break; 4026 } 4027 } 4028 } 4029 } 4030 if (allowed) { 4031 if (!gp.grantedPermissions.contains(perm)) { 4032 changedPermission = true; 4033 gp.grantedPermissions.add(perm); 4034 gp.gids = appendInts(gp.gids, bp.gids); 4035 } else if (!ps.haveGids) { 4036 gp.gids = appendInts(gp.gids, bp.gids); 4037 } 4038 } else { 4039 Slog.w(TAG, "Not granting permission " + perm 4040 + " to package " + pkg.packageName 4041 + " because it was previously installed without"); 4042 } 4043 } else { 4044 if (gp.grantedPermissions.remove(perm)) { 4045 changedPermission = true; 4046 gp.gids = removeInts(gp.gids, bp.gids); 4047 Slog.i(TAG, "Un-granting permission " + perm 4048 + " from package " + pkg.packageName 4049 + " (protectionLevel=" + bp.protectionLevel 4050 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) 4051 + ")"); 4052 } else { 4053 Slog.w(TAG, "Not granting permission " + perm 4054 + " to package " + pkg.packageName 4055 + " (protectionLevel=" + bp.protectionLevel 4056 + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) 4057 + ")"); 4058 } 4059 } 4060 } else { 4061 Slog.w(TAG, "Unknown permission " + name 4062 + " in package " + pkg.packageName); 4063 } 4064 } 4065 4066 if ((changedPermission || replace) && !ps.permissionsFixed && 4067 ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) || 4068 ((ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)){ 4069 // This is the first that we have heard about this package, so the 4070 // permissions we have now selected are fixed until explicitly 4071 // changed. 4072 ps.permissionsFixed = true; 4073 } 4074 ps.haveGids = true; 4075 } 4076 4077 private final class ActivityIntentResolver 4078 extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> { 4079 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) { 4080 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; 4081 return super.queryIntent(intent, resolvedType, defaultOnly); 4082 } 4083 4084 public List queryIntent(Intent intent, String resolvedType, int flags) { 4085 mFlags = flags; 4086 return super.queryIntent(intent, resolvedType, 4087 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0); 4088 } 4089 4090 public List queryIntentForPackage(Intent intent, String resolvedType, int flags, 4091 ArrayList<PackageParser.Activity> packageActivities) { 4092 if (packageActivities == null) { 4093 return null; 4094 } 4095 mFlags = flags; 4096 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; 4097 int N = packageActivities.size(); 4098 ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut = 4099 new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N); 4100 4101 ArrayList<PackageParser.ActivityIntentInfo> intentFilters; 4102 for (int i = 0; i < N; ++i) { 4103 intentFilters = packageActivities.get(i).intents; 4104 if (intentFilters != null && intentFilters.size() > 0) { 4105 listCut.add(intentFilters); 4106 } 4107 } 4108 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut); 4109 } 4110 4111 public final void addActivity(PackageParser.Activity a, String type) { 4112 final boolean systemApp = isSystemApp(a.info.applicationInfo); 4113 mActivities.put(a.getComponentName(), a); 4114 if (SHOW_INFO || Config.LOGV) Log.v( 4115 TAG, " " + type + " " + 4116 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":"); 4117 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name); 4118 int NI = a.intents.size(); 4119 for (int j=0; j<NI; j++) { 4120 PackageParser.ActivityIntentInfo intent = a.intents.get(j); 4121 if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) { 4122 intent.setPriority(0); 4123 Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity " 4124 + a.className + " with priority > 0, forcing to 0"); 4125 } 4126 if (SHOW_INFO || Config.LOGV) { 4127 Log.v(TAG, " IntentFilter:"); 4128 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 4129 } 4130 if (!intent.debugCheck()) { 4131 Log.w(TAG, "==> For Activity " + a.info.name); 4132 } 4133 addFilter(intent); 4134 } 4135 } 4136 4137 public final void removeActivity(PackageParser.Activity a, String type) { 4138 mActivities.remove(a.getComponentName()); 4139 if (SHOW_INFO || Config.LOGV) Log.v( 4140 TAG, " " + type + " " + 4141 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":"); 4142 if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name); 4143 int NI = a.intents.size(); 4144 for (int j=0; j<NI; j++) { 4145 PackageParser.ActivityIntentInfo intent = a.intents.get(j); 4146 if (SHOW_INFO || Config.LOGV) { 4147 Log.v(TAG, " IntentFilter:"); 4148 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 4149 } 4150 removeFilter(intent); 4151 } 4152 } 4153 4154 @Override 4155 protected boolean allowFilterResult( 4156 PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) { 4157 ActivityInfo filterAi = filter.activity.info; 4158 for (int i=dest.size()-1; i>=0; i--) { 4159 ActivityInfo destAi = dest.get(i).activityInfo; 4160 if (destAi.name == filterAi.name 4161 && destAi.packageName == filterAi.packageName) { 4162 return false; 4163 } 4164 } 4165 return true; 4166 } 4167 4168 @Override 4169 protected String packageForFilter(PackageParser.ActivityIntentInfo info) { 4170 return info.activity.owner.packageName; 4171 } 4172 4173 @Override 4174 protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info, 4175 int match) { 4176 if (!mSettings.isEnabledLP(info.activity.info, mFlags)) { 4177 return null; 4178 } 4179 final PackageParser.Activity activity = info.activity; 4180 if (mSafeMode && (activity.info.applicationInfo.flags 4181 &ApplicationInfo.FLAG_SYSTEM) == 0) { 4182 return null; 4183 } 4184 final ResolveInfo res = new ResolveInfo(); 4185 res.activityInfo = PackageParser.generateActivityInfo(activity, 4186 mFlags); 4187 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) { 4188 res.filter = info; 4189 } 4190 res.priority = info.getPriority(); 4191 res.preferredOrder = activity.owner.mPreferredOrder; 4192 //System.out.println("Result: " + res.activityInfo.className + 4193 // " = " + res.priority); 4194 res.match = match; 4195 res.isDefault = info.hasDefault; 4196 res.labelRes = info.labelRes; 4197 res.nonLocalizedLabel = info.nonLocalizedLabel; 4198 res.icon = info.icon; 4199 return res; 4200 } 4201 4202 @Override 4203 protected void sortResults(List<ResolveInfo> results) { 4204 Collections.sort(results, mResolvePrioritySorter); 4205 } 4206 4207 @Override 4208 protected void dumpFilter(PrintWriter out, String prefix, 4209 PackageParser.ActivityIntentInfo filter) { 4210 out.print(prefix); out.print( 4211 Integer.toHexString(System.identityHashCode(filter.activity))); 4212 out.print(' '); 4213 out.print(filter.activity.getComponentShortName()); 4214 out.print(" filter "); 4215 out.println(Integer.toHexString(System.identityHashCode(filter))); 4216 } 4217 4218 // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) { 4219 // final Iterator<ResolveInfo> i = resolveInfoList.iterator(); 4220 // final List<ResolveInfo> retList = Lists.newArrayList(); 4221 // while (i.hasNext()) { 4222 // final ResolveInfo resolveInfo = i.next(); 4223 // if (isEnabledLP(resolveInfo.activityInfo)) { 4224 // retList.add(resolveInfo); 4225 // } 4226 // } 4227 // return retList; 4228 // } 4229 4230 // Keys are String (activity class name), values are Activity. 4231 private final HashMap<ComponentName, PackageParser.Activity> mActivities 4232 = new HashMap<ComponentName, PackageParser.Activity>(); 4233 private int mFlags; 4234 } 4235 4236 private final class ServiceIntentResolver 4237 extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> { 4238 public List queryIntent(Intent intent, String resolvedType, boolean defaultOnly) { 4239 mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; 4240 return super.queryIntent(intent, resolvedType, defaultOnly); 4241 } 4242 4243 public List queryIntent(Intent intent, String resolvedType, int flags) { 4244 mFlags = flags; 4245 return super.queryIntent(intent, resolvedType, 4246 (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0); 4247 } 4248 4249 public List queryIntentForPackage(Intent intent, String resolvedType, int flags, 4250 ArrayList<PackageParser.Service> packageServices) { 4251 if (packageServices == null) { 4252 return null; 4253 } 4254 mFlags = flags; 4255 final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; 4256 int N = packageServices.size(); 4257 ArrayList<ArrayList<PackageParser.ServiceIntentInfo>> listCut = 4258 new ArrayList<ArrayList<PackageParser.ServiceIntentInfo>>(N); 4259 4260 ArrayList<PackageParser.ServiceIntentInfo> intentFilters; 4261 for (int i = 0; i < N; ++i) { 4262 intentFilters = packageServices.get(i).intents; 4263 if (intentFilters != null && intentFilters.size() > 0) { 4264 listCut.add(intentFilters); 4265 } 4266 } 4267 return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut); 4268 } 4269 4270 public final void addService(PackageParser.Service s) { 4271 mServices.put(s.getComponentName(), s); 4272 if (SHOW_INFO || Config.LOGV) Log.v( 4273 TAG, " " + (s.info.nonLocalizedLabel != null 4274 ? s.info.nonLocalizedLabel : s.info.name) + ":"); 4275 if (SHOW_INFO || Config.LOGV) Log.v( 4276 TAG, " Class=" + s.info.name); 4277 int NI = s.intents.size(); 4278 int j; 4279 for (j=0; j<NI; j++) { 4280 PackageParser.ServiceIntentInfo intent = s.intents.get(j); 4281 if (SHOW_INFO || Config.LOGV) { 4282 Log.v(TAG, " IntentFilter:"); 4283 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 4284 } 4285 if (!intent.debugCheck()) { 4286 Log.w(TAG, "==> For Service " + s.info.name); 4287 } 4288 addFilter(intent); 4289 } 4290 } 4291 4292 public final void removeService(PackageParser.Service s) { 4293 mServices.remove(s.getComponentName()); 4294 if (SHOW_INFO || Config.LOGV) Log.v( 4295 TAG, " " + (s.info.nonLocalizedLabel != null 4296 ? s.info.nonLocalizedLabel : s.info.name) + ":"); 4297 if (SHOW_INFO || Config.LOGV) Log.v( 4298 TAG, " Class=" + s.info.name); 4299 int NI = s.intents.size(); 4300 int j; 4301 for (j=0; j<NI; j++) { 4302 PackageParser.ServiceIntentInfo intent = s.intents.get(j); 4303 if (SHOW_INFO || Config.LOGV) { 4304 Log.v(TAG, " IntentFilter:"); 4305 intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); 4306 } 4307 removeFilter(intent); 4308 } 4309 } 4310 4311 @Override 4312 protected boolean allowFilterResult( 4313 PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) { 4314 ServiceInfo filterSi = filter.service.info; 4315 for (int i=dest.size()-1; i>=0; i--) { 4316 ServiceInfo destAi = dest.get(i).serviceInfo; 4317 if (destAi.name == filterSi.name 4318 && destAi.packageName == filterSi.packageName) { 4319 return false; 4320 } 4321 } 4322 return true; 4323 } 4324 4325 @Override 4326 protected String packageForFilter(PackageParser.ServiceIntentInfo info) { 4327 return info.service.owner.packageName; 4328 } 4329 4330 @Override 4331 protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter, 4332 int match) { 4333 final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter; 4334 if (!mSettings.isEnabledLP(info.service.info, mFlags)) { 4335 return null; 4336 } 4337 final PackageParser.Service service = info.service; 4338 if (mSafeMode && (service.info.applicationInfo.flags 4339 &ApplicationInfo.FLAG_SYSTEM) == 0) { 4340 return null; 4341 } 4342 final ResolveInfo res = new ResolveInfo(); 4343 res.serviceInfo = PackageParser.generateServiceInfo(service, 4344 mFlags); 4345 if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) { 4346 res.filter = filter; 4347 } 4348 res.priority = info.getPriority(); 4349 res.preferredOrder = service.owner.mPreferredOrder; 4350 //System.out.println("Result: " + res.activityInfo.className + 4351 // " = " + res.priority); 4352 res.match = match; 4353 res.isDefault = info.hasDefault; 4354 res.labelRes = info.labelRes; 4355 res.nonLocalizedLabel = info.nonLocalizedLabel; 4356 res.icon = info.icon; 4357 return res; 4358 } 4359 4360 @Override 4361 protected void sortResults(List<ResolveInfo> results) { 4362 Collections.sort(results, mResolvePrioritySorter); 4363 } 4364 4365 @Override 4366 protected void dumpFilter(PrintWriter out, String prefix, 4367 PackageParser.ServiceIntentInfo filter) { 4368 out.print(prefix); out.print( 4369 Integer.toHexString(System.identityHashCode(filter.service))); 4370 out.print(' '); 4371 out.print(filter.service.getComponentShortName()); 4372 out.print(" filter "); 4373 out.println(Integer.toHexString(System.identityHashCode(filter))); 4374 } 4375 4376 // List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) { 4377 // final Iterator<ResolveInfo> i = resolveInfoList.iterator(); 4378 // final List<ResolveInfo> retList = Lists.newArrayList(); 4379 // while (i.hasNext()) { 4380 // final ResolveInfo resolveInfo = (ResolveInfo) i; 4381 // if (isEnabledLP(resolveInfo.serviceInfo)) { 4382 // retList.add(resolveInfo); 4383 // } 4384 // } 4385 // return retList; 4386 // } 4387 4388 // Keys are String (activity class name), values are Activity. 4389 private final HashMap<ComponentName, PackageParser.Service> mServices 4390 = new HashMap<ComponentName, PackageParser.Service>(); 4391 private int mFlags; 4392 }; 4393 4394 private static final Comparator<ResolveInfo> mResolvePrioritySorter = 4395 new Comparator<ResolveInfo>() { 4396 public int compare(ResolveInfo r1, ResolveInfo r2) { 4397 int v1 = r1.priority; 4398 int v2 = r2.priority; 4399 //System.out.println("Comparing: q1=" + q1 + " q2=" + q2); 4400 if (v1 != v2) { 4401 return (v1 > v2) ? -1 : 1; 4402 } 4403 v1 = r1.preferredOrder; 4404 v2 = r2.preferredOrder; 4405 if (v1 != v2) { 4406 return (v1 > v2) ? -1 : 1; 4407 } 4408 if (r1.isDefault != r2.isDefault) { 4409 return r1.isDefault ? -1 : 1; 4410 } 4411 v1 = r1.match; 4412 v2 = r2.match; 4413 //System.out.println("Comparing: m1=" + m1 + " m2=" + m2); 4414 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0); 4415 } 4416 }; 4417 4418 private static final Comparator<ProviderInfo> mProviderInitOrderSorter = 4419 new Comparator<ProviderInfo>() { 4420 public int compare(ProviderInfo p1, ProviderInfo p2) { 4421 final int v1 = p1.initOrder; 4422 final int v2 = p2.initOrder; 4423 return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0); 4424 } 4425 }; 4426 4427 private static final void sendPackageBroadcast(String action, String pkg, 4428 Bundle extras, IIntentReceiver finishedReceiver) { 4429 IActivityManager am = ActivityManagerNative.getDefault(); 4430 if (am != null) { 4431 try { 4432 final Intent intent = new Intent(action, 4433 pkg != null ? Uri.fromParts("package", pkg, null) : null); 4434 if (extras != null) { 4435 intent.putExtras(extras); 4436 } 4437 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 4438 am.broadcastIntent(null, intent, null, finishedReceiver, 4439 0, null, null, null, finishedReceiver != null, false); 4440 } catch (RemoteException ex) { 4441 } 4442 } 4443 } 4444 4445 public String nextPackageToClean(String lastPackage) { 4446 synchronized (mPackages) { 4447 if (!mMediaMounted) { 4448 // If the external storage is no longer mounted at this point, 4449 // the caller may not have been able to delete all of this 4450 // packages files and can not delete any more. Bail. 4451 return null; 4452 } 4453 if (lastPackage != null) { 4454 mSettings.mPackagesToBeCleaned.remove(lastPackage); 4455 } 4456 return mSettings.mPackagesToBeCleaned.size() > 0 4457 ? mSettings.mPackagesToBeCleaned.get(0) : null; 4458 } 4459 } 4460 4461 void schedulePackageCleaning(String packageName) { 4462 mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE, packageName)); 4463 } 4464 4465 void startCleaningPackages() { 4466 synchronized (mPackages) { 4467 if (!mMediaMounted) { 4468 return; 4469 } 4470 if (mSettings.mPackagesToBeCleaned.size() <= 0) { 4471 return; 4472 } 4473 } 4474 Intent intent = new Intent(PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE); 4475 intent.setComponent(DEFAULT_CONTAINER_COMPONENT); 4476 IActivityManager am = ActivityManagerNative.getDefault(); 4477 if (am != null) { 4478 try { 4479 am.startService(null, intent, null); 4480 } catch (RemoteException e) { 4481 } 4482 } 4483 } 4484 4485 private final class AppDirObserver extends FileObserver { 4486 public AppDirObserver(String path, int mask, boolean isrom) { 4487 super(path, mask); 4488 mRootDir = path; 4489 mIsRom = isrom; 4490 } 4491 4492 public void onEvent(int event, String path) { 4493 String removedPackage = null; 4494 int removedUid = -1; 4495 String addedPackage = null; 4496 int addedUid = -1; 4497 4498 synchronized (mInstallLock) { 4499 String fullPathStr = null; 4500 File fullPath = null; 4501 if (path != null) { 4502 fullPath = new File(mRootDir, path); 4503 fullPathStr = fullPath.getPath(); 4504 } 4505 4506 if (Config.LOGV) Log.v( 4507 TAG, "File " + fullPathStr + " changed: " 4508 + Integer.toHexString(event)); 4509 4510 if (!isPackageFilename(path)) { 4511 if (Config.LOGV) Log.v( 4512 TAG, "Ignoring change of non-package file: " + fullPathStr); 4513 return; 4514 } 4515 4516 // Ignore packages that are being installed or 4517 // have just been installed. 4518 if (ignoreCodePath(fullPathStr)) { 4519 return; 4520 } 4521 PackageParser.Package p = null; 4522 synchronized (mPackages) { 4523 p = mAppDirs.get(fullPathStr); 4524 } 4525 if ((event&REMOVE_EVENTS) != 0) { 4526 if (p != null) { 4527 removePackageLI(p, true); 4528 removedPackage = p.applicationInfo.packageName; 4529 removedUid = p.applicationInfo.uid; 4530 } 4531 } 4532 4533 if ((event&ADD_EVENTS) != 0) { 4534 if (p == null) { 4535 p = scanPackageLI(fullPath, 4536 (mIsRom ? PackageParser.PARSE_IS_SYSTEM 4537 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) | 4538 PackageParser.PARSE_CHATTY | 4539 PackageParser.PARSE_MUST_BE_APK, 4540 SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME, 4541 System.currentTimeMillis()); 4542 if (p != null) { 4543 synchronized (mPackages) { 4544 updatePermissionsLP(p.packageName, p, 4545 p.permissions.size() > 0, false, false); 4546 } 4547 addedPackage = p.applicationInfo.packageName; 4548 addedUid = p.applicationInfo.uid; 4549 } 4550 } 4551 } 4552 4553 synchronized (mPackages) { 4554 mSettings.writeLP(); 4555 } 4556 } 4557 4558 if (removedPackage != null) { 4559 Bundle extras = new Bundle(1); 4560 extras.putInt(Intent.EXTRA_UID, removedUid); 4561 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false); 4562 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, 4563 extras, null); 4564 } 4565 if (addedPackage != null) { 4566 Bundle extras = new Bundle(1); 4567 extras.putInt(Intent.EXTRA_UID, addedUid); 4568 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage, 4569 extras, null); 4570 } 4571 } 4572 4573 private final String mRootDir; 4574 private final boolean mIsRom; 4575 } 4576 4577 /* Called when a downloaded package installation has been confirmed by the user */ 4578 public void installPackage( 4579 final Uri packageURI, final IPackageInstallObserver observer, final int flags) { 4580 installPackage(packageURI, observer, flags, null); 4581 } 4582 4583 /* Called when a downloaded package installation has been confirmed by the user */ 4584 public void installPackage( 4585 final Uri packageURI, final IPackageInstallObserver observer, final int flags, 4586 final String installerPackageName) { 4587 mContext.enforceCallingOrSelfPermission( 4588 android.Manifest.permission.INSTALL_PACKAGES, null); 4589 4590 Message msg = mHandler.obtainMessage(INIT_COPY); 4591 msg.obj = new InstallParams(packageURI, observer, flags, 4592 installerPackageName); 4593 mHandler.sendMessage(msg); 4594 } 4595 4596 public void finishPackageInstall(int token) { 4597 if (DEBUG_INSTALL) Log.v(TAG, "BM finishing package install for " + token); 4598 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); 4599 mHandler.sendMessage(msg); 4600 } 4601 4602 private void processPendingInstall(final InstallArgs args, final int currentStatus) { 4603 // Queue up an async operation since the package installation may take a little while. 4604 mHandler.post(new Runnable() { 4605 public void run() { 4606 mHandler.removeCallbacks(this); 4607 // Result object to be returned 4608 PackageInstalledInfo res = new PackageInstalledInfo(); 4609 res.returnCode = currentStatus; 4610 res.uid = -1; 4611 res.pkg = null; 4612 res.removedInfo = new PackageRemovedInfo(); 4613 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) { 4614 args.doPreInstall(res.returnCode); 4615 synchronized (mInstallLock) { 4616 installPackageLI(args, true, res); 4617 } 4618 args.doPostInstall(res.returnCode); 4619 } 4620 4621 // A restore should be performed at this point if (a) the install 4622 // succeeded, (b) the operation is not an update, and (c) the new 4623 // package has a backupAgent defined. 4624 final boolean update = res.removedInfo.removedPackage != null; 4625 boolean doRestore = (!update 4626 && res.pkg != null 4627 && res.pkg.applicationInfo.backupAgentName != null); 4628 4629 // Set up the post-install work request bookkeeping. This will be used 4630 // and cleaned up by the post-install event handling regardless of whether 4631 // there's a restore pass performed. Token values are >= 1. 4632 int token; 4633 if (mNextInstallToken < 0) mNextInstallToken = 1; 4634 token = mNextInstallToken++; 4635 4636 PostInstallData data = new PostInstallData(args, res); 4637 mRunningInstalls.put(token, data); 4638 if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); 4639 4640 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) { 4641 // Pass responsibility to the Backup Manager. It will perform a 4642 // restore if appropriate, then pass responsibility back to the 4643 // Package Manager to run the post-install observer callbacks 4644 // and broadcasts. 4645 IBackupManager bm = IBackupManager.Stub.asInterface( 4646 ServiceManager.getService(Context.BACKUP_SERVICE)); 4647 if (bm != null) { 4648 if (DEBUG_INSTALL) Log.v(TAG, "token " + token 4649 + " to BM for possible restore"); 4650 try { 4651 bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token); 4652 } catch (RemoteException e) { 4653 // can't happen; the backup manager is local 4654 } catch (Exception e) { 4655 Slog.e(TAG, "Exception trying to enqueue restore", e); 4656 doRestore = false; 4657 } 4658 } else { 4659 Slog.e(TAG, "Backup Manager not found!"); 4660 doRestore = false; 4661 } 4662 } 4663 4664 if (!doRestore) { 4665 // No restore possible, or the Backup Manager was mysteriously not 4666 // available -- just fire the post-install work request directly. 4667 if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token); 4668 Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); 4669 mHandler.sendMessage(msg); 4670 } 4671 } 4672 }); 4673 } 4674 4675 abstract class HandlerParams { 4676 final static int MAX_RETRIES = 4; 4677 int retry = 0; 4678 final void startCopy() { 4679 try { 4680 if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy"); 4681 retry++; 4682 if (retry > MAX_RETRIES) { 4683 Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up"); 4684 mHandler.sendEmptyMessage(MCS_GIVE_UP); 4685 handleServiceError(); 4686 return; 4687 } else { 4688 handleStartCopy(); 4689 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_UNBIND"); 4690 mHandler.sendEmptyMessage(MCS_UNBIND); 4691 } 4692 } catch (RemoteException e) { 4693 if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT"); 4694 mHandler.sendEmptyMessage(MCS_RECONNECT); 4695 } 4696 handleReturnCode(); 4697 } 4698 4699 final void serviceError() { 4700 if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError"); 4701 handleServiceError(); 4702 handleReturnCode(); 4703 } 4704 abstract void handleStartCopy() throws RemoteException; 4705 abstract void handleServiceError(); 4706 abstract void handleReturnCode(); 4707 } 4708 4709 class InstallParams extends HandlerParams { 4710 final IPackageInstallObserver observer; 4711 int flags; 4712 final Uri packageURI; 4713 final String installerPackageName; 4714 private InstallArgs mArgs; 4715 private int mRet; 4716 InstallParams(Uri packageURI, 4717 IPackageInstallObserver observer, int flags, 4718 String installerPackageName) { 4719 this.packageURI = packageURI; 4720 this.flags = flags; 4721 this.observer = observer; 4722 this.installerPackageName = installerPackageName; 4723 } 4724 4725 private int installLocationPolicy(PackageInfoLite pkgLite, int flags) { 4726 String packageName = pkgLite.packageName; 4727 int installLocation = pkgLite.installLocation; 4728 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; 4729 synchronized (mPackages) { 4730 PackageParser.Package pkg = mPackages.get(packageName); 4731 if (pkg != null) { 4732 if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { 4733 // Check for updated system application. 4734 if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 4735 if (onSd) { 4736 Slog.w(TAG, "Cannot install update to system app on sdcard"); 4737 return PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION; 4738 } 4739 return PackageHelper.RECOMMEND_INSTALL_INTERNAL; 4740 } else { 4741 if (onSd) { 4742 // Install flag overrides everything. 4743 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; 4744 } 4745 // If current upgrade specifies particular preference 4746 if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) { 4747 // Application explicitly specified internal. 4748 return PackageHelper.RECOMMEND_INSTALL_INTERNAL; 4749 } else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) { 4750 // App explictly prefers external. Let policy decide 4751 } else { 4752 // Prefer previous location 4753 if (isExternal(pkg)) { 4754 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; 4755 } 4756 return PackageHelper.RECOMMEND_INSTALL_INTERNAL; 4757 } 4758 } 4759 } else { 4760 // Invalid install. Return error code 4761 return PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS; 4762 } 4763 } 4764 } 4765 // All the special cases have been taken care of. 4766 // Return result based on recommended install location. 4767 if (onSd) { 4768 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL; 4769 } 4770 return pkgLite.recommendedInstallLocation; 4771 } 4772 4773 /* 4774 * Invoke remote method to get package information and install 4775 * location values. Override install location based on default 4776 * policy if needed and then create install arguments based 4777 * on the install location. 4778 */ 4779 public void handleStartCopy() throws RemoteException { 4780 int ret = PackageManager.INSTALL_SUCCEEDED; 4781 boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; 4782 boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0; 4783 boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0; 4784 if (onInt && onSd) { 4785 // Check if both bits are set. 4786 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external"); 4787 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; 4788 } else if (fwdLocked && onSd) { 4789 // Check for forward locked apps 4790 Slog.w(TAG, "Cannot install fwd locked apps on sdcard"); 4791 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; 4792 } else { 4793 // Remote call to find out default install location 4794 final PackageInfoLite pkgLite; 4795 try { 4796 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, 4797 Intent.FLAG_GRANT_READ_URI_PERMISSION); 4798 pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags); 4799 } finally { 4800 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); 4801 } 4802 4803 int loc = pkgLite.recommendedInstallLocation; 4804 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){ 4805 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; 4806 } else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){ 4807 ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS; 4808 } else if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){ 4809 ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 4810 } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) { 4811 ret = PackageManager.INSTALL_FAILED_INVALID_APK; 4812 } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) { 4813 ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE; 4814 } else { 4815 // Override with defaults if needed. 4816 loc = installLocationPolicy(pkgLite, flags); 4817 if (!onSd && !onInt) { 4818 // Override install location with flags 4819 if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { 4820 // Set the flag to install on external media. 4821 flags |= PackageManager.INSTALL_EXTERNAL; 4822 flags &= ~PackageManager.INSTALL_INTERNAL; 4823 } else { 4824 // Make sure the flag for installing on external 4825 // media is unset 4826 flags |= PackageManager.INSTALL_INTERNAL; 4827 flags &= ~PackageManager.INSTALL_EXTERNAL; 4828 } 4829 } 4830 } 4831 } 4832 // Create the file args now. 4833 mArgs = createInstallArgs(this); 4834 if (ret == PackageManager.INSTALL_SUCCEEDED) { 4835 // Create copy only if we are not in an erroneous state. 4836 // Remote call to initiate copy using temporary file 4837 ret = mArgs.copyApk(mContainerService, true); 4838 } 4839 mRet = ret; 4840 } 4841 4842 @Override 4843 void handleReturnCode() { 4844 // If mArgs is null, then MCS couldn't be reached. When it 4845 // reconnects, it will try again to install. At that point, this 4846 // will succeed. 4847 if (mArgs != null) { 4848 processPendingInstall(mArgs, mRet); 4849 } 4850 } 4851 4852 @Override 4853 void handleServiceError() { 4854 mArgs = createInstallArgs(this); 4855 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; 4856 } 4857 } 4858 4859 /* 4860 * Utility class used in movePackage api. 4861 * srcArgs and targetArgs are not set for invalid flags and make 4862 * sure to do null checks when invoking methods on them. 4863 * We probably want to return ErrorPrams for both failed installs 4864 * and moves. 4865 */ 4866 class MoveParams extends HandlerParams { 4867 final IPackageMoveObserver observer; 4868 final int flags; 4869 final String packageName; 4870 final InstallArgs srcArgs; 4871 final InstallArgs targetArgs; 4872 int mRet; 4873 4874 MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags, 4875 String packageName, String dataDir) { 4876 this.srcArgs = srcArgs; 4877 this.observer = observer; 4878 this.flags = flags; 4879 this.packageName = packageName; 4880 if (srcArgs != null) { 4881 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath())); 4882 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir); 4883 } else { 4884 targetArgs = null; 4885 } 4886 } 4887 4888 public void handleStartCopy() throws RemoteException { 4889 mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 4890 // Check for storage space on target medium 4891 if (!targetArgs.checkFreeStorage(mContainerService)) { 4892 Log.w(TAG, "Insufficient storage to install"); 4893 return; 4894 } 4895 // Create the file args now. 4896 mRet = targetArgs.copyApk(mContainerService, false); 4897 targetArgs.doPreInstall(mRet); 4898 if (DEBUG_SD_INSTALL) { 4899 StringBuilder builder = new StringBuilder(); 4900 if (srcArgs != null) { 4901 builder.append("src: "); 4902 builder.append(srcArgs.getCodePath()); 4903 } 4904 if (targetArgs != null) { 4905 builder.append(" target : "); 4906 builder.append(targetArgs.getCodePath()); 4907 } 4908 Log.i(TAG, builder.toString()); 4909 } 4910 } 4911 4912 @Override 4913 void handleReturnCode() { 4914 targetArgs.doPostInstall(mRet); 4915 int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR; 4916 if (mRet == PackageManager.INSTALL_SUCCEEDED) { 4917 currentStatus = PackageManager.MOVE_SUCCEEDED; 4918 } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){ 4919 currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; 4920 } 4921 processPendingMove(this, currentStatus); 4922 } 4923 4924 @Override 4925 void handleServiceError() { 4926 mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR; 4927 } 4928 } 4929 4930 private InstallArgs createInstallArgs(InstallParams params) { 4931 if (installOnSd(params.flags)) { 4932 return new SdInstallArgs(params); 4933 } else { 4934 return new FileInstallArgs(params); 4935 } 4936 } 4937 4938 private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath, 4939 String nativeLibraryPath) { 4940 if (installOnSd(flags)) { 4941 return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); 4942 } else { 4943 return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath); 4944 } 4945 } 4946 4947 // Used by package mover 4948 private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) { 4949 if (installOnSd(flags)) { 4950 String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME); 4951 return new SdInstallArgs(packageURI, cid); 4952 } else { 4953 return new FileInstallArgs(packageURI, pkgName, dataDir); 4954 } 4955 } 4956 4957 static abstract class InstallArgs { 4958 final IPackageInstallObserver observer; 4959 // Always refers to PackageManager flags only 4960 final int flags; 4961 final Uri packageURI; 4962 final String installerPackageName; 4963 4964 InstallArgs(Uri packageURI, 4965 IPackageInstallObserver observer, int flags, 4966 String installerPackageName) { 4967 this.packageURI = packageURI; 4968 this.flags = flags; 4969 this.observer = observer; 4970 this.installerPackageName = installerPackageName; 4971 } 4972 4973 abstract void createCopyFile(); 4974 abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException; 4975 abstract int doPreInstall(int status); 4976 abstract boolean doRename(int status, String pkgName, String oldCodePath); 4977 abstract int doPostInstall(int status); 4978 abstract String getCodePath(); 4979 abstract String getResourcePath(); 4980 abstract String getNativeLibraryPath(); 4981 // Need installer lock especially for dex file removal. 4982 abstract void cleanUpResourcesLI(); 4983 abstract boolean doPostDeleteLI(boolean delete); 4984 abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException; 4985 } 4986 4987 class FileInstallArgs extends InstallArgs { 4988 File installDir; 4989 String codeFileName; 4990 String resourceFileName; 4991 String libraryPath; 4992 boolean created = false; 4993 4994 FileInstallArgs(InstallParams params) { 4995 super(params.packageURI, params.observer, 4996 params.flags, params.installerPackageName); 4997 } 4998 4999 FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { 5000 super(null, null, 0, null); 5001 File codeFile = new File(fullCodePath); 5002 installDir = codeFile.getParentFile(); 5003 codeFileName = fullCodePath; 5004 resourceFileName = fullResourcePath; 5005 libraryPath = nativeLibraryPath; 5006 } 5007 5008 FileInstallArgs(Uri packageURI, String pkgName, String dataDir) { 5009 super(packageURI, null, 0, null); 5010 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; 5011 String apkName = getNextCodePath(null, pkgName, ".apk"); 5012 codeFileName = new File(installDir, apkName + ".apk").getPath(); 5013 resourceFileName = getResourcePathFromCodePath(); 5014 libraryPath = new File(dataDir, LIB_DIR_NAME).getPath(); 5015 } 5016 5017 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { 5018 try { 5019 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, 5020 Intent.FLAG_GRANT_READ_URI_PERMISSION); 5021 return imcs.checkFreeStorage(false, packageURI); 5022 } finally { 5023 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); 5024 } 5025 } 5026 5027 String getCodePath() { 5028 return codeFileName; 5029 } 5030 5031 void createCopyFile() { 5032 installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir; 5033 codeFileName = createTempPackageFile(installDir).getPath(); 5034 resourceFileName = getResourcePathFromCodePath(); 5035 created = true; 5036 } 5037 5038 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { 5039 if (temp) { 5040 // Generate temp file name 5041 createCopyFile(); 5042 } 5043 // Get a ParcelFileDescriptor to write to the output file 5044 File codeFile = new File(codeFileName); 5045 if (!created) { 5046 try { 5047 codeFile.createNewFile(); 5048 // Set permissions 5049 if (!setPermissions()) { 5050 // Failed setting permissions. 5051 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5052 } 5053 } catch (IOException e) { 5054 Slog.w(TAG, "Failed to create file " + codeFile); 5055 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5056 } 5057 } 5058 ParcelFileDescriptor out = null; 5059 try { 5060 out = ParcelFileDescriptor.open(codeFile, ParcelFileDescriptor.MODE_READ_WRITE); 5061 } catch (FileNotFoundException e) { 5062 Slog.e(TAG, "Failed to create file descritpor for : " + codeFileName); 5063 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5064 } 5065 // Copy the resource now 5066 int ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5067 try { 5068 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, 5069 Intent.FLAG_GRANT_READ_URI_PERMISSION); 5070 if (imcs.copyResource(packageURI, out)) { 5071 ret = PackageManager.INSTALL_SUCCEEDED; 5072 } 5073 } finally { 5074 try { if (out != null) out.close(); } catch (IOException e) {} 5075 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); 5076 } 5077 5078 return ret; 5079 } 5080 5081 int doPreInstall(int status) { 5082 if (status != PackageManager.INSTALL_SUCCEEDED) { 5083 cleanUp(); 5084 } 5085 return status; 5086 } 5087 5088 boolean doRename(int status, final String pkgName, String oldCodePath) { 5089 if (status != PackageManager.INSTALL_SUCCEEDED) { 5090 cleanUp(); 5091 return false; 5092 } else { 5093 // Rename based on packageName 5094 File codeFile = new File(getCodePath()); 5095 String apkName = getNextCodePath(oldCodePath, pkgName, ".apk"); 5096 File desFile = new File(installDir, apkName + ".apk"); 5097 if (!codeFile.renameTo(desFile)) { 5098 return false; 5099 } 5100 // Reset paths since the file has been renamed. 5101 codeFileName = desFile.getPath(); 5102 resourceFileName = getResourcePathFromCodePath(); 5103 // Set permissions 5104 if (!setPermissions()) { 5105 // Failed setting permissions. 5106 return false; 5107 } 5108 return true; 5109 } 5110 } 5111 5112 int doPostInstall(int status) { 5113 if (status != PackageManager.INSTALL_SUCCEEDED) { 5114 cleanUp(); 5115 } 5116 return status; 5117 } 5118 5119 String getResourcePath() { 5120 return resourceFileName; 5121 } 5122 5123 String getResourcePathFromCodePath() { 5124 String codePath = getCodePath(); 5125 if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) { 5126 String apkNameOnly = getApkName(codePath); 5127 return mAppInstallDir.getPath() + "/" + apkNameOnly + ".zip"; 5128 } else { 5129 return codePath; 5130 } 5131 } 5132 5133 @Override 5134 String getNativeLibraryPath() { 5135 return libraryPath; 5136 } 5137 5138 private boolean cleanUp() { 5139 boolean ret = true; 5140 String sourceDir = getCodePath(); 5141 String publicSourceDir = getResourcePath(); 5142 if (sourceDir != null) { 5143 File sourceFile = new File(sourceDir); 5144 if (!sourceFile.exists()) { 5145 Slog.w(TAG, "Package source " + sourceDir + " does not exist."); 5146 ret = false; 5147 } 5148 // Delete application's code and resources 5149 sourceFile.delete(); 5150 } 5151 if (publicSourceDir != null && !publicSourceDir.equals(sourceDir)) { 5152 final File publicSourceFile = new File(publicSourceDir); 5153 if (!publicSourceFile.exists()) { 5154 Slog.w(TAG, "Package public source " + publicSourceFile + " does not exist."); 5155 } 5156 if (publicSourceFile.exists()) { 5157 publicSourceFile.delete(); 5158 } 5159 } 5160 return ret; 5161 } 5162 5163 void cleanUpResourcesLI() { 5164 String sourceDir = getCodePath(); 5165 if (cleanUp() && mInstaller != null) { 5166 int retCode = mInstaller.rmdex(sourceDir); 5167 if (retCode < 0) { 5168 Slog.w(TAG, "Couldn't remove dex file for package: " 5169 + " at location " 5170 + sourceDir + ", retcode=" + retCode); 5171 // we don't consider this to be a failure of the core package deletion 5172 } 5173 } 5174 } 5175 5176 private boolean setPermissions() { 5177 // TODO Do this in a more elegant way later on. for now just a hack 5178 if (!isFwdLocked()) { 5179 final int filePermissions = 5180 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP 5181 |FileUtils.S_IROTH; 5182 int retCode = FileUtils.setPermissions(getCodePath(), filePermissions, -1, -1); 5183 if (retCode != 0) { 5184 Slog.e(TAG, "Couldn't set new package file permissions for " + 5185 getCodePath() 5186 + ". The return code was: " + retCode); 5187 // TODO Define new internal error 5188 return false; 5189 } 5190 return true; 5191 } 5192 return true; 5193 } 5194 5195 boolean doPostDeleteLI(boolean delete) { 5196 // XXX err, shouldn't we respect the delete flag? 5197 cleanUpResourcesLI(); 5198 return true; 5199 } 5200 5201 private boolean isFwdLocked() { 5202 return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0; 5203 } 5204 } 5205 5206 class SdInstallArgs extends InstallArgs { 5207 static final String RES_FILE_NAME = "pkg.apk"; 5208 5209 String cid; 5210 String packagePath; 5211 String libraryPath; 5212 5213 SdInstallArgs(InstallParams params) { 5214 super(params.packageURI, params.observer, 5215 params.flags, params.installerPackageName); 5216 } 5217 5218 SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { 5219 super(null, null, PackageManager.INSTALL_EXTERNAL, null); 5220 // Extract cid from fullCodePath 5221 int eidx = fullCodePath.lastIndexOf("/"); 5222 String subStr1 = fullCodePath.substring(0, eidx); 5223 int sidx = subStr1.lastIndexOf("/"); 5224 cid = subStr1.substring(sidx+1, eidx); 5225 setCachePath(subStr1); 5226 } 5227 5228 SdInstallArgs(String cid) { 5229 super(null, null, PackageManager.INSTALL_EXTERNAL, null); 5230 this.cid = cid; 5231 setCachePath(PackageHelper.getSdDir(cid)); 5232 } 5233 5234 SdInstallArgs(Uri packageURI, String cid) { 5235 super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null); 5236 this.cid = cid; 5237 } 5238 5239 void createCopyFile() { 5240 cid = getTempContainerId(); 5241 } 5242 5243 boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException { 5244 try { 5245 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, 5246 Intent.FLAG_GRANT_READ_URI_PERMISSION); 5247 return imcs.checkFreeStorage(true, packageURI); 5248 } finally { 5249 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); 5250 } 5251 } 5252 5253 int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException { 5254 if (temp) { 5255 createCopyFile(); 5256 } 5257 5258 final String newCachePath; 5259 try { 5260 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI, 5261 Intent.FLAG_GRANT_READ_URI_PERMISSION); 5262 newCachePath = imcs.copyResourceToContainer(packageURI, cid, 5263 getEncryptKey(), RES_FILE_NAME); 5264 } finally { 5265 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION); 5266 } 5267 5268 if (newCachePath != null) { 5269 setCachePath(newCachePath); 5270 return PackageManager.INSTALL_SUCCEEDED; 5271 } else { 5272 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; 5273 } 5274 } 5275 5276 @Override 5277 String getCodePath() { 5278 return packagePath; 5279 } 5280 5281 @Override 5282 String getResourcePath() { 5283 return packagePath; 5284 } 5285 5286 @Override 5287 String getNativeLibraryPath() { 5288 return libraryPath; 5289 } 5290 5291 int doPreInstall(int status) { 5292 if (status != PackageManager.INSTALL_SUCCEEDED) { 5293 // Destroy container 5294 PackageHelper.destroySdDir(cid); 5295 } else { 5296 boolean mounted = PackageHelper.isContainerMounted(cid); 5297 if (!mounted) { 5298 String newCachePath = PackageHelper.mountSdDir(cid, getEncryptKey(), 5299 Process.SYSTEM_UID); 5300 if (newCachePath != null) { 5301 setCachePath(newCachePath); 5302 } else { 5303 return PackageManager.INSTALL_FAILED_CONTAINER_ERROR; 5304 } 5305 } 5306 } 5307 return status; 5308 } 5309 5310 boolean doRename(int status, final String pkgName, 5311 String oldCodePath) { 5312 String newCacheId = getNextCodePath(oldCodePath, pkgName, "/" + RES_FILE_NAME); 5313 String newCachePath = null; 5314 if (PackageHelper.isContainerMounted(cid)) { 5315 // Unmount the container 5316 if (!PackageHelper.unMountSdDir(cid)) { 5317 Slog.i(TAG, "Failed to unmount " + cid + " before renaming"); 5318 return false; 5319 } 5320 } 5321 if (!PackageHelper.renameSdDir(cid, newCacheId)) { 5322 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId + 5323 " which might be stale. Will try to clean up."); 5324 // Clean up the stale container and proceed to recreate. 5325 if (!PackageHelper.destroySdDir(newCacheId)) { 5326 Slog.e(TAG, "Very strange. Cannot clean up stale container " + newCacheId); 5327 return false; 5328 } 5329 // Successfully cleaned up stale container. Try to rename again. 5330 if (!PackageHelper.renameSdDir(cid, newCacheId)) { 5331 Slog.e(TAG, "Failed to rename " + cid + " to " + newCacheId 5332 + " inspite of cleaning it up."); 5333 return false; 5334 } 5335 } 5336 if (!PackageHelper.isContainerMounted(newCacheId)) { 5337 Slog.w(TAG, "Mounting container " + newCacheId); 5338 newCachePath = PackageHelper.mountSdDir(newCacheId, 5339 getEncryptKey(), Process.SYSTEM_UID); 5340 } else { 5341 newCachePath = PackageHelper.getSdDir(newCacheId); 5342 } 5343 if (newCachePath == null) { 5344 Slog.w(TAG, "Failed to get cache path for " + newCacheId); 5345 return false; 5346 } 5347 Log.i(TAG, "Succesfully renamed " + cid + 5348 " to " + newCacheId + 5349 " at new path: " + newCachePath); 5350 cid = newCacheId; 5351 setCachePath(newCachePath); 5352 return true; 5353 } 5354 5355 private void setCachePath(String newCachePath) { 5356 File cachePath = new File(newCachePath); 5357 libraryPath = new File(cachePath, LIB_DIR_NAME).getPath(); 5358 packagePath = new File(cachePath, RES_FILE_NAME).getPath(); 5359 } 5360 5361 int doPostInstall(int status) { 5362 if (status != PackageManager.INSTALL_SUCCEEDED) { 5363 cleanUp(); 5364 } else { 5365 boolean mounted = PackageHelper.isContainerMounted(cid); 5366 if (!mounted) { 5367 PackageHelper.mountSdDir(cid, 5368 getEncryptKey(), Process.myUid()); 5369 } 5370 } 5371 return status; 5372 } 5373 5374 private void cleanUp() { 5375 // Destroy secure container 5376 PackageHelper.destroySdDir(cid); 5377 } 5378 5379 void cleanUpResourcesLI() { 5380 String sourceFile = getCodePath(); 5381 // Remove dex file 5382 if (mInstaller != null) { 5383 int retCode = mInstaller.rmdex(sourceFile); 5384 if (retCode < 0) { 5385 Slog.w(TAG, "Couldn't remove dex file for package: " 5386 + " at location " 5387 + sourceFile.toString() + ", retcode=" + retCode); 5388 // we don't consider this to be a failure of the core package deletion 5389 } 5390 } 5391 cleanUp(); 5392 } 5393 5394 boolean matchContainer(String app) { 5395 if (cid.startsWith(app)) { 5396 return true; 5397 } 5398 return false; 5399 } 5400 5401 String getPackageName() { 5402 int idx = cid.lastIndexOf("-"); 5403 if (idx == -1) { 5404 return cid; 5405 } 5406 return cid.substring(0, idx); 5407 } 5408 5409 boolean doPostDeleteLI(boolean delete) { 5410 boolean ret = false; 5411 boolean mounted = PackageHelper.isContainerMounted(cid); 5412 if (mounted) { 5413 // Unmount first 5414 ret = PackageHelper.unMountSdDir(cid); 5415 } 5416 if (ret && delete) { 5417 cleanUpResourcesLI(); 5418 } 5419 return ret; 5420 } 5421 }; 5422 5423 // Utility method used to create code paths based on package name and available index. 5424 private static String getNextCodePath(String oldCodePath, String prefix, String suffix) { 5425 String idxStr = ""; 5426 int idx = 1; 5427 // Fall back to default value of idx=1 if prefix is not 5428 // part of oldCodePath 5429 if (oldCodePath != null) { 5430 String subStr = oldCodePath; 5431 // Drop the suffix right away 5432 if (subStr.endsWith(suffix)) { 5433 subStr = subStr.substring(0, subStr.length() - suffix.length()); 5434 } 5435 // If oldCodePath already contains prefix find out the 5436 // ending index to either increment or decrement. 5437 int sidx = subStr.lastIndexOf(prefix); 5438 if (sidx != -1) { 5439 subStr = subStr.substring(sidx + prefix.length()); 5440 if (subStr != null) { 5441 if (subStr.startsWith(INSTALL_PACKAGE_SUFFIX)) { 5442 subStr = subStr.substring(INSTALL_PACKAGE_SUFFIX.length()); 5443 } 5444 try { 5445 idx = Integer.parseInt(subStr); 5446 if (idx <= 1) { 5447 idx++; 5448 } else { 5449 idx--; 5450 } 5451 } catch(NumberFormatException e) { 5452 } 5453 } 5454 } 5455 } 5456 idxStr = INSTALL_PACKAGE_SUFFIX + Integer.toString(idx); 5457 return prefix + idxStr; 5458 } 5459 5460 // Utility method used to ignore ADD/REMOVE events 5461 // by directory observer. 5462 private static boolean ignoreCodePath(String fullPathStr) { 5463 String apkName = getApkName(fullPathStr); 5464 int idx = apkName.lastIndexOf(INSTALL_PACKAGE_SUFFIX); 5465 if (idx != -1 && ((idx+1) < apkName.length())) { 5466 // Make sure the package ends with a numeral 5467 String version = apkName.substring(idx+1); 5468 try { 5469 Integer.parseInt(version); 5470 return true; 5471 } catch (NumberFormatException e) {} 5472 } 5473 return false; 5474 } 5475 5476 // Utility method that returns the relative package path with respect 5477 // to the installation directory. Like say for /data/data/com.test-1.apk 5478 // string com.test-1 is returned. 5479 static String getApkName(String codePath) { 5480 if (codePath == null) { 5481 return null; 5482 } 5483 int sidx = codePath.lastIndexOf("/"); 5484 int eidx = codePath.lastIndexOf("."); 5485 if (eidx == -1) { 5486 eidx = codePath.length(); 5487 } else if (eidx == 0) { 5488 Slog.w(TAG, " Invalid code path, "+ codePath + " Not a valid apk name"); 5489 return null; 5490 } 5491 return codePath.substring(sidx+1, eidx); 5492 } 5493 5494 class PackageInstalledInfo { 5495 String name; 5496 int uid; 5497 PackageParser.Package pkg; 5498 int returnCode; 5499 PackageRemovedInfo removedInfo; 5500 } 5501 5502 /* 5503 * Install a non-existing package. 5504 */ 5505 private void installNewPackageLI(PackageParser.Package pkg, 5506 int parseFlags, 5507 int scanMode, 5508 String installerPackageName, PackageInstalledInfo res) { 5509 // Remember this for later, in case we need to rollback this install 5510 String pkgName = pkg.packageName; 5511 5512 boolean dataDirExists = getDataPathForPackage(pkg).exists(); 5513 res.name = pkgName; 5514 synchronized(mPackages) { 5515 if (mSettings.mRenamedPackages.containsKey(pkgName)) { 5516 // A package with the same name is already installed, though 5517 // it has been renamed to an older name. The package we 5518 // are trying to install should be installed as an update to 5519 // the existing one, but that has not been requested, so bail. 5520 Slog.w(TAG, "Attempt to re-install " + pkgName 5521 + " without first uninstalling package running as " 5522 + mSettings.mRenamedPackages.get(pkgName)); 5523 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS; 5524 return; 5525 } 5526 if (mPackages.containsKey(pkgName) || mAppDirs.containsKey(pkg.mPath)) { 5527 // Don't allow installation over an existing package with the same name. 5528 Slog.w(TAG, "Attempt to re-install " + pkgName 5529 + " without first uninstalling."); 5530 res.returnCode = PackageManager.INSTALL_FAILED_ALREADY_EXISTS; 5531 return; 5532 } 5533 } 5534 mLastScanError = PackageManager.INSTALL_SUCCEEDED; 5535 PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode, 5536 System.currentTimeMillis()); 5537 if (newPackage == null) { 5538 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath); 5539 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { 5540 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK; 5541 } 5542 } else { 5543 updateSettingsLI(newPackage, 5544 installerPackageName, 5545 res); 5546 // delete the partially installed application. the data directory will have to be 5547 // restored if it was already existing 5548 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { 5549 // remove package from internal structures. Note that we want deletePackageX to 5550 // delete the package data and cache directories that it created in 5551 // scanPackageLocked, unless those directories existed before we even tried to 5552 // install. 5553 deletePackageLI( 5554 pkgName, false, 5555 dataDirExists ? PackageManager.DONT_DELETE_DATA : 0, 5556 res.removedInfo, true); 5557 } 5558 } 5559 } 5560 5561 private void replacePackageLI(PackageParser.Package pkg, 5562 int parseFlags, 5563 int scanMode, 5564 String installerPackageName, PackageInstalledInfo res) { 5565 5566 PackageParser.Package oldPackage; 5567 String pkgName = pkg.packageName; 5568 // First find the old package info and check signatures 5569 synchronized(mPackages) { 5570 oldPackage = mPackages.get(pkgName); 5571 if (checkSignaturesLP(oldPackage.mSignatures, pkg.mSignatures) 5572 != PackageManager.SIGNATURE_MATCH) { 5573 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; 5574 return; 5575 } 5576 } 5577 boolean sysPkg = (isSystemApp(oldPackage)); 5578 if (sysPkg) { 5579 replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res); 5580 } else { 5581 replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res); 5582 } 5583 } 5584 5585 private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage, 5586 PackageParser.Package pkg, 5587 int parseFlags, int scanMode, 5588 String installerPackageName, PackageInstalledInfo res) { 5589 PackageParser.Package newPackage = null; 5590 String pkgName = deletedPackage.packageName; 5591 boolean deletedPkg = true; 5592 boolean updatedSettings = false; 5593 5594 String oldInstallerPackageName = null; 5595 synchronized (mPackages) { 5596 oldInstallerPackageName = mSettings.getInstallerPackageName(pkgName); 5597 } 5598 5599 long origUpdateTime; 5600 if (pkg.mExtras != null) { 5601 origUpdateTime = ((PackageSetting)pkg.mExtras).lastUpdateTime; 5602 } else { 5603 origUpdateTime = 0; 5604 } 5605 5606 // First delete the existing package while retaining the data directory 5607 if (!deletePackageLI(pkgName, true, PackageManager.DONT_DELETE_DATA, 5608 res.removedInfo, true)) { 5609 // If the existing package wasn't successfully deleted 5610 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE; 5611 deletedPkg = false; 5612 } else { 5613 // Successfully deleted the old package. Now proceed with re-installation 5614 mLastScanError = PackageManager.INSTALL_SUCCEEDED; 5615 newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME, 5616 System.currentTimeMillis()); 5617 if (newPackage == null) { 5618 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath); 5619 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { 5620 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK; 5621 } 5622 } else { 5623 updateSettingsLI(newPackage, 5624 installerPackageName, 5625 res); 5626 updatedSettings = true; 5627 } 5628 } 5629 5630 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { 5631 // remove package from internal structures. Note that we want deletePackageX to 5632 // delete the package data and cache directories that it created in 5633 // scanPackageLocked, unless those directories existed before we even tried to 5634 // install. 5635 if(updatedSettings) { 5636 deletePackageLI( 5637 pkgName, true, 5638 PackageManager.DONT_DELETE_DATA, 5639 res.removedInfo, true); 5640 } 5641 // Since we failed to install the new package we need to restore the old 5642 // package that we deleted. 5643 if(deletedPkg) { 5644 File restoreFile = new File(deletedPackage.mPath); 5645 if (restoreFile == null) { 5646 Slog.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName); 5647 return; 5648 } 5649 // Parse old package 5650 boolean oldOnSd = isExternal(deletedPackage); 5651 int oldParseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | 5652 (isForwardLocked(deletedPackage) ? PackageParser.PARSE_FORWARD_LOCK : 0) | 5653 (oldOnSd ? PackageParser.PARSE_ON_SDCARD : 0); 5654 int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE 5655 | SCAN_UPDATE_TIME; 5656 if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode, 5657 origUpdateTime) == null) { 5658 Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade"); 5659 return; 5660 } 5661 // Restore of old package succeeded. Update permissions. 5662 synchronized (mPackages) { 5663 updatePermissionsLP(deletedPackage.packageName, deletedPackage, 5664 true, false, false); 5665 mSettings.writeLP(); 5666 } 5667 Slog.i(TAG, "Successfully restored package : " + pkgName + " after failed upgrade"); 5668 } 5669 } 5670 } 5671 5672 private void replaceSystemPackageLI(PackageParser.Package deletedPackage, 5673 PackageParser.Package pkg, 5674 int parseFlags, int scanMode, 5675 String installerPackageName, PackageInstalledInfo res) { 5676 PackageParser.Package newPackage = null; 5677 boolean updatedSettings = false; 5678 parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING | 5679 PackageParser.PARSE_IS_SYSTEM; 5680 String packageName = deletedPackage.packageName; 5681 res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE; 5682 if (packageName == null) { 5683 Slog.w(TAG, "Attempt to delete null packageName."); 5684 return; 5685 } 5686 PackageParser.Package oldPkg; 5687 PackageSetting oldPkgSetting; 5688 synchronized (mPackages) { 5689 oldPkg = mPackages.get(packageName); 5690 oldPkgSetting = mSettings.mPackages.get(packageName); 5691 if((oldPkg == null) || (oldPkg.applicationInfo == null) || 5692 (oldPkgSetting == null)) { 5693 Slog.w(TAG, "Couldn't find package:"+packageName+" information"); 5694 return; 5695 } 5696 } 5697 5698 killApplication(packageName, oldPkg.applicationInfo.uid); 5699 5700 res.removedInfo.uid = oldPkg.applicationInfo.uid; 5701 res.removedInfo.removedPackage = packageName; 5702 // Remove existing system package 5703 removePackageLI(oldPkg, true); 5704 synchronized (mPackages) { 5705 if (!mSettings.disableSystemPackageLP(packageName) && deletedPackage != null) { 5706 // We didn't need to disable the .apk as a current system package, 5707 // which means we are replacing another update that is already 5708 // installed. We need to make sure to delete the older one's .apk. 5709 res.removedInfo.args = createInstallArgs(isExternal(pkg) 5710 ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL, 5711 deletedPackage.applicationInfo.sourceDir, 5712 deletedPackage.applicationInfo.publicSourceDir, 5713 deletedPackage.applicationInfo.nativeLibraryDir); 5714 } else { 5715 res.removedInfo.args = null; 5716 } 5717 } 5718 5719 // Successfully disabled the old package. Now proceed with re-installation 5720 mLastScanError = PackageManager.INSTALL_SUCCEEDED; 5721 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; 5722 newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0); 5723 if (newPackage == null) { 5724 Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath); 5725 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) { 5726 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_APK; 5727 } 5728 } else { 5729 if (newPackage.mExtras != null) { 5730 final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras; 5731 newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime; 5732 newPkgSetting.lastUpdateTime = System.currentTimeMillis(); 5733 } 5734 updateSettingsLI(newPackage, installerPackageName, res); 5735 updatedSettings = true; 5736 } 5737 5738 if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) { 5739 // Re installation failed. Restore old information 5740 // Remove new pkg information 5741 if (newPackage != null) { 5742 removePackageLI(newPackage, true); 5743 } 5744 // Add back the old system package 5745 scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0); 5746 // Restore the old system information in Settings 5747 synchronized(mPackages) { 5748 if (updatedSettings) { 5749 mSettings.enableSystemPackageLP(packageName); 5750 mSettings.setInstallerPackageName(packageName, 5751 oldPkgSetting.installerPackageName); 5752 } 5753 mSettings.writeLP(); 5754 } 5755 } 5756 } 5757 5758 // Utility method used to move dex files during install. 5759 private int moveDexFilesLI(PackageParser.Package newPackage) { 5760 int retCode; 5761 if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) { 5762 retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath); 5763 if (retCode != 0) { 5764 if (mNoDexOpt) { 5765 /* 5766 * If we're in an engineering build, programs are lazily run 5767 * through dexopt. If the .dex file doesn't exist yet, it 5768 * will be created when the program is run next. 5769 */ 5770 Slog.i(TAG, "dex file doesn't exist, skipping move: " + newPackage.mPath); 5771 } else { 5772 Slog.e(TAG, "Couldn't rename dex file: " + newPackage.mPath); 5773 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5774 } 5775 } 5776 } 5777 return PackageManager.INSTALL_SUCCEEDED; 5778 } 5779 5780 private void updateSettingsLI(PackageParser.Package newPackage, 5781 String installerPackageName, PackageInstalledInfo res) { 5782 String pkgName = newPackage.packageName; 5783 synchronized (mPackages) { 5784 //write settings. the installStatus will be incomplete at this stage. 5785 //note that the new package setting would have already been 5786 //added to mPackages. It hasn't been persisted yet. 5787 mSettings.setInstallStatus(pkgName, PKG_INSTALL_INCOMPLETE); 5788 mSettings.writeLP(); 5789 } 5790 5791 if ((res.returnCode = moveDexFilesLI(newPackage)) 5792 != PackageManager.INSTALL_SUCCEEDED) { 5793 // Discontinue if moving dex files failed. 5794 return; 5795 } 5796 if((res.returnCode = setPermissionsLI(newPackage)) 5797 != PackageManager.INSTALL_SUCCEEDED) { 5798 if (mInstaller != null) { 5799 mInstaller.rmdex(newPackage.mScanPath); 5800 } 5801 return; 5802 } else { 5803 Log.d(TAG, "New package installed in " + newPackage.mPath); 5804 } 5805 synchronized (mPackages) { 5806 updatePermissionsLP(newPackage.packageName, newPackage, 5807 newPackage.permissions.size() > 0, true, false); 5808 res.name = pkgName; 5809 res.uid = newPackage.applicationInfo.uid; 5810 res.pkg = newPackage; 5811 mSettings.setInstallStatus(pkgName, PKG_INSTALL_COMPLETE); 5812 mSettings.setInstallerPackageName(pkgName, installerPackageName); 5813 res.returnCode = PackageManager.INSTALL_SUCCEEDED; 5814 //to update install status 5815 mSettings.writeLP(); 5816 } 5817 } 5818 5819 private void installPackageLI(InstallArgs args, 5820 boolean newInstall, PackageInstalledInfo res) { 5821 int pFlags = args.flags; 5822 String installerPackageName = args.installerPackageName; 5823 File tmpPackageFile = new File(args.getCodePath()); 5824 boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0); 5825 boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0); 5826 boolean replace = false; 5827 int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE 5828 | (newInstall ? SCAN_NEW_INSTALL : 0); 5829 // Result object to be returned 5830 res.returnCode = PackageManager.INSTALL_SUCCEEDED; 5831 5832 // Retrieve PackageSettings and parse package 5833 int parseFlags = PackageParser.PARSE_CHATTY | 5834 (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) | 5835 (onSd ? PackageParser.PARSE_ON_SDCARD : 0); 5836 parseFlags |= mDefParseFlags; 5837 PackageParser pp = new PackageParser(tmpPackageFile.getPath()); 5838 pp.setSeparateProcesses(mSeparateProcesses); 5839 final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, 5840 null, mMetrics, parseFlags); 5841 if (pkg == null) { 5842 res.returnCode = pp.getParseError(); 5843 return; 5844 } 5845 String pkgName = res.name = pkg.packageName; 5846 if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) { 5847 if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) { 5848 res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY; 5849 return; 5850 } 5851 } 5852 if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) { 5853 res.returnCode = pp.getParseError(); 5854 return; 5855 } 5856 // Get rid of all references to package scan path via parser. 5857 pp = null; 5858 String oldCodePath = null; 5859 boolean systemApp = false; 5860 synchronized (mPackages) { 5861 // Check if installing already existing package 5862 if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) { 5863 String oldName = mSettings.mRenamedPackages.get(pkgName); 5864 if (pkg.mOriginalPackages != null 5865 && pkg.mOriginalPackages.contains(oldName) 5866 && mPackages.containsKey(oldName)) { 5867 // This package is derived from an original package, 5868 // and this device has been updating from that original 5869 // name. We must continue using the original name, so 5870 // rename the new package here. 5871 pkg.setPackageName(oldName); 5872 pkgName = pkg.packageName; 5873 replace = true; 5874 } else if (mPackages.containsKey(pkgName)) { 5875 // This package, under its official name, already exists 5876 // on the device; we should replace it. 5877 replace = true; 5878 } 5879 } 5880 PackageSetting ps = mSettings.mPackages.get(pkgName); 5881 if (ps != null) { 5882 oldCodePath = mSettings.mPackages.get(pkgName).codePathString; 5883 if (ps.pkg != null && ps.pkg.applicationInfo != null) { 5884 systemApp = (ps.pkg.applicationInfo.flags & 5885 ApplicationInfo.FLAG_SYSTEM) != 0; 5886 } 5887 } 5888 } 5889 5890 if (systemApp && onSd) { 5891 // Disable updates to system apps on sdcard 5892 Slog.w(TAG, "Cannot install updates to system apps on sdcard"); 5893 res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION; 5894 return; 5895 } 5896 5897 if (!args.doRename(res.returnCode, pkgName, oldCodePath)) { 5898 res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5899 return; 5900 } 5901 // Set application objects path explicitly after the rename 5902 setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath()); 5903 pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath(); 5904 if (replace) { 5905 replacePackageLI(pkg, parseFlags, scanMode, 5906 installerPackageName, res); 5907 } else { 5908 installNewPackageLI(pkg, parseFlags, scanMode, 5909 installerPackageName,res); 5910 } 5911 } 5912 5913 private int setPermissionsLI(PackageParser.Package newPackage) { 5914 String pkgName = newPackage.packageName; 5915 int retCode = 0; 5916 // TODO Gross hack but fix later. Ideally move this to be a post installation 5917 // check after alloting uid. 5918 if (isForwardLocked(newPackage)) { 5919 File destResourceFile = new File(newPackage.applicationInfo.publicSourceDir); 5920 try { 5921 extractPublicFiles(newPackage, destResourceFile); 5922 } catch (IOException e) { 5923 Slog.e(TAG, "Couldn't create a new zip file for the public parts of a" + 5924 " forward-locked app."); 5925 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5926 } finally { 5927 //TODO clean up the extracted public files 5928 } 5929 if (mInstaller != null) { 5930 retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath), 5931 newPackage.applicationInfo.uid); 5932 } else { 5933 final int filePermissions = 5934 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP; 5935 retCode = FileUtils.setPermissions(newPackage.mPath, filePermissions, -1, 5936 newPackage.applicationInfo.uid); 5937 } 5938 } else { 5939 // The permissions on the resource file was set when it was copied for 5940 // non forward locked apps and apps on sdcard 5941 } 5942 5943 if (retCode != 0) { 5944 Slog.e(TAG, "Couldn't set new package file permissions for " + 5945 newPackage.mPath 5946 + ". The return code was: " + retCode); 5947 // TODO Define new internal error 5948 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 5949 } 5950 return PackageManager.INSTALL_SUCCEEDED; 5951 } 5952 5953 private static boolean isForwardLocked(PackageParser.Package pkg) { 5954 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0; 5955 } 5956 5957 private static boolean isExternal(PackageParser.Package pkg) { 5958 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; 5959 } 5960 5961 private static boolean isSystemApp(PackageParser.Package pkg) { 5962 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 5963 } 5964 5965 private static boolean isSystemApp(ApplicationInfo info) { 5966 return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 5967 } 5968 5969 private static boolean isUpdatedSystemApp(PackageParser.Package pkg) { 5970 return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; 5971 } 5972 5973 private void extractPublicFiles(PackageParser.Package newPackage, 5974 File publicZipFile) throws IOException { 5975 final FileOutputStream fstr = new FileOutputStream(publicZipFile); 5976 final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr); 5977 final ZipFile privateZip = new ZipFile(newPackage.mPath); 5978 5979 // Copy manifest, resources.arsc and res directory to public zip 5980 5981 final Enumeration<? extends ZipEntry> privateZipEntries = privateZip.entries(); 5982 while (privateZipEntries.hasMoreElements()) { 5983 final ZipEntry zipEntry = privateZipEntries.nextElement(); 5984 final String zipEntryName = zipEntry.getName(); 5985 if ("AndroidManifest.xml".equals(zipEntryName) 5986 || "resources.arsc".equals(zipEntryName) 5987 || zipEntryName.startsWith("res/")) { 5988 try { 5989 copyZipEntry(zipEntry, privateZip, publicZipOutStream); 5990 } catch (IOException e) { 5991 try { 5992 publicZipOutStream.close(); 5993 throw e; 5994 } finally { 5995 publicZipFile.delete(); 5996 } 5997 } 5998 } 5999 } 6000 6001 publicZipOutStream.finish(); 6002 publicZipOutStream.flush(); 6003 FileUtils.sync(fstr); 6004 publicZipOutStream.close(); 6005 FileUtils.setPermissions( 6006 publicZipFile.getAbsolutePath(), 6007 FileUtils.S_IRUSR|FileUtils.S_IWUSR|FileUtils.S_IRGRP|FileUtils.S_IROTH, 6008 -1, -1); 6009 } 6010 6011 private static void copyZipEntry(ZipEntry zipEntry, 6012 ZipFile inZipFile, 6013 ZipOutputStream outZipStream) throws IOException { 6014 byte[] buffer = new byte[4096]; 6015 int num; 6016 6017 ZipEntry newEntry; 6018 if (zipEntry.getMethod() == ZipEntry.STORED) { 6019 // Preserve the STORED method of the input entry. 6020 newEntry = new ZipEntry(zipEntry); 6021 } else { 6022 // Create a new entry so that the compressed len is recomputed. 6023 newEntry = new ZipEntry(zipEntry.getName()); 6024 } 6025 outZipStream.putNextEntry(newEntry); 6026 6027 InputStream data = inZipFile.getInputStream(zipEntry); 6028 while ((num = data.read(buffer)) > 0) { 6029 outZipStream.write(buffer, 0, num); 6030 } 6031 outZipStream.flush(); 6032 } 6033 6034 private void deleteTempPackageFiles() { 6035 FilenameFilter filter = new FilenameFilter() { 6036 public boolean accept(File dir, String name) { 6037 return name.startsWith("vmdl") && name.endsWith(".tmp"); 6038 } 6039 }; 6040 String tmpFilesList[] = mAppInstallDir.list(filter); 6041 if(tmpFilesList == null) { 6042 return; 6043 } 6044 for(int i = 0; i < tmpFilesList.length; i++) { 6045 File tmpFile = new File(mAppInstallDir, tmpFilesList[i]); 6046 tmpFile.delete(); 6047 } 6048 } 6049 6050 private File createTempPackageFile(File installDir) { 6051 File tmpPackageFile; 6052 try { 6053 tmpPackageFile = File.createTempFile("vmdl", ".tmp", installDir); 6054 } catch (IOException e) { 6055 Slog.e(TAG, "Couldn't create temp file for downloaded package file."); 6056 return null; 6057 } 6058 try { 6059 FileUtils.setPermissions( 6060 tmpPackageFile.getCanonicalPath(), FileUtils.S_IRUSR|FileUtils.S_IWUSR, 6061 -1, -1); 6062 } catch (IOException e) { 6063 Slog.e(TAG, "Trouble getting the canoncical path for a temp file."); 6064 return null; 6065 } 6066 return tmpPackageFile; 6067 } 6068 6069 public void deletePackage(final String packageName, 6070 final IPackageDeleteObserver observer, 6071 final int flags) { 6072 mContext.enforceCallingOrSelfPermission( 6073 android.Manifest.permission.DELETE_PACKAGES, null); 6074 // Queue up an async operation since the package deletion may take a little while. 6075 mHandler.post(new Runnable() { 6076 public void run() { 6077 mHandler.removeCallbacks(this); 6078 final boolean succeded = deletePackageX(packageName, true, true, flags); 6079 if (observer != null) { 6080 try { 6081 observer.packageDeleted(succeded); 6082 } catch (RemoteException e) { 6083 Log.i(TAG, "Observer no longer exists."); 6084 } //end catch 6085 } //end if 6086 } //end run 6087 }); 6088 } 6089 6090 /** 6091 * This method is an internal method that could be get invoked either 6092 * to delete an installed package or to clean up a failed installation. 6093 * After deleting an installed package, a broadcast is sent to notify any 6094 * listeners that the package has been installed. For cleaning up a failed 6095 * installation, the broadcast is not necessary since the package's 6096 * installation wouldn't have sent the initial broadcast either 6097 * The key steps in deleting a package are 6098 * deleting the package information in internal structures like mPackages, 6099 * deleting the packages base directories through installd 6100 * updating mSettings to reflect current status 6101 * persisting settings for later use 6102 * sending a broadcast if necessary 6103 */ 6104 private boolean deletePackageX(String packageName, boolean sendBroadCast, 6105 boolean deleteCodeAndResources, int flags) { 6106 PackageRemovedInfo info = new PackageRemovedInfo(); 6107 boolean res; 6108 6109 IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface( 6110 ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)); 6111 try { 6112 if (dpm != null && dpm.packageHasActiveAdmins(packageName)) { 6113 Slog.w(TAG, "Not removing package " + packageName + ": has active device admin"); 6114 return false; 6115 } 6116 } catch (RemoteException e) { 6117 } 6118 6119 synchronized (mInstallLock) { 6120 res = deletePackageLI(packageName, deleteCodeAndResources, 6121 flags | REMOVE_CHATTY, info, true); 6122 } 6123 6124 if(res && sendBroadCast) { 6125 boolean systemUpdate = info.isRemovedPackageSystemUpdate; 6126 info.sendBroadcast(deleteCodeAndResources, systemUpdate); 6127 6128 // If the removed package was a system update, the old system packaged 6129 // was re-enabled; we need to broadcast this information 6130 if (systemUpdate) { 6131 Bundle extras = new Bundle(1); 6132 extras.putInt(Intent.EXTRA_UID, info.removedUid >= 0 ? info.removedUid : info.uid); 6133 extras.putBoolean(Intent.EXTRA_REPLACING, true); 6134 6135 sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, extras, null); 6136 sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName, extras, null); 6137 } 6138 } 6139 // Force a gc here. 6140 Runtime.getRuntime().gc(); 6141 // Delete the resources here after sending the broadcast to let 6142 // other processes clean up before deleting resources. 6143 if (info.args != null) { 6144 synchronized (mInstallLock) { 6145 info.args.doPostDeleteLI(deleteCodeAndResources); 6146 } 6147 } 6148 return res; 6149 } 6150 6151 static class PackageRemovedInfo { 6152 String removedPackage; 6153 int uid = -1; 6154 int removedUid = -1; 6155 boolean isRemovedPackageSystemUpdate = false; 6156 // Clean up resources deleted packages. 6157 InstallArgs args = null; 6158 6159 void sendBroadcast(boolean fullRemove, boolean replacing) { 6160 Bundle extras = new Bundle(1); 6161 extras.putInt(Intent.EXTRA_UID, removedUid >= 0 ? removedUid : uid); 6162 extras.putBoolean(Intent.EXTRA_DATA_REMOVED, fullRemove); 6163 if (replacing) { 6164 extras.putBoolean(Intent.EXTRA_REPLACING, true); 6165 } 6166 if (removedPackage != null) { 6167 sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, extras, null); 6168 } 6169 if (removedUid >= 0) { 6170 sendPackageBroadcast(Intent.ACTION_UID_REMOVED, null, extras, null); 6171 } 6172 } 6173 } 6174 6175 /* 6176 * This method deletes the package from internal data structures. If the DONT_DELETE_DATA 6177 * flag is not set, the data directory is removed as well. 6178 * make sure this flag is set for partially installed apps. If not its meaningless to 6179 * delete a partially installed application. 6180 */ 6181 private void removePackageDataLI(PackageParser.Package p, PackageRemovedInfo outInfo, 6182 int flags, boolean writeSettings) { 6183 String packageName = p.packageName; 6184 if (outInfo != null) { 6185 outInfo.removedPackage = packageName; 6186 } 6187 removePackageLI(p, (flags&REMOVE_CHATTY) != 0); 6188 // Retrieve object to delete permissions for shared user later on 6189 PackageSetting deletedPs; 6190 synchronized (mPackages) { 6191 deletedPs = mSettings.mPackages.get(packageName); 6192 } 6193 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) { 6194 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); 6195 if (mInstaller != null) { 6196 int retCode = mInstaller.remove(packageName, useEncryptedFSDir); 6197 if (retCode < 0) { 6198 Slog.w(TAG, "Couldn't remove app data or cache directory for package: " 6199 + packageName + ", retcode=" + retCode); 6200 // we don't consider this to be a failure of the core package deletion 6201 } 6202 } else { 6203 // for simulator 6204 PackageParser.Package pkg = mPackages.get(packageName); 6205 File dataDir = new File(pkg.applicationInfo.dataDir); 6206 dataDir.delete(); 6207 } 6208 schedulePackageCleaning(packageName); 6209 } 6210 synchronized (mPackages) { 6211 if (deletedPs != null) { 6212 if ((flags&PackageManager.DONT_DELETE_DATA) == 0) { 6213 if (outInfo != null) { 6214 outInfo.removedUid = mSettings.removePackageLP(packageName); 6215 } 6216 if (deletedPs != null) { 6217 updatePermissionsLP(deletedPs.name, null, false, false, false); 6218 if (deletedPs.sharedUser != null) { 6219 // remove permissions associated with package 6220 mSettings.updateSharedUserPermsLP(deletedPs, mGlobalGids); 6221 } 6222 } 6223 } 6224 // remove from preferred activities. 6225 ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>(); 6226 for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) { 6227 if (pa.mActivity.getPackageName().equals(deletedPs.name)) { 6228 removed.add(pa); 6229 } 6230 } 6231 for (PreferredActivity pa : removed) { 6232 mSettings.mPreferredActivities.removeFilter(pa); 6233 } 6234 } 6235 if (writeSettings) { 6236 // Save settings now 6237 mSettings.writeLP(); 6238 } 6239 } 6240 } 6241 6242 /* 6243 * Tries to delete system package. 6244 */ 6245 private boolean deleteSystemPackageLI(PackageParser.Package p, 6246 int flags, PackageRemovedInfo outInfo, boolean writeSettings) { 6247 ApplicationInfo applicationInfo = p.applicationInfo; 6248 //applicable for non-partially installed applications only 6249 if (applicationInfo == null) { 6250 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo."); 6251 return false; 6252 } 6253 PackageSetting ps = null; 6254 // Confirm if the system package has been updated 6255 // An updated system app can be deleted. This will also have to restore 6256 // the system pkg from system partition 6257 synchronized (mPackages) { 6258 ps = mSettings.getDisabledSystemPkg(p.packageName); 6259 } 6260 if (ps == null) { 6261 Slog.w(TAG, "Attempt to delete unknown system package "+ p.packageName); 6262 return false; 6263 } else { 6264 Log.i(TAG, "Deleting system pkg from data partition"); 6265 } 6266 // Delete the updated package 6267 outInfo.isRemovedPackageSystemUpdate = true; 6268 if (ps.versionCode < p.mVersionCode) { 6269 // Delete data for downgrades 6270 flags &= ~PackageManager.DONT_DELETE_DATA; 6271 } else { 6272 // Preserve data by setting flag 6273 flags |= PackageManager.DONT_DELETE_DATA; 6274 } 6275 boolean ret = deleteInstalledPackageLI(p, true, flags, outInfo, 6276 writeSettings); 6277 if (!ret) { 6278 return false; 6279 } 6280 synchronized (mPackages) { 6281 // Reinstate the old system package 6282 mSettings.enableSystemPackageLP(p.packageName); 6283 // Remove any native libraries from the upgraded package. 6284 NativeLibraryHelper.removeNativeBinariesLI(p.applicationInfo.nativeLibraryDir); 6285 } 6286 // Install the system package 6287 PackageParser.Package newPkg = scanPackageLI(ps.codePath, 6288 PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM, 6289 SCAN_MONITOR | SCAN_NO_PATHS, 0); 6290 6291 if (newPkg == null) { 6292 Slog.w(TAG, "Failed to restore system package:"+p.packageName+" with error:" + mLastScanError); 6293 return false; 6294 } 6295 synchronized (mPackages) { 6296 updatePermissionsLP(newPkg.packageName, newPkg, true, true, false); 6297 if (writeSettings) { 6298 mSettings.writeLP(); 6299 } 6300 } 6301 return true; 6302 } 6303 6304 private boolean deleteInstalledPackageLI(PackageParser.Package p, 6305 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo, 6306 boolean writeSettings) { 6307 ApplicationInfo applicationInfo = p.applicationInfo; 6308 if (applicationInfo == null) { 6309 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo."); 6310 return false; 6311 } 6312 if (outInfo != null) { 6313 outInfo.uid = applicationInfo.uid; 6314 } 6315 6316 // Delete package data from internal structures and also remove data if flag is set 6317 removePackageDataLI(p, outInfo, flags, writeSettings); 6318 6319 // Delete application code and resources 6320 if (deleteCodeAndResources) { 6321 // TODO can pick up from PackageSettings as well 6322 int installFlags = isExternal(p) ? PackageManager.INSTALL_EXTERNAL : 0; 6323 installFlags |= isForwardLocked(p) ? PackageManager.INSTALL_FORWARD_LOCK : 0; 6324 outInfo.args = createInstallArgs(installFlags, applicationInfo.sourceDir, 6325 applicationInfo.publicSourceDir, applicationInfo.nativeLibraryDir); 6326 } 6327 return true; 6328 } 6329 6330 /* 6331 * This method handles package deletion in general 6332 */ 6333 private boolean deletePackageLI(String packageName, 6334 boolean deleteCodeAndResources, int flags, PackageRemovedInfo outInfo, 6335 boolean writeSettings) { 6336 if (packageName == null) { 6337 Slog.w(TAG, "Attempt to delete null packageName."); 6338 return false; 6339 } 6340 PackageParser.Package p; 6341 boolean dataOnly = false; 6342 synchronized (mPackages) { 6343 p = mPackages.get(packageName); 6344 if (p == null) { 6345 //this retrieves partially installed apps 6346 dataOnly = true; 6347 PackageSetting ps = mSettings.mPackages.get(packageName); 6348 if (ps == null) { 6349 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6350 return false; 6351 } 6352 p = ps.pkg; 6353 } 6354 } 6355 if (p == null) { 6356 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6357 return false; 6358 } 6359 6360 if (dataOnly) { 6361 // Delete application data first 6362 removePackageDataLI(p, outInfo, flags, writeSettings); 6363 return true; 6364 } 6365 // At this point the package should have ApplicationInfo associated with it 6366 if (p.applicationInfo == null) { 6367 Slog.w(TAG, "Package " + p.packageName + " has no applicationInfo."); 6368 return false; 6369 } 6370 boolean ret = false; 6371 if (isSystemApp(p)) { 6372 Log.i(TAG, "Removing system package:"+p.packageName); 6373 // When an updated system application is deleted we delete the existing resources as well and 6374 // fall back to existing code in system partition 6375 ret = deleteSystemPackageLI(p, flags, outInfo, writeSettings); 6376 } else { 6377 Log.i(TAG, "Removing non-system package:"+p.packageName); 6378 // Kill application pre-emptively especially for apps on sd. 6379 killApplication(packageName, p.applicationInfo.uid); 6380 ret = deleteInstalledPackageLI(p, deleteCodeAndResources, flags, outInfo, 6381 writeSettings); 6382 } 6383 return ret; 6384 } 6385 6386 public void clearApplicationUserData(final String packageName, 6387 final IPackageDataObserver observer) { 6388 mContext.enforceCallingOrSelfPermission( 6389 android.Manifest.permission.CLEAR_APP_USER_DATA, null); 6390 // Queue up an async operation since the package deletion may take a little while. 6391 mHandler.post(new Runnable() { 6392 public void run() { 6393 mHandler.removeCallbacks(this); 6394 final boolean succeeded; 6395 synchronized (mInstallLock) { 6396 succeeded = clearApplicationUserDataLI(packageName); 6397 } 6398 if (succeeded) { 6399 // invoke DeviceStorageMonitor's update method to clear any notifications 6400 DeviceStorageMonitorService dsm = (DeviceStorageMonitorService) 6401 ServiceManager.getService(DeviceStorageMonitorService.SERVICE); 6402 if (dsm != null) { 6403 dsm.updateMemory(); 6404 } 6405 } 6406 if(observer != null) { 6407 try { 6408 observer.onRemoveCompleted(packageName, succeeded); 6409 } catch (RemoteException e) { 6410 Log.i(TAG, "Observer no longer exists."); 6411 } 6412 } //end if observer 6413 } //end run 6414 }); 6415 } 6416 6417 private boolean clearApplicationUserDataLI(String packageName) { 6418 if (packageName == null) { 6419 Slog.w(TAG, "Attempt to delete null packageName."); 6420 return false; 6421 } 6422 PackageParser.Package p; 6423 boolean dataOnly = false; 6424 synchronized (mPackages) { 6425 p = mPackages.get(packageName); 6426 if(p == null) { 6427 dataOnly = true; 6428 PackageSetting ps = mSettings.mPackages.get(packageName); 6429 if((ps == null) || (ps.pkg == null)) { 6430 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6431 return false; 6432 } 6433 p = ps.pkg; 6434 } 6435 } 6436 boolean useEncryptedFSDir = false; 6437 6438 if(!dataOnly) { 6439 //need to check this only for fully installed applications 6440 if (p == null) { 6441 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6442 return false; 6443 } 6444 final ApplicationInfo applicationInfo = p.applicationInfo; 6445 if (applicationInfo == null) { 6446 Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); 6447 return false; 6448 } 6449 useEncryptedFSDir = useEncryptedFilesystemForPackage(p); 6450 } 6451 if (mInstaller != null) { 6452 int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir); 6453 if (retCode < 0) { 6454 Slog.w(TAG, "Couldn't remove cache files for package: " 6455 + packageName); 6456 return false; 6457 } 6458 } 6459 return true; 6460 } 6461 6462 public void deleteApplicationCacheFiles(final String packageName, 6463 final IPackageDataObserver observer) { 6464 mContext.enforceCallingOrSelfPermission( 6465 android.Manifest.permission.DELETE_CACHE_FILES, null); 6466 // Queue up an async operation since the package deletion may take a little while. 6467 mHandler.post(new Runnable() { 6468 public void run() { 6469 mHandler.removeCallbacks(this); 6470 final boolean succeded; 6471 synchronized (mInstallLock) { 6472 succeded = deleteApplicationCacheFilesLI(packageName); 6473 } 6474 if(observer != null) { 6475 try { 6476 observer.onRemoveCompleted(packageName, succeded); 6477 } catch (RemoteException e) { 6478 Log.i(TAG, "Observer no longer exists."); 6479 } 6480 } //end if observer 6481 } //end run 6482 }); 6483 } 6484 6485 private boolean deleteApplicationCacheFilesLI(String packageName) { 6486 if (packageName == null) { 6487 Slog.w(TAG, "Attempt to delete null packageName."); 6488 return false; 6489 } 6490 PackageParser.Package p; 6491 synchronized (mPackages) { 6492 p = mPackages.get(packageName); 6493 } 6494 if (p == null) { 6495 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6496 return false; 6497 } 6498 final ApplicationInfo applicationInfo = p.applicationInfo; 6499 if (applicationInfo == null) { 6500 Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); 6501 return false; 6502 } 6503 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); 6504 if (mInstaller != null) { 6505 int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir); 6506 if (retCode < 0) { 6507 Slog.w(TAG, "Couldn't remove cache files for package: " 6508 + packageName); 6509 return false; 6510 } 6511 } 6512 return true; 6513 } 6514 6515 public void getPackageSizeInfo(final String packageName, 6516 final IPackageStatsObserver observer) { 6517 mContext.enforceCallingOrSelfPermission( 6518 android.Manifest.permission.GET_PACKAGE_SIZE, null); 6519 // Queue up an async operation since the package deletion may take a little while. 6520 mHandler.post(new Runnable() { 6521 public void run() { 6522 mHandler.removeCallbacks(this); 6523 PackageStats lStats = new PackageStats(packageName); 6524 final boolean succeded; 6525 synchronized (mInstallLock) { 6526 succeded = getPackageSizeInfoLI(packageName, lStats); 6527 } 6528 if(observer != null) { 6529 try { 6530 observer.onGetStatsCompleted(lStats, succeded); 6531 } catch (RemoteException e) { 6532 Log.i(TAG, "Observer no longer exists."); 6533 } 6534 } //end if observer 6535 } //end run 6536 }); 6537 } 6538 6539 private boolean getPackageSizeInfoLI(String packageName, PackageStats pStats) { 6540 if (packageName == null) { 6541 Slog.w(TAG, "Attempt to get size of null packageName."); 6542 return false; 6543 } 6544 PackageParser.Package p; 6545 boolean dataOnly = false; 6546 synchronized (mPackages) { 6547 p = mPackages.get(packageName); 6548 if(p == null) { 6549 dataOnly = true; 6550 PackageSetting ps = mSettings.mPackages.get(packageName); 6551 if((ps == null) || (ps.pkg == null)) { 6552 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist."); 6553 return false; 6554 } 6555 p = ps.pkg; 6556 } 6557 } 6558 String publicSrcDir = null; 6559 if(!dataOnly) { 6560 final ApplicationInfo applicationInfo = p.applicationInfo; 6561 if (applicationInfo == null) { 6562 Slog.w(TAG, "Package " + packageName + " has no applicationInfo."); 6563 return false; 6564 } 6565 publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null; 6566 } 6567 boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p); 6568 if (mInstaller != null) { 6569 int res = mInstaller.getSizeInfo(packageName, p.mPath, 6570 publicSrcDir, pStats, useEncryptedFSDir); 6571 if (res < 0) { 6572 return false; 6573 } else { 6574 return true; 6575 } 6576 } 6577 return true; 6578 } 6579 6580 6581 public void addPackageToPreferred(String packageName) { 6582 Slog.w(TAG, "addPackageToPreferred: this is now a no-op"); 6583 } 6584 6585 public void removePackageFromPreferred(String packageName) { 6586 Slog.w(TAG, "removePackageFromPreferred: this is now a no-op"); 6587 } 6588 6589 public List<PackageInfo> getPreferredPackages(int flags) { 6590 return new ArrayList<PackageInfo>(); 6591 } 6592 6593 int getUidTargetSdkVersionLockedLP(int uid) { 6594 Object obj = mSettings.getUserIdLP(uid); 6595 if (obj instanceof SharedUserSetting) { 6596 SharedUserSetting sus = (SharedUserSetting)obj; 6597 final int N = sus.packages.size(); 6598 int vers = Build.VERSION_CODES.CUR_DEVELOPMENT; 6599 Iterator<PackageSetting> it = sus.packages.iterator(); 6600 int i=0; 6601 while (it.hasNext()) { 6602 PackageSetting ps = it.next(); 6603 if (ps.pkg != null) { 6604 int v = ps.pkg.applicationInfo.targetSdkVersion; 6605 if (v < vers) vers = v; 6606 } 6607 } 6608 return vers; 6609 } else if (obj instanceof PackageSetting) { 6610 PackageSetting ps = (PackageSetting)obj; 6611 if (ps.pkg != null) { 6612 return ps.pkg.applicationInfo.targetSdkVersion; 6613 } 6614 } 6615 return Build.VERSION_CODES.CUR_DEVELOPMENT; 6616 } 6617 6618 public void addPreferredActivity(IntentFilter filter, int match, 6619 ComponentName[] set, ComponentName activity) { 6620 synchronized (mPackages) { 6621 if (mContext.checkCallingOrSelfPermission( 6622 android.Manifest.permission.SET_PREFERRED_APPLICATIONS) 6623 != PackageManager.PERMISSION_GRANTED) { 6624 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) 6625 < Build.VERSION_CODES.FROYO) { 6626 Slog.w(TAG, "Ignoring addPreferredActivity() from uid " 6627 + Binder.getCallingUid()); 6628 return; 6629 } 6630 mContext.enforceCallingOrSelfPermission( 6631 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); 6632 } 6633 6634 Slog.i(TAG, "Adding preferred activity " + activity + ":"); 6635 filter.dump(new LogPrinter(Log.INFO, TAG), " "); 6636 mSettings.mPreferredActivities.addFilter( 6637 new PreferredActivity(filter, match, set, activity)); 6638 scheduleWriteSettingsLocked(); 6639 } 6640 } 6641 6642 public void replacePreferredActivity(IntentFilter filter, int match, 6643 ComponentName[] set, ComponentName activity) { 6644 if (filter.countActions() != 1) { 6645 throw new IllegalArgumentException( 6646 "replacePreferredActivity expects filter to have only 1 action."); 6647 } 6648 if (filter.countCategories() != 1) { 6649 throw new IllegalArgumentException( 6650 "replacePreferredActivity expects filter to have only 1 category."); 6651 } 6652 if (filter.countDataAuthorities() != 0 6653 || filter.countDataPaths() != 0 6654 || filter.countDataSchemes() != 0 6655 || filter.countDataTypes() != 0) { 6656 throw new IllegalArgumentException( 6657 "replacePreferredActivity expects filter to have no data authorities, " + 6658 "paths, schemes or types."); 6659 } 6660 synchronized (mPackages) { 6661 if (mContext.checkCallingOrSelfPermission( 6662 android.Manifest.permission.SET_PREFERRED_APPLICATIONS) 6663 != PackageManager.PERMISSION_GRANTED) { 6664 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) 6665 < Build.VERSION_CODES.FROYO) { 6666 Slog.w(TAG, "Ignoring replacePreferredActivity() from uid " 6667 + Binder.getCallingUid()); 6668 return; 6669 } 6670 mContext.enforceCallingOrSelfPermission( 6671 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); 6672 } 6673 6674 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); 6675 String action = filter.getAction(0); 6676 String category = filter.getCategory(0); 6677 while (it.hasNext()) { 6678 PreferredActivity pa = it.next(); 6679 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) { 6680 it.remove(); 6681 Log.i(TAG, "Removed preferred activity " + pa.mActivity + ":"); 6682 filter.dump(new LogPrinter(Log.INFO, TAG), " "); 6683 } 6684 } 6685 addPreferredActivity(filter, match, set, activity); 6686 } 6687 } 6688 6689 public void clearPackagePreferredActivities(String packageName) { 6690 synchronized (mPackages) { 6691 int uid = Binder.getCallingUid(); 6692 PackageParser.Package pkg = mPackages.get(packageName); 6693 if (pkg == null || pkg.applicationInfo.uid != uid) { 6694 if (mContext.checkCallingOrSelfPermission( 6695 android.Manifest.permission.SET_PREFERRED_APPLICATIONS) 6696 != PackageManager.PERMISSION_GRANTED) { 6697 if (getUidTargetSdkVersionLockedLP(Binder.getCallingUid()) 6698 < Build.VERSION_CODES.FROYO) { 6699 Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid " 6700 + Binder.getCallingUid()); 6701 return; 6702 } 6703 mContext.enforceCallingOrSelfPermission( 6704 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); 6705 } 6706 } 6707 6708 if (clearPackagePreferredActivitiesLP(packageName)) { 6709 scheduleWriteSettingsLocked(); 6710 } 6711 } 6712 } 6713 6714 boolean clearPackagePreferredActivitiesLP(String packageName) { 6715 boolean changed = false; 6716 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); 6717 while (it.hasNext()) { 6718 PreferredActivity pa = it.next(); 6719 if (pa.mActivity.getPackageName().equals(packageName)) { 6720 it.remove(); 6721 changed = true; 6722 } 6723 } 6724 return changed; 6725 } 6726 6727 public int getPreferredActivities(List<IntentFilter> outFilters, 6728 List<ComponentName> outActivities, String packageName) { 6729 6730 int num = 0; 6731 synchronized (mPackages) { 6732 Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); 6733 while (it.hasNext()) { 6734 PreferredActivity pa = it.next(); 6735 if (packageName == null 6736 || pa.mActivity.getPackageName().equals(packageName)) { 6737 if (outFilters != null) { 6738 outFilters.add(new IntentFilter(pa)); 6739 } 6740 if (outActivities != null) { 6741 outActivities.add(pa.mActivity); 6742 } 6743 } 6744 } 6745 } 6746 6747 return num; 6748 } 6749 6750 public void setApplicationEnabledSetting(String appPackageName, 6751 int newState, int flags) { 6752 setEnabledSetting(appPackageName, null, newState, flags); 6753 } 6754 6755 public void setComponentEnabledSetting(ComponentName componentName, 6756 int newState, int flags) { 6757 setEnabledSetting(componentName.getPackageName(), 6758 componentName.getClassName(), newState, flags); 6759 } 6760 6761 private void setEnabledSetting( 6762 final String packageName, String className, int newState, final int flags) { 6763 if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT 6764 || newState == COMPONENT_ENABLED_STATE_ENABLED 6765 || newState == COMPONENT_ENABLED_STATE_DISABLED)) { 6766 throw new IllegalArgumentException("Invalid new component state: " 6767 + newState); 6768 } 6769 PackageSetting pkgSetting; 6770 final int uid = Binder.getCallingUid(); 6771 final int permission = mContext.checkCallingPermission( 6772 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); 6773 final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); 6774 boolean sendNow = false; 6775 boolean isApp = (className == null); 6776 String componentName = isApp ? packageName : className; 6777 int packageUid = -1; 6778 ArrayList<String> components; 6779 synchronized (mPackages) { 6780 pkgSetting = mSettings.mPackages.get(packageName); 6781 if (pkgSetting == null) { 6782 if (className == null) { 6783 throw new IllegalArgumentException( 6784 "Unknown package: " + packageName); 6785 } 6786 throw new IllegalArgumentException( 6787 "Unknown component: " + packageName 6788 + "/" + className); 6789 } 6790 if (!allowedByPermission && (uid != pkgSetting.userId)) { 6791 throw new SecurityException( 6792 "Permission Denial: attempt to change component state from pid=" 6793 + Binder.getCallingPid() 6794 + ", uid=" + uid + ", package uid=" + pkgSetting.userId); 6795 } 6796 if (className == null) { 6797 // We're dealing with an application/package level state change 6798 if (pkgSetting.enabled == newState) { 6799 // Nothing to do 6800 return; 6801 } 6802 pkgSetting.enabled = newState; 6803 pkgSetting.pkg.mSetEnabled = newState; 6804 } else { 6805 // We're dealing with a component level state change 6806 switch (newState) { 6807 case COMPONENT_ENABLED_STATE_ENABLED: 6808 if (!pkgSetting.enableComponentLP(className)) { 6809 return; 6810 } 6811 break; 6812 case COMPONENT_ENABLED_STATE_DISABLED: 6813 if (!pkgSetting.disableComponentLP(className)) { 6814 return; 6815 } 6816 break; 6817 case COMPONENT_ENABLED_STATE_DEFAULT: 6818 if (!pkgSetting.restoreComponentLP(className)) { 6819 return; 6820 } 6821 break; 6822 default: 6823 Slog.e(TAG, "Invalid new component state: " + newState); 6824 return; 6825 } 6826 } 6827 mSettings.writeLP(); 6828 packageUid = pkgSetting.userId; 6829 components = mPendingBroadcasts.get(packageName); 6830 boolean newPackage = components == null; 6831 if (newPackage) { 6832 components = new ArrayList<String>(); 6833 } 6834 if (!components.contains(componentName)) { 6835 components.add(componentName); 6836 } 6837 if ((flags&PackageManager.DONT_KILL_APP) == 0) { 6838 sendNow = true; 6839 // Purge entry from pending broadcast list if another one exists already 6840 // since we are sending one right away. 6841 mPendingBroadcasts.remove(packageName); 6842 } else { 6843 if (newPackage) { 6844 mPendingBroadcasts.put(packageName, components); 6845 } 6846 if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) { 6847 // Schedule a message 6848 mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY); 6849 } 6850 } 6851 } 6852 6853 long callingId = Binder.clearCallingIdentity(); 6854 try { 6855 if (sendNow) { 6856 sendPackageChangedBroadcast(packageName, 6857 (flags&PackageManager.DONT_KILL_APP) != 0, components, packageUid); 6858 } 6859 } finally { 6860 Binder.restoreCallingIdentity(callingId); 6861 } 6862 } 6863 6864 private void sendPackageChangedBroadcast(String packageName, 6865 boolean killFlag, ArrayList<String> componentNames, int packageUid) { 6866 if (false) Log.v(TAG, "Sending package changed: package=" + packageName 6867 + " components=" + componentNames); 6868 Bundle extras = new Bundle(4); 6869 extras.putString(Intent.EXTRA_CHANGED_COMPONENT_NAME, componentNames.get(0)); 6870 String nameList[] = new String[componentNames.size()]; 6871 componentNames.toArray(nameList); 6872 extras.putStringArray(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST, nameList); 6873 extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, killFlag); 6874 extras.putInt(Intent.EXTRA_UID, packageUid); 6875 sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, null); 6876 } 6877 6878 public String getInstallerPackageName(String packageName) { 6879 synchronized (mPackages) { 6880 PackageSetting pkg = mSettings.mPackages.get(packageName); 6881 if (pkg == null) { 6882 throw new IllegalArgumentException("Unknown package: " + packageName); 6883 } 6884 return pkg.installerPackageName; 6885 } 6886 } 6887 6888 public int getApplicationEnabledSetting(String appPackageName) { 6889 synchronized (mPackages) { 6890 PackageSetting pkg = mSettings.mPackages.get(appPackageName); 6891 if (pkg == null) { 6892 throw new IllegalArgumentException("Unknown package: " + appPackageName); 6893 } 6894 return pkg.enabled; 6895 } 6896 } 6897 6898 public int getComponentEnabledSetting(ComponentName componentName) { 6899 synchronized (mPackages) { 6900 final String packageNameStr = componentName.getPackageName(); 6901 PackageSetting pkg = mSettings.mPackages.get(packageNameStr); 6902 if (pkg == null) { 6903 throw new IllegalArgumentException("Unknown component: " + componentName); 6904 } 6905 final String classNameStr = componentName.getClassName(); 6906 return pkg.currentEnabledStateLP(classNameStr); 6907 } 6908 } 6909 6910 public void enterSafeMode() { 6911 if (!mSystemReady) { 6912 mSafeMode = true; 6913 } 6914 } 6915 6916 public void systemReady() { 6917 mSystemReady = true; 6918 6919 // Read the compatibilty setting when the system is ready. 6920 boolean compatibilityModeEnabled = android.provider.Settings.System.getInt( 6921 mContext.getContentResolver(), 6922 android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1; 6923 PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled); 6924 if (DEBUG_SETTINGS) { 6925 Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); 6926 } 6927 } 6928 6929 public boolean isSafeMode() { 6930 return mSafeMode; 6931 } 6932 6933 public boolean hasSystemUidErrors() { 6934 return mHasSystemUidErrors; 6935 } 6936 6937 static String arrayToString(int[] array) { 6938 StringBuffer buf = new StringBuffer(128); 6939 buf.append('['); 6940 if (array != null) { 6941 for (int i=0; i<array.length; i++) { 6942 if (i > 0) buf.append(", "); 6943 buf.append(array[i]); 6944 } 6945 } 6946 buf.append(']'); 6947 return buf.toString(); 6948 } 6949 6950 @Override 6951 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 6952 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 6953 != PackageManager.PERMISSION_GRANTED) { 6954 pw.println("Permission Denial: can't dump ActivityManager from from pid=" 6955 + Binder.getCallingPid() 6956 + ", uid=" + Binder.getCallingUid() 6957 + " without permission " 6958 + android.Manifest.permission.DUMP); 6959 return; 6960 } 6961 6962 boolean dumpStar = true; 6963 boolean dumpLibs = false; 6964 boolean dumpFeatures = false; 6965 boolean dumpResolvers = false; 6966 boolean dumpPermissions = false; 6967 boolean dumpPackages = false; 6968 boolean dumpSharedUsers = false; 6969 boolean dumpMessages = false; 6970 boolean dumpProviders = false; 6971 6972 String packageName = null; 6973 boolean showFilters = false; 6974 6975 int opti = 0; 6976 while (opti < args.length) { 6977 String opt = args[opti]; 6978 if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { 6979 break; 6980 } 6981 opti++; 6982 if ("-a".equals(opt)) { 6983 // Right now we only know how to print all. 6984 } else if ("-h".equals(opt)) { 6985 pw.println("Package manager dump options:"); 6986 pw.println(" [-h] [-f] [cmd] ..."); 6987 pw.println(" -f: print details of intent filters"); 6988 pw.println(" -h: print this help"); 6989 pw.println(" cmd may be one of:"); 6990 pw.println(" l[ibraries]: list known shared libraries"); 6991 pw.println(" f[ibraries]: list device features"); 6992 pw.println(" r[esolvers]: dump intent resolvers"); 6993 pw.println(" perm[issions]: dump permissions"); 6994 pw.println(" prov[iders]: dump content providers"); 6995 pw.println(" p[ackages]: dump installed packages"); 6996 pw.println(" s[hared-users]: dump shared user IDs"); 6997 pw.println(" m[essages]: print collected runtime messages"); 6998 pw.println(" <package.name>: info about given package"); 6999 return; 7000 } else if ("-f".equals(opt)) { 7001 showFilters = true; 7002 } else { 7003 pw.println("Unknown argument: " + opt + "; use -h for help"); 7004 } 7005 } 7006 7007 // Is the caller requesting to dump a particular piece of data? 7008 if (opti < args.length) { 7009 String cmd = args[opti]; 7010 opti++; 7011 // Is this a package name? 7012 if ("android".equals(cmd) || cmd.contains(".")) { 7013 packageName = cmd; 7014 } else if ("l".equals(cmd) || "libraries".equals(cmd)) { 7015 dumpStar = false; 7016 dumpLibs = true; 7017 } else if ("f".equals(cmd) || "features".equals(cmd)) { 7018 dumpStar = false; 7019 dumpFeatures = true; 7020 } else if ("r".equals(cmd) || "resolvers".equals(cmd)) { 7021 dumpStar = false; 7022 dumpResolvers = true; 7023 } else if ("perm".equals(cmd) || "permissions".equals(cmd)) { 7024 dumpStar = false; 7025 dumpPermissions = true; 7026 } else if ("p".equals(cmd) || "packages".equals(cmd)) { 7027 dumpStar = false; 7028 dumpPackages = true; 7029 } else if ("s".equals(cmd) || "shared-users".equals(cmd)) { 7030 dumpStar = false; 7031 dumpSharedUsers = true; 7032 } else if ("prov".equals(cmd) || "providers".equals(cmd)) { 7033 dumpStar = false; 7034 dumpProviders = true; 7035 } else if ("m".equals(cmd) || "messages".equals(cmd)) { 7036 dumpStar = false; 7037 dumpMessages = true; 7038 } 7039 } 7040 7041 boolean printedTitle = false; 7042 7043 synchronized (mPackages) { 7044 if ((dumpStar || dumpLibs) && packageName == null) { 7045 if (printedTitle) pw.println(" "); 7046 printedTitle = true; 7047 pw.println("Libraries:"); 7048 Iterator<String> it = mSharedLibraries.keySet().iterator(); 7049 while (it.hasNext()) { 7050 String name = it.next(); 7051 pw.print(" "); 7052 pw.print(name); 7053 pw.print(" -> "); 7054 pw.println(mSharedLibraries.get(name)); 7055 } 7056 } 7057 7058 if ((dumpStar || dumpFeatures) && packageName == null) { 7059 if (printedTitle) pw.println(" "); 7060 printedTitle = true; 7061 pw.println("Features:"); 7062 Iterator<String> it = mAvailableFeatures.keySet().iterator(); 7063 while (it.hasNext()) { 7064 String name = it.next(); 7065 pw.print(" "); 7066 pw.println(name); 7067 } 7068 } 7069 7070 if (dumpStar || dumpResolvers) { 7071 if (mActivities.dump(pw, printedTitle 7072 ? "\nActivity Resolver Table:" : "Activity Resolver Table:", 7073 " ", packageName, showFilters)) { 7074 printedTitle = true; 7075 } 7076 if (mReceivers.dump(pw, printedTitle 7077 ? "\nReceiver Resolver Table:" : "Receiver Resolver Table:", 7078 " ", packageName, showFilters)) { 7079 printedTitle = true; 7080 } 7081 if (mServices.dump(pw, printedTitle 7082 ? "\nService Resolver Table:" : "Service Resolver Table:", 7083 " ", packageName, showFilters)) { 7084 printedTitle = true; 7085 } 7086 if (mSettings.mPreferredActivities.dump(pw, printedTitle 7087 ? "\nPreferred Activities:" : "Preferred Activities:", 7088 " ", packageName, showFilters)) { 7089 printedTitle = true; 7090 } 7091 } 7092 7093 boolean printedSomething = false; 7094 if (dumpStar || dumpPermissions) { 7095 for (BasePermission p : mSettings.mPermissions.values()) { 7096 if (packageName != null && !packageName.equals(p.sourcePackage)) { 7097 continue; 7098 } 7099 if (!printedSomething) { 7100 if (printedTitle) pw.println(" "); 7101 pw.println("Permissions:"); 7102 printedSomething = true; 7103 printedTitle = true; 7104 } 7105 pw.print(" Permission ["); pw.print(p.name); pw.print("] ("); 7106 pw.print(Integer.toHexString(System.identityHashCode(p))); 7107 pw.println("):"); 7108 pw.print(" sourcePackage="); pw.println(p.sourcePackage); 7109 pw.print(" uid="); pw.print(p.uid); 7110 pw.print(" gids="); pw.print(arrayToString(p.gids)); 7111 pw.print(" type="); pw.print(p.type); 7112 pw.print(" prot="); pw.println(p.protectionLevel); 7113 if (p.packageSetting != null) { 7114 pw.print(" packageSetting="); pw.println(p.packageSetting); 7115 } 7116 if (p.perm != null) { 7117 pw.print(" perm="); pw.println(p.perm); 7118 } 7119 } 7120 } 7121 7122 if (dumpStar || dumpProviders) { 7123 printedSomething = false; 7124 for (PackageParser.Provider p : mProviders.values()) { 7125 if (packageName != null && !packageName.equals(p.info.packageName)) { 7126 continue; 7127 } 7128 if (!printedSomething) { 7129 if (printedTitle) pw.println(" "); 7130 pw.println("Registered ContentProviders:"); 7131 printedSomething = true; 7132 printedTitle = true; 7133 } 7134 pw.print(" ["); pw.print(p.info.authority); pw.print("]: "); 7135 pw.println(p.toString()); 7136 } 7137 } 7138 7139 printedSomething = false; 7140 SharedUserSetting packageSharedUser = null; 7141 if (dumpStar || dumpPackages) { 7142 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 7143 Date date = new Date(); 7144 for (PackageSetting ps : mSettings.mPackages.values()) { 7145 if (packageName != null && !packageName.equals(ps.realName) 7146 && !packageName.equals(ps.name)) { 7147 continue; 7148 } 7149 if (!printedSomething) { 7150 if (printedTitle) pw.println(" "); 7151 pw.println("Packages:"); 7152 printedSomething = true; 7153 printedTitle = true; 7154 } 7155 packageSharedUser = ps.sharedUser; 7156 pw.print(" Package ["); 7157 pw.print(ps.realName != null ? ps.realName : ps.name); 7158 pw.print("] ("); 7159 pw.print(Integer.toHexString(System.identityHashCode(ps))); 7160 pw.println("):"); 7161 if (ps.realName != null) { 7162 pw.print(" compat name="); pw.println(ps.name); 7163 } 7164 pw.print(" userId="); pw.print(ps.userId); 7165 pw.print(" gids="); pw.println(arrayToString(ps.gids)); 7166 pw.print(" sharedUser="); pw.println(ps.sharedUser); 7167 pw.print(" pkg="); pw.println(ps.pkg); 7168 pw.print(" codePath="); pw.println(ps.codePathString); 7169 pw.print(" resourcePath="); pw.println(ps.resourcePathString); 7170 pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString); 7171 pw.print(" versionCode="); pw.println(ps.versionCode); 7172 if (ps.pkg != null) { 7173 pw.print(" versionName="); pw.println(ps.pkg.mVersionName); 7174 pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); 7175 pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion); 7176 if (ps.pkg.mOperationPending) { 7177 pw.println(" mOperationPending=true"); 7178 } 7179 pw.print(" supportsScreens=["); 7180 boolean first = true; 7181 if ((ps.pkg.applicationInfo.flags & 7182 ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { 7183 if (!first) pw.print(", "); 7184 first = false; 7185 pw.print("small"); 7186 } 7187 if ((ps.pkg.applicationInfo.flags & 7188 ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { 7189 if (!first) pw.print(", "); 7190 first = false; 7191 pw.print("medium"); 7192 } 7193 if ((ps.pkg.applicationInfo.flags & 7194 ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { 7195 if (!first) pw.print(", "); 7196 first = false; 7197 pw.print("large"); 7198 } 7199 if ((ps.pkg.applicationInfo.flags & 7200 ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { 7201 if (!first) pw.print(", "); 7202 first = false; 7203 pw.print("xlarge"); 7204 } 7205 if ((ps.pkg.applicationInfo.flags & 7206 ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { 7207 if (!first) pw.print(", "); 7208 first = false; 7209 pw.print("resizeable"); 7210 } 7211 if ((ps.pkg.applicationInfo.flags & 7212 ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { 7213 if (!first) pw.print(", "); 7214 first = false; 7215 pw.print("anyDensity"); 7216 } 7217 } 7218 pw.println("]"); 7219 pw.print(" timeStamp="); 7220 date.setTime(ps.timeStamp); pw.println(sdf.format(date)); 7221 pw.print(" firstInstallTime="); 7222 date.setTime(ps.firstInstallTime); pw.println(sdf.format(date)); 7223 pw.print(" lastUpdateTime="); 7224 date.setTime(ps.lastUpdateTime); pw.println(sdf.format(date)); 7225 pw.print(" signatures="); pw.println(ps.signatures); 7226 pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed); 7227 pw.print(" haveGids="); pw.println(ps.haveGids); 7228 pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags)); 7229 pw.print(" installStatus="); pw.print(ps.installStatus); 7230 pw.print(" enabled="); pw.println(ps.enabled); 7231 if (ps.disabledComponents.size() > 0) { 7232 pw.println(" disabledComponents:"); 7233 for (String s : ps.disabledComponents) { 7234 pw.print(" "); pw.println(s); 7235 } 7236 } 7237 if (ps.enabledComponents.size() > 0) { 7238 pw.println(" enabledComponents:"); 7239 for (String s : ps.enabledComponents) { 7240 pw.print(" "); pw.println(s); 7241 } 7242 } 7243 if (ps.grantedPermissions.size() > 0) { 7244 pw.println(" grantedPermissions:"); 7245 for (String s : ps.grantedPermissions) { 7246 pw.print(" "); pw.println(s); 7247 } 7248 } 7249 } 7250 } 7251 printedSomething = false; 7252 if (dumpStar || dumpPackages) { 7253 if (mSettings.mRenamedPackages.size() > 0) { 7254 for (HashMap.Entry<String, String> e 7255 : mSettings.mRenamedPackages.entrySet()) { 7256 if (packageName != null && !packageName.equals(e.getKey()) 7257 && !packageName.equals(e.getValue())) { 7258 continue; 7259 } 7260 if (!printedSomething) { 7261 if (printedTitle) pw.println(" "); 7262 pw.println("Renamed packages:"); 7263 printedSomething = true; 7264 printedTitle = true; 7265 } 7266 pw.print(" "); pw.print(e.getKey()); pw.print(" -> "); 7267 pw.println(e.getValue()); 7268 } 7269 } 7270 printedSomething = false; 7271 if (mSettings.mDisabledSysPackages.size() > 0) { 7272 for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) { 7273 if (packageName != null && !packageName.equals(ps.realName) 7274 && !packageName.equals(ps.name)) { 7275 continue; 7276 } 7277 if (!printedSomething) { 7278 if (printedTitle) pw.println(" "); 7279 pw.println("Hidden system packages:"); 7280 printedSomething = true; 7281 printedTitle = true; 7282 } 7283 pw.print(" Package ["); 7284 pw.print(ps.realName != null ? ps.realName : ps.name); 7285 pw.print("] ("); 7286 pw.print(Integer.toHexString(System.identityHashCode(ps))); 7287 pw.println("):"); 7288 if (ps.realName != null) { 7289 pw.print(" compat name="); pw.println(ps.name); 7290 } 7291 pw.print(" userId="); pw.println(ps.userId); 7292 pw.print(" sharedUser="); pw.println(ps.sharedUser); 7293 pw.print(" codePath="); pw.println(ps.codePathString); 7294 pw.print(" resourcePath="); pw.println(ps.resourcePathString); 7295 } 7296 } 7297 } 7298 printedSomething = false; 7299 if (dumpStar || dumpSharedUsers) { 7300 for (SharedUserSetting su : mSettings.mSharedUsers.values()) { 7301 if (packageName != null && su != packageSharedUser) { 7302 continue; 7303 } 7304 if (!printedSomething) { 7305 if (printedTitle) pw.println(" "); 7306 pw.println("Shared users:"); 7307 printedSomething = true; 7308 printedTitle = true; 7309 } 7310 pw.print(" SharedUser ["); pw.print(su.name); pw.print("] ("); 7311 pw.print(Integer.toHexString(System.identityHashCode(su))); 7312 pw.println("):"); 7313 pw.print(" userId="); pw.print(su.userId); 7314 pw.print(" gids="); pw.println(arrayToString(su.gids)); 7315 pw.println(" grantedPermissions:"); 7316 for (String s : su.grantedPermissions) { 7317 pw.print(" "); pw.println(s); 7318 } 7319 } 7320 } 7321 7322 if ((dumpStar || dumpMessages) && packageName == null) { 7323 if (printedTitle) pw.println(" "); 7324 printedTitle = true; 7325 pw.println("Settings parse messages:"); 7326 pw.print(mSettings.mReadMessages.toString()); 7327 7328 pw.println(" "); 7329 pw.println("Package warning messages:"); 7330 File fname = getSettingsProblemFile(); 7331 FileInputStream in; 7332 try { 7333 in = new FileInputStream(fname); 7334 int avail = in.available(); 7335 byte[] data = new byte[avail]; 7336 in.read(data); 7337 pw.print(new String(data)); 7338 } catch (FileNotFoundException e) { 7339 } catch (IOException e) { 7340 } 7341 } 7342 } 7343 } 7344 7345 static final class BasePermission { 7346 final static int TYPE_NORMAL = 0; 7347 final static int TYPE_BUILTIN = 1; 7348 final static int TYPE_DYNAMIC = 2; 7349 7350 final String name; 7351 String sourcePackage; 7352 PackageSettingBase packageSetting; 7353 final int type; 7354 int protectionLevel; 7355 PackageParser.Permission perm; 7356 PermissionInfo pendingInfo; 7357 int uid; 7358 int[] gids; 7359 7360 BasePermission(String _name, String _sourcePackage, int _type) { 7361 name = _name; 7362 sourcePackage = _sourcePackage; 7363 type = _type; 7364 // Default to most conservative protection level. 7365 protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; 7366 } 7367 7368 public String toString() { 7369 return "BasePermission{" 7370 + Integer.toHexString(System.identityHashCode(this)) 7371 + " " + name + "}"; 7372 } 7373 } 7374 7375 static class PackageSignatures { 7376 private Signature[] mSignatures; 7377 7378 PackageSignatures(PackageSignatures orig) { 7379 if (orig != null && orig.mSignatures != null) { 7380 mSignatures = orig.mSignatures.clone(); 7381 } 7382 } 7383 7384 PackageSignatures(Signature[] sigs) { 7385 assignSignatures(sigs); 7386 } 7387 7388 PackageSignatures() { 7389 } 7390 7391 void writeXml(XmlSerializer serializer, String tagName, 7392 ArrayList<Signature> pastSignatures) throws IOException { 7393 if (mSignatures == null) { 7394 return; 7395 } 7396 serializer.startTag(null, tagName); 7397 serializer.attribute(null, "count", 7398 Integer.toString(mSignatures.length)); 7399 for (int i=0; i<mSignatures.length; i++) { 7400 serializer.startTag(null, "cert"); 7401 final Signature sig = mSignatures[i]; 7402 final int sigHash = sig.hashCode(); 7403 final int numPast = pastSignatures.size(); 7404 int j; 7405 for (j=0; j<numPast; j++) { 7406 Signature pastSig = pastSignatures.get(j); 7407 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) { 7408 serializer.attribute(null, "index", Integer.toString(j)); 7409 break; 7410 } 7411 } 7412 if (j >= numPast) { 7413 pastSignatures.add(sig); 7414 serializer.attribute(null, "index", Integer.toString(numPast)); 7415 serializer.attribute(null, "key", sig.toCharsString()); 7416 } 7417 serializer.endTag(null, "cert"); 7418 } 7419 serializer.endTag(null, tagName); 7420 } 7421 7422 void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures) 7423 throws IOException, XmlPullParserException { 7424 String countStr = parser.getAttributeValue(null, "count"); 7425 if (countStr == null) { 7426 reportSettingsProblem(Log.WARN, 7427 "Error in package manager settings: <signatures> has" 7428 + " no count at " + parser.getPositionDescription()); 7429 XmlUtils.skipCurrentTag(parser); 7430 } 7431 final int count = Integer.parseInt(countStr); 7432 mSignatures = new Signature[count]; 7433 int pos = 0; 7434 7435 int outerDepth = parser.getDepth(); 7436 int type; 7437 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 7438 && (type != XmlPullParser.END_TAG 7439 || parser.getDepth() > outerDepth)) { 7440 if (type == XmlPullParser.END_TAG 7441 || type == XmlPullParser.TEXT) { 7442 continue; 7443 } 7444 7445 String tagName = parser.getName(); 7446 if (tagName.equals("cert")) { 7447 if (pos < count) { 7448 String index = parser.getAttributeValue(null, "index"); 7449 if (index != null) { 7450 try { 7451 int idx = Integer.parseInt(index); 7452 String key = parser.getAttributeValue(null, "key"); 7453 if (key == null) { 7454 if (idx >= 0 && idx < pastSignatures.size()) { 7455 Signature sig = pastSignatures.get(idx); 7456 if (sig != null) { 7457 mSignatures[pos] = pastSignatures.get(idx); 7458 pos++; 7459 } else { 7460 reportSettingsProblem(Log.WARN, 7461 "Error in package manager settings: <cert> " 7462 + "index " + index + " is not defined at " 7463 + parser.getPositionDescription()); 7464 } 7465 } else { 7466 reportSettingsProblem(Log.WARN, 7467 "Error in package manager settings: <cert> " 7468 + "index " + index + " is out of bounds at " 7469 + parser.getPositionDescription()); 7470 } 7471 } else { 7472 while (pastSignatures.size() <= idx) { 7473 pastSignatures.add(null); 7474 } 7475 Signature sig = new Signature(key); 7476 pastSignatures.set(idx, sig); 7477 mSignatures[pos] = sig; 7478 pos++; 7479 } 7480 } catch (NumberFormatException e) { 7481 reportSettingsProblem(Log.WARN, 7482 "Error in package manager settings: <cert> " 7483 + "index " + index + " is not a number at " 7484 + parser.getPositionDescription()); 7485 } 7486 } else { 7487 reportSettingsProblem(Log.WARN, 7488 "Error in package manager settings: <cert> has" 7489 + " no index at " + parser.getPositionDescription()); 7490 } 7491 } else { 7492 reportSettingsProblem(Log.WARN, 7493 "Error in package manager settings: too " 7494 + "many <cert> tags, expected " + count 7495 + " at " + parser.getPositionDescription()); 7496 } 7497 } else { 7498 reportSettingsProblem(Log.WARN, 7499 "Unknown element under <cert>: " 7500 + parser.getName()); 7501 } 7502 XmlUtils.skipCurrentTag(parser); 7503 } 7504 7505 if (pos < count) { 7506 // Should never happen -- there is an error in the written 7507 // settings -- but if it does we don't want to generate 7508 // a bad array. 7509 Signature[] newSigs = new Signature[pos]; 7510 System.arraycopy(mSignatures, 0, newSigs, 0, pos); 7511 mSignatures = newSigs; 7512 } 7513 } 7514 7515 private void assignSignatures(Signature[] sigs) { 7516 if (sigs == null) { 7517 mSignatures = null; 7518 return; 7519 } 7520 mSignatures = new Signature[sigs.length]; 7521 for (int i=0; i<sigs.length; i++) { 7522 mSignatures[i] = sigs[i]; 7523 } 7524 } 7525 7526 @Override 7527 public String toString() { 7528 StringBuffer buf = new StringBuffer(128); 7529 buf.append("PackageSignatures{"); 7530 buf.append(Integer.toHexString(System.identityHashCode(this))); 7531 buf.append(" ["); 7532 if (mSignatures != null) { 7533 for (int i=0; i<mSignatures.length; i++) { 7534 if (i > 0) buf.append(", "); 7535 buf.append(Integer.toHexString( 7536 System.identityHashCode(mSignatures[i]))); 7537 } 7538 } 7539 buf.append("]}"); 7540 return buf.toString(); 7541 } 7542 } 7543 7544 static class PreferredActivity extends IntentFilter { 7545 final int mMatch; 7546 final String[] mSetPackages; 7547 final String[] mSetClasses; 7548 final String[] mSetComponents; 7549 final ComponentName mActivity; 7550 final String mShortActivity; 7551 String mParseError; 7552 7553 PreferredActivity(IntentFilter filter, int match, ComponentName[] set, 7554 ComponentName activity) { 7555 super(filter); 7556 mMatch = match&IntentFilter.MATCH_CATEGORY_MASK; 7557 mActivity = activity; 7558 mShortActivity = activity.flattenToShortString(); 7559 mParseError = null; 7560 if (set != null) { 7561 final int N = set.length; 7562 String[] myPackages = new String[N]; 7563 String[] myClasses = new String[N]; 7564 String[] myComponents = new String[N]; 7565 for (int i=0; i<N; i++) { 7566 ComponentName cn = set[i]; 7567 if (cn == null) { 7568 mSetPackages = null; 7569 mSetClasses = null; 7570 mSetComponents = null; 7571 return; 7572 } 7573 myPackages[i] = cn.getPackageName().intern(); 7574 myClasses[i] = cn.getClassName().intern(); 7575 myComponents[i] = cn.flattenToShortString().intern(); 7576 } 7577 mSetPackages = myPackages; 7578 mSetClasses = myClasses; 7579 mSetComponents = myComponents; 7580 } else { 7581 mSetPackages = null; 7582 mSetClasses = null; 7583 mSetComponents = null; 7584 } 7585 } 7586 7587 PreferredActivity(XmlPullParser parser) throws XmlPullParserException, 7588 IOException { 7589 mShortActivity = parser.getAttributeValue(null, "name"); 7590 mActivity = ComponentName.unflattenFromString(mShortActivity); 7591 if (mActivity == null) { 7592 mParseError = "Bad activity name " + mShortActivity; 7593 } 7594 String matchStr = parser.getAttributeValue(null, "match"); 7595 mMatch = matchStr != null ? Integer.parseInt(matchStr, 16) : 0; 7596 String setCountStr = parser.getAttributeValue(null, "set"); 7597 int setCount = setCountStr != null ? Integer.parseInt(setCountStr) : 0; 7598 7599 String[] myPackages = setCount > 0 ? new String[setCount] : null; 7600 String[] myClasses = setCount > 0 ? new String[setCount] : null; 7601 String[] myComponents = setCount > 0 ? new String[setCount] : null; 7602 7603 int setPos = 0; 7604 7605 int outerDepth = parser.getDepth(); 7606 int type; 7607 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 7608 && (type != XmlPullParser.END_TAG 7609 || parser.getDepth() > outerDepth)) { 7610 if (type == XmlPullParser.END_TAG 7611 || type == XmlPullParser.TEXT) { 7612 continue; 7613 } 7614 7615 String tagName = parser.getName(); 7616 //Log.i(TAG, "Parse outerDepth=" + outerDepth + " depth=" 7617 // + parser.getDepth() + " tag=" + tagName); 7618 if (tagName.equals("set")) { 7619 String name = parser.getAttributeValue(null, "name"); 7620 if (name == null) { 7621 if (mParseError == null) { 7622 mParseError = "No name in set tag in preferred activity " 7623 + mShortActivity; 7624 } 7625 } else if (setPos >= setCount) { 7626 if (mParseError == null) { 7627 mParseError = "Too many set tags in preferred activity " 7628 + mShortActivity; 7629 } 7630 } else { 7631 ComponentName cn = ComponentName.unflattenFromString(name); 7632 if (cn == null) { 7633 if (mParseError == null) { 7634 mParseError = "Bad set name " + name + " in preferred activity " 7635 + mShortActivity; 7636 } 7637 } else { 7638 myPackages[setPos] = cn.getPackageName(); 7639 myClasses[setPos] = cn.getClassName(); 7640 myComponents[setPos] = name; 7641 setPos++; 7642 } 7643 } 7644 XmlUtils.skipCurrentTag(parser); 7645 } else if (tagName.equals("filter")) { 7646 //Log.i(TAG, "Starting to parse filter..."); 7647 readFromXml(parser); 7648 //Log.i(TAG, "Finished filter: outerDepth=" + outerDepth + " depth=" 7649 // + parser.getDepth() + " tag=" + parser.getName()); 7650 } else { 7651 reportSettingsProblem(Log.WARN, 7652 "Unknown element under <preferred-activities>: " 7653 + parser.getName()); 7654 XmlUtils.skipCurrentTag(parser); 7655 } 7656 } 7657 7658 if (setPos != setCount) { 7659 if (mParseError == null) { 7660 mParseError = "Not enough set tags (expected " + setCount 7661 + " but found " + setPos + ") in " + mShortActivity; 7662 } 7663 } 7664 7665 mSetPackages = myPackages; 7666 mSetClasses = myClasses; 7667 mSetComponents = myComponents; 7668 } 7669 7670 public void writeToXml(XmlSerializer serializer) throws IOException { 7671 final int NS = mSetClasses != null ? mSetClasses.length : 0; 7672 serializer.attribute(null, "name", mShortActivity); 7673 serializer.attribute(null, "match", Integer.toHexString(mMatch)); 7674 serializer.attribute(null, "set", Integer.toString(NS)); 7675 for (int s=0; s<NS; s++) { 7676 serializer.startTag(null, "set"); 7677 serializer.attribute(null, "name", mSetComponents[s]); 7678 serializer.endTag(null, "set"); 7679 } 7680 serializer.startTag(null, "filter"); 7681 super.writeToXml(serializer); 7682 serializer.endTag(null, "filter"); 7683 } 7684 7685 boolean sameSet(List<ResolveInfo> query, int priority) { 7686 if (mSetPackages == null) return false; 7687 final int NQ = query.size(); 7688 final int NS = mSetPackages.length; 7689 int numMatch = 0; 7690 for (int i=0; i<NQ; i++) { 7691 ResolveInfo ri = query.get(i); 7692 if (ri.priority != priority) continue; 7693 ActivityInfo ai = ri.activityInfo; 7694 boolean good = false; 7695 for (int j=0; j<NS; j++) { 7696 if (mSetPackages[j].equals(ai.packageName) 7697 && mSetClasses[j].equals(ai.name)) { 7698 numMatch++; 7699 good = true; 7700 break; 7701 } 7702 } 7703 if (!good) return false; 7704 } 7705 return numMatch == NS; 7706 } 7707 } 7708 7709 static class GrantedPermissions { 7710 int pkgFlags; 7711 7712 HashSet<String> grantedPermissions = new HashSet<String>(); 7713 int[] gids; 7714 7715 GrantedPermissions(int pkgFlags) { 7716 setFlags(pkgFlags); 7717 } 7718 7719 GrantedPermissions(GrantedPermissions base) { 7720 pkgFlags = base.pkgFlags; 7721 grantedPermissions = (HashSet<String>) base.grantedPermissions.clone(); 7722 7723 if (base.gids != null) { 7724 gids = base.gids.clone(); 7725 } 7726 } 7727 7728 void setFlags(int pkgFlags) { 7729 this.pkgFlags = pkgFlags & ( 7730 ApplicationInfo.FLAG_SYSTEM | 7731 ApplicationInfo.FLAG_FORWARD_LOCK | 7732 ApplicationInfo.FLAG_EXTERNAL_STORAGE | 7733 ApplicationInfo.FLAG_NEVER_ENCRYPT); 7734 } 7735 } 7736 7737 /** 7738 * Settings base class for pending and resolved classes. 7739 */ 7740 static class PackageSettingBase extends GrantedPermissions { 7741 final String name; 7742 final String realName; 7743 File codePath; 7744 String codePathString; 7745 File resourcePath; 7746 String resourcePathString; 7747 String nativeLibraryPathString; 7748 long timeStamp; 7749 long firstInstallTime; 7750 long lastUpdateTime; 7751 int versionCode; 7752 7753 boolean uidError; 7754 7755 PackageSignatures signatures = new PackageSignatures(); 7756 7757 boolean permissionsFixed; 7758 boolean haveGids; 7759 7760 /* Explicitly disabled components */ 7761 HashSet<String> disabledComponents = new HashSet<String>(0); 7762 /* Explicitly enabled components */ 7763 HashSet<String> enabledComponents = new HashSet<String>(0); 7764 int enabled = COMPONENT_ENABLED_STATE_DEFAULT; 7765 int installStatus = PKG_INSTALL_COMPLETE; 7766 7767 PackageSettingBase origPackage; 7768 7769 /* package name of the app that installed this package */ 7770 String installerPackageName; 7771 7772 PackageSettingBase(String name, String realName, File codePath, File resourcePath, 7773 String nativeLibraryPathString, int pVersionCode, int pkgFlags) { 7774 super(pkgFlags); 7775 this.name = name; 7776 this.realName = realName; 7777 init(codePath, resourcePath, nativeLibraryPathString, pVersionCode); 7778 } 7779 7780 /** 7781 * New instance of PackageSetting with one-level-deep cloning. 7782 */ 7783 PackageSettingBase(PackageSettingBase base) { 7784 super(base); 7785 7786 name = base.name; 7787 realName = base.realName; 7788 codePath = base.codePath; 7789 codePathString = base.codePathString; 7790 resourcePath = base.resourcePath; 7791 resourcePathString = base.resourcePathString; 7792 nativeLibraryPathString = base.nativeLibraryPathString; 7793 timeStamp = base.timeStamp; 7794 firstInstallTime = base.firstInstallTime; 7795 lastUpdateTime = base.lastUpdateTime; 7796 versionCode = base.versionCode; 7797 7798 uidError = base.uidError; 7799 7800 signatures = new PackageSignatures(base.signatures); 7801 7802 permissionsFixed = base.permissionsFixed; 7803 haveGids = base.haveGids; 7804 7805 disabledComponents = (HashSet<String>) base.disabledComponents.clone(); 7806 7807 enabledComponents = (HashSet<String>) base.enabledComponents.clone(); 7808 7809 enabled = base.enabled; 7810 installStatus = base.installStatus; 7811 7812 origPackage = base.origPackage; 7813 7814 installerPackageName = base.installerPackageName; 7815 } 7816 7817 void init(File codePath, File resourcePath, String nativeLibraryPathString, 7818 int pVersionCode) { 7819 this.codePath = codePath; 7820 this.codePathString = codePath.toString(); 7821 this.resourcePath = resourcePath; 7822 this.resourcePathString = resourcePath.toString(); 7823 this.nativeLibraryPathString = nativeLibraryPathString; 7824 this.versionCode = pVersionCode; 7825 } 7826 7827 public void setInstallerPackageName(String packageName) { 7828 installerPackageName = packageName; 7829 } 7830 7831 String getInstallerPackageName() { 7832 return installerPackageName; 7833 } 7834 7835 public void setInstallStatus(int newStatus) { 7836 installStatus = newStatus; 7837 } 7838 7839 public int getInstallStatus() { 7840 return installStatus; 7841 } 7842 7843 public void setTimeStamp(long newStamp) { 7844 timeStamp = newStamp; 7845 } 7846 7847 /** 7848 * Make a shallow copy of this package settings. 7849 */ 7850 public void copyFrom(PackageSettingBase base) { 7851 grantedPermissions = base.grantedPermissions; 7852 gids = base.gids; 7853 7854 timeStamp = base.timeStamp; 7855 firstInstallTime = base.firstInstallTime; 7856 lastUpdateTime = base.lastUpdateTime; 7857 signatures = base.signatures; 7858 permissionsFixed = base.permissionsFixed; 7859 haveGids = base.haveGids; 7860 disabledComponents = base.disabledComponents; 7861 enabledComponents = base.enabledComponents; 7862 enabled = base.enabled; 7863 installStatus = base.installStatus; 7864 } 7865 7866 boolean enableComponentLP(String componentClassName) { 7867 boolean changed = disabledComponents.remove(componentClassName); 7868 changed |= enabledComponents.add(componentClassName); 7869 return changed; 7870 } 7871 7872 boolean disableComponentLP(String componentClassName) { 7873 boolean changed = enabledComponents.remove(componentClassName); 7874 changed |= disabledComponents.add(componentClassName); 7875 return changed; 7876 } 7877 7878 boolean restoreComponentLP(String componentClassName) { 7879 boolean changed = enabledComponents.remove(componentClassName); 7880 changed |= disabledComponents.remove(componentClassName); 7881 return changed; 7882 } 7883 7884 int currentEnabledStateLP(String componentName) { 7885 if (enabledComponents.contains(componentName)) { 7886 return COMPONENT_ENABLED_STATE_ENABLED; 7887 } else if (disabledComponents.contains(componentName)) { 7888 return COMPONENT_ENABLED_STATE_DISABLED; 7889 } else { 7890 return COMPONENT_ENABLED_STATE_DEFAULT; 7891 } 7892 } 7893 } 7894 7895 /** 7896 * Settings data for a particular package we know about. 7897 */ 7898 static final class PackageSetting extends PackageSettingBase { 7899 int userId; 7900 PackageParser.Package pkg; 7901 SharedUserSetting sharedUser; 7902 7903 PackageSetting(String name, String realName, File codePath, File resourcePath, 7904 String nativeLibraryPathString, int pVersionCode, int pkgFlags) { 7905 super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode, 7906 pkgFlags); 7907 } 7908 7909 /** 7910 * New instance of PackageSetting replicating the original settings. 7911 * Note that it keeps the same PackageParser.Package instance. 7912 */ 7913 PackageSetting(PackageSetting orig) { 7914 super(orig); 7915 7916 userId = orig.userId; 7917 pkg = orig.pkg; 7918 sharedUser = orig.sharedUser; 7919 } 7920 7921 @Override 7922 public String toString() { 7923 return "PackageSetting{" 7924 + Integer.toHexString(System.identityHashCode(this)) 7925 + " " + name + "/" + userId + "}"; 7926 } 7927 } 7928 7929 /** 7930 * Settings data for a particular shared user ID we know about. 7931 */ 7932 static final class SharedUserSetting extends GrantedPermissions { 7933 final String name; 7934 int userId; 7935 final HashSet<PackageSetting> packages = new HashSet<PackageSetting>(); 7936 final PackageSignatures signatures = new PackageSignatures(); 7937 7938 SharedUserSetting(String _name, int _pkgFlags) { 7939 super(_pkgFlags); 7940 name = _name; 7941 } 7942 7943 @Override 7944 public String toString() { 7945 return "SharedUserSetting{" 7946 + Integer.toHexString(System.identityHashCode(this)) 7947 + " " + name + "/" + userId + "}"; 7948 } 7949 } 7950 7951 /** 7952 * Holds information about dynamic settings. 7953 */ 7954 private static final class Settings { 7955 private final File mSettingsFilename; 7956 private final File mBackupSettingsFilename; 7957 private final File mPackageListFilename; 7958 private final HashMap<String, PackageSetting> mPackages = 7959 new HashMap<String, PackageSetting>(); 7960 // List of replaced system applications 7961 final HashMap<String, PackageSetting> mDisabledSysPackages = 7962 new HashMap<String, PackageSetting>(); 7963 7964 // These are the last platform API version we were using for 7965 // the apps installed on internal and external storage. It is 7966 // used to grant newer permissions one time during a system upgrade. 7967 int mInternalSdkPlatform; 7968 int mExternalSdkPlatform; 7969 7970 // The user's preferred activities associated with particular intent 7971 // filters. 7972 private final IntentResolver<PreferredActivity, PreferredActivity> mPreferredActivities = 7973 new IntentResolver<PreferredActivity, PreferredActivity>() { 7974 @Override 7975 protected String packageForFilter(PreferredActivity filter) { 7976 return filter.mActivity.getPackageName(); 7977 } 7978 @Override 7979 protected void dumpFilter(PrintWriter out, String prefix, 7980 PreferredActivity filter) { 7981 out.print(prefix); out.print( 7982 Integer.toHexString(System.identityHashCode(filter))); 7983 out.print(' '); 7984 out.print(filter.mActivity.flattenToShortString()); 7985 out.print(" match=0x"); 7986 out.println( Integer.toHexString(filter.mMatch)); 7987 if (filter.mSetComponents != null) { 7988 out.print(prefix); out.println(" Selected from:"); 7989 for (int i=0; i<filter.mSetComponents.length; i++) { 7990 out.print(prefix); out.print(" "); 7991 out.println(filter.mSetComponents[i]); 7992 } 7993 } 7994 } 7995 }; 7996 private final HashMap<String, SharedUserSetting> mSharedUsers = 7997 new HashMap<String, SharedUserSetting>(); 7998 private final ArrayList<Object> mUserIds = new ArrayList<Object>(); 7999 private final SparseArray<Object> mOtherUserIds = 8000 new SparseArray<Object>(); 8001 8002 // For reading/writing settings file. 8003 private final ArrayList<Signature> mPastSignatures = 8004 new ArrayList<Signature>(); 8005 8006 // Mapping from permission names to info about them. 8007 final HashMap<String, BasePermission> mPermissions = 8008 new HashMap<String, BasePermission>(); 8009 8010 // Mapping from permission tree names to info about them. 8011 final HashMap<String, BasePermission> mPermissionTrees = 8012 new HashMap<String, BasePermission>(); 8013 8014 // Packages that have been uninstalled and still need their external 8015 // storage data deleted. 8016 final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>(); 8017 8018 // Packages that have been renamed since they were first installed. 8019 // Keys are the new names of the packages, values are the original 8020 // names. The packages appear everwhere else under their original 8021 // names. 8022 final HashMap<String, String> mRenamedPackages = new HashMap<String, String>(); 8023 8024 private final StringBuilder mReadMessages = new StringBuilder(); 8025 8026 private static final class PendingPackage extends PackageSettingBase { 8027 final int sharedId; 8028 8029 PendingPackage(String name, String realName, File codePath, File resourcePath, 8030 String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) { 8031 super(name, realName, codePath, resourcePath, nativeLibraryPathString, 8032 pVersionCode, pkgFlags); 8033 this.sharedId = sharedId; 8034 } 8035 } 8036 private final ArrayList<PendingPackage> mPendingPackages 8037 = new ArrayList<PendingPackage>(); 8038 8039 Settings() { 8040 File dataDir = Environment.getDataDirectory(); 8041 File systemDir = new File(dataDir, "system"); 8042 // TODO(oam): This secure dir creation needs to be moved somewhere else (later) 8043 File systemSecureDir = new File(dataDir, "secure/system"); 8044 systemDir.mkdirs(); 8045 systemSecureDir.mkdirs(); 8046 FileUtils.setPermissions(systemDir.toString(), 8047 FileUtils.S_IRWXU|FileUtils.S_IRWXG 8048 |FileUtils.S_IROTH|FileUtils.S_IXOTH, 8049 -1, -1); 8050 FileUtils.setPermissions(systemSecureDir.toString(), 8051 FileUtils.S_IRWXU|FileUtils.S_IRWXG 8052 |FileUtils.S_IROTH|FileUtils.S_IXOTH, 8053 -1, -1); 8054 mSettingsFilename = new File(systemDir, "packages.xml"); 8055 mBackupSettingsFilename = new File(systemDir, "packages-backup.xml"); 8056 mPackageListFilename = new File(systemDir, "packages.list"); 8057 } 8058 8059 PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage, 8060 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, 8061 String nativeLibraryPathString, int pkgFlags, boolean create, boolean add) { 8062 final String name = pkg.packageName; 8063 PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath, 8064 resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags, create, add); 8065 return p; 8066 } 8067 8068 PackageSetting peekPackageLP(String name) { 8069 return mPackages.get(name); 8070 /* 8071 PackageSetting p = mPackages.get(name); 8072 if (p != null && p.codePath.getPath().equals(codePath)) { 8073 return p; 8074 } 8075 return null; 8076 */ 8077 } 8078 8079 void setInstallStatus(String pkgName, int status) { 8080 PackageSetting p = mPackages.get(pkgName); 8081 if(p != null) { 8082 if(p.getInstallStatus() != status) { 8083 p.setInstallStatus(status); 8084 } 8085 } 8086 } 8087 8088 void setInstallerPackageName(String pkgName, 8089 String installerPkgName) { 8090 PackageSetting p = mPackages.get(pkgName); 8091 if(p != null) { 8092 p.setInstallerPackageName(installerPkgName); 8093 } 8094 } 8095 8096 String getInstallerPackageName(String pkgName) { 8097 PackageSetting p = mPackages.get(pkgName); 8098 return (p == null) ? null : p.getInstallerPackageName(); 8099 } 8100 8101 int getInstallStatus(String pkgName) { 8102 PackageSetting p = mPackages.get(pkgName); 8103 if(p != null) { 8104 return p.getInstallStatus(); 8105 } 8106 return -1; 8107 } 8108 8109 SharedUserSetting getSharedUserLP(String name, 8110 int pkgFlags, boolean create) { 8111 SharedUserSetting s = mSharedUsers.get(name); 8112 if (s == null) { 8113 if (!create) { 8114 return null; 8115 } 8116 s = new SharedUserSetting(name, pkgFlags); 8117 if (MULTIPLE_APPLICATION_UIDS) { 8118 s.userId = newUserIdLP(s); 8119 } else { 8120 s.userId = FIRST_APPLICATION_UID; 8121 } 8122 Log.i(TAG, "New shared user " + name + ": id=" + s.userId); 8123 // < 0 means we couldn't assign a userid; fall out and return 8124 // s, which is currently null 8125 if (s.userId >= 0) { 8126 mSharedUsers.put(name, s); 8127 } 8128 } 8129 8130 return s; 8131 } 8132 8133 boolean disableSystemPackageLP(String name) { 8134 PackageSetting p = mPackages.get(name); 8135 if(p == null) { 8136 Log.w(TAG, "Package:"+name+" is not an installed package"); 8137 return false; 8138 } 8139 PackageSetting dp = mDisabledSysPackages.get(name); 8140 // always make sure the system package code and resource paths dont change 8141 if (dp == null) { 8142 if((p.pkg != null) && (p.pkg.applicationInfo != null)) { 8143 p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; 8144 } 8145 mDisabledSysPackages.put(name, p); 8146 8147 // a little trick... when we install the new package, we don't 8148 // want to modify the existing PackageSetting for the built-in 8149 // version. so at this point we need a new PackageSetting that 8150 // is okay to muck with. 8151 PackageSetting newp = new PackageSetting(p); 8152 replacePackageLP(name, newp); 8153 return true; 8154 } 8155 return false; 8156 } 8157 8158 PackageSetting enableSystemPackageLP(String name) { 8159 PackageSetting p = mDisabledSysPackages.get(name); 8160 if(p == null) { 8161 Log.w(TAG, "Package:"+name+" is not disabled"); 8162 return null; 8163 } 8164 // Reset flag in ApplicationInfo object 8165 if((p.pkg != null) && (p.pkg.applicationInfo != null)) { 8166 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; 8167 } 8168 PackageSetting ret = addPackageLP(name, p.realName, p.codePath, p.resourcePath, 8169 p.nativeLibraryPathString, p.userId, p.versionCode, p.pkgFlags); 8170 mDisabledSysPackages.remove(name); 8171 return ret; 8172 } 8173 8174 PackageSetting addPackageLP(String name, String realName, File codePath, File resourcePath, 8175 String nativeLibraryPathString, int uid, int vc, int pkgFlags) { 8176 PackageSetting p = mPackages.get(name); 8177 if (p != null) { 8178 if (p.userId == uid) { 8179 return p; 8180 } 8181 reportSettingsProblem(Log.ERROR, 8182 "Adding duplicate package, keeping first: " + name); 8183 return null; 8184 } 8185 p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, 8186 vc, pkgFlags); 8187 p.userId = uid; 8188 if (addUserIdLP(uid, p, name)) { 8189 mPackages.put(name, p); 8190 return p; 8191 } 8192 return null; 8193 } 8194 8195 SharedUserSetting addSharedUserLP(String name, int uid, int pkgFlags) { 8196 SharedUserSetting s = mSharedUsers.get(name); 8197 if (s != null) { 8198 if (s.userId == uid) { 8199 return s; 8200 } 8201 reportSettingsProblem(Log.ERROR, 8202 "Adding duplicate shared user, keeping first: " + name); 8203 return null; 8204 } 8205 s = new SharedUserSetting(name, pkgFlags); 8206 s.userId = uid; 8207 if (addUserIdLP(uid, s, name)) { 8208 mSharedUsers.put(name, s); 8209 return s; 8210 } 8211 return null; 8212 } 8213 8214 // Transfer ownership of permissions from one package to another. 8215 private void transferPermissions(String origPkg, String newPkg) { 8216 // Transfer ownership of permissions to the new package. 8217 for (int i=0; i<2; i++) { 8218 HashMap<String, BasePermission> permissions = 8219 i == 0 ? mPermissionTrees : mPermissions; 8220 for (BasePermission bp : permissions.values()) { 8221 if (origPkg.equals(bp.sourcePackage)) { 8222 if (DEBUG_UPGRADE) Log.v(TAG, 8223 "Moving permission " + bp.name 8224 + " from pkg " + bp.sourcePackage 8225 + " to " + newPkg); 8226 bp.sourcePackage = newPkg; 8227 bp.packageSetting = null; 8228 bp.perm = null; 8229 if (bp.pendingInfo != null) { 8230 bp.pendingInfo.packageName = newPkg; 8231 } 8232 bp.uid = 0; 8233 bp.gids = null; 8234 } 8235 } 8236 } 8237 } 8238 8239 private PackageSetting getPackageLP(String name, PackageSetting origPackage, 8240 String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, 8241 String nativeLibraryPathString, int vc, int pkgFlags, boolean create, boolean add) { 8242 PackageSetting p = mPackages.get(name); 8243 if (p != null) { 8244 if (!p.codePath.equals(codePath)) { 8245 // Check to see if its a disabled system app 8246 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) { 8247 // This is an updated system app with versions in both system 8248 // and data partition. Just let the most recent version 8249 // take precedence. 8250 Slog.w(TAG, "Trying to update system app code path from " + 8251 p.codePathString + " to " + codePath.toString()); 8252 } else { 8253 // Just a change in the code path is not an issue, but 8254 // let's log a message about it. 8255 Slog.i(TAG, "Package " + name + " codePath changed from " + p.codePath 8256 + " to " + codePath + "; Retaining data and using new"); 8257 /* 8258 * Since we've changed paths, we need to prefer the new 8259 * native library path over the one stored in the 8260 * package settings since we might have moved from 8261 * internal to external storage or vice versa. 8262 */ 8263 p.nativeLibraryPathString = nativeLibraryPathString; 8264 } 8265 } 8266 if (p.sharedUser != sharedUser) { 8267 reportSettingsProblem(Log.WARN, 8268 "Package " + name + " shared user changed from " 8269 + (p.sharedUser != null ? p.sharedUser.name : "<nothing>") 8270 + " to " 8271 + (sharedUser != null ? sharedUser.name : "<nothing>") 8272 + "; replacing with new"); 8273 p = null; 8274 } else { 8275 if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0) { 8276 // If what we are scanning is a system package, then 8277 // make it so, regardless of whether it was previously 8278 // installed only in the data partition. 8279 p.pkgFlags |= ApplicationInfo.FLAG_SYSTEM; 8280 } 8281 } 8282 } 8283 if (p == null) { 8284 // Create a new PackageSettings entry. this can end up here because 8285 // of code path mismatch or user id mismatch of an updated system partition 8286 if (!create) { 8287 return null; 8288 } 8289 if (origPackage != null) { 8290 // We are consuming the data from an existing package. 8291 p = new PackageSetting(origPackage.name, name, codePath, resourcePath, 8292 nativeLibraryPathString, vc, pkgFlags); 8293 if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name 8294 + " is adopting original package " + origPackage.name); 8295 // Note that we will retain the new package's signature so 8296 // that we can keep its data. 8297 PackageSignatures s = p.signatures; 8298 p.copyFrom(origPackage); 8299 p.signatures = s; 8300 p.sharedUser = origPackage.sharedUser; 8301 p.userId = origPackage.userId; 8302 p.origPackage = origPackage; 8303 mRenamedPackages.put(name, origPackage.name); 8304 name = origPackage.name; 8305 // Update new package state. 8306 p.setTimeStamp(codePath.lastModified()); 8307 } else { 8308 p = new PackageSetting(name, realName, codePath, resourcePath, 8309 nativeLibraryPathString, vc, pkgFlags); 8310 p.setTimeStamp(codePath.lastModified()); 8311 p.sharedUser = sharedUser; 8312 if (sharedUser != null) { 8313 p.userId = sharedUser.userId; 8314 } else if (MULTIPLE_APPLICATION_UIDS) { 8315 // Clone the setting here for disabled system packages 8316 PackageSetting dis = mDisabledSysPackages.get(name); 8317 if (dis != null) { 8318 // For disabled packages a new setting is created 8319 // from the existing user id. This still has to be 8320 // added to list of user id's 8321 // Copy signatures from previous setting 8322 if (dis.signatures.mSignatures != null) { 8323 p.signatures.mSignatures = dis.signatures.mSignatures.clone(); 8324 } 8325 p.userId = dis.userId; 8326 // Clone permissions 8327 p.grantedPermissions = new HashSet<String>(dis.grantedPermissions); 8328 // Clone component info 8329 p.disabledComponents = new HashSet<String>(dis.disabledComponents); 8330 p.enabledComponents = new HashSet<String>(dis.enabledComponents); 8331 // Add new setting to list of user ids 8332 addUserIdLP(p.userId, p, name); 8333 } else { 8334 // Assign new user id 8335 p.userId = newUserIdLP(p); 8336 } 8337 } else { 8338 p.userId = FIRST_APPLICATION_UID; 8339 } 8340 } 8341 if (p.userId < 0) { 8342 reportSettingsProblem(Log.WARN, 8343 "Package " + name + " could not be assigned a valid uid"); 8344 return null; 8345 } 8346 if (add) { 8347 // Finish adding new package by adding it and updating shared 8348 // user preferences 8349 addPackageSettingLP(p, name, sharedUser); 8350 } 8351 } 8352 return p; 8353 } 8354 8355 private void insertPackageSettingLP(PackageSetting p, PackageParser.Package pkg) { 8356 p.pkg = pkg; 8357 pkg.mSetEnabled = p.enabled; 8358 final String codePath = pkg.applicationInfo.sourceDir; 8359 final String resourcePath = pkg.applicationInfo.publicSourceDir; 8360 // Update code path if needed 8361 if (!codePath.equalsIgnoreCase(p.codePathString)) { 8362 Slog.w(TAG, "Code path for pkg : " + p.pkg.packageName + 8363 " changing from " + p.codePathString + " to " + codePath); 8364 p.codePath = new File(codePath); 8365 p.codePathString = codePath; 8366 } 8367 //Update resource path if needed 8368 if (!resourcePath.equalsIgnoreCase(p.resourcePathString)) { 8369 Slog.w(TAG, "Resource path for pkg : " + p.pkg.packageName + 8370 " changing from " + p.resourcePathString + " to " + resourcePath); 8371 p.resourcePath = new File(resourcePath); 8372 p.resourcePathString = resourcePath; 8373 } 8374 // Update the native library path if needed 8375 final String nativeLibraryPath = pkg.applicationInfo.nativeLibraryDir; 8376 if (nativeLibraryPath != null 8377 && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) { 8378 p.nativeLibraryPathString = nativeLibraryPath; 8379 } 8380 // Update version code if needed 8381 if (pkg.mVersionCode != p.versionCode) { 8382 p.versionCode = pkg.mVersionCode; 8383 } 8384 // Update signatures if needed. 8385 if (p.signatures.mSignatures == null) { 8386 p.signatures.assignSignatures(pkg.mSignatures); 8387 } 8388 // If this app defines a shared user id initialize 8389 // the shared user signatures as well. 8390 if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) { 8391 p.sharedUser.signatures.assignSignatures(pkg.mSignatures); 8392 } 8393 addPackageSettingLP(p, pkg.packageName, p.sharedUser); 8394 } 8395 8396 // Utility method that adds a PackageSetting to mPackages and 8397 // completes updating the shared user attributes 8398 private void addPackageSettingLP(PackageSetting p, String name, 8399 SharedUserSetting sharedUser) { 8400 mPackages.put(name, p); 8401 if (sharedUser != null) { 8402 if (p.sharedUser != null && p.sharedUser != sharedUser) { 8403 reportSettingsProblem(Log.ERROR, 8404 "Package " + p.name + " was user " 8405 + p.sharedUser + " but is now " + sharedUser 8406 + "; I am not changing its files so it will probably fail!"); 8407 p.sharedUser.packages.remove(p); 8408 } else if (p.userId != sharedUser.userId) { 8409 reportSettingsProblem(Log.ERROR, 8410 "Package " + p.name + " was user id " + p.userId 8411 + " but is now user " + sharedUser 8412 + " with id " + sharedUser.userId 8413 + "; I am not changing its files so it will probably fail!"); 8414 } 8415 8416 sharedUser.packages.add(p); 8417 p.sharedUser = sharedUser; 8418 p.userId = sharedUser.userId; 8419 } 8420 } 8421 8422 /* 8423 * Update the shared user setting when a package using 8424 * specifying the shared user id is removed. The gids 8425 * associated with each permission of the deleted package 8426 * are removed from the shared user's gid list only if its 8427 * not in use by other permissions of packages in the 8428 * shared user setting. 8429 */ 8430 private void updateSharedUserPermsLP(PackageSetting deletedPs, int[] globalGids) { 8431 if ( (deletedPs == null) || (deletedPs.pkg == null)) { 8432 Slog.i(TAG, "Trying to update info for null package. Just ignoring"); 8433 return; 8434 } 8435 // No sharedUserId 8436 if (deletedPs.sharedUser == null) { 8437 return; 8438 } 8439 SharedUserSetting sus = deletedPs.sharedUser; 8440 // Update permissions 8441 for (String eachPerm: deletedPs.pkg.requestedPermissions) { 8442 boolean used = false; 8443 if (!sus.grantedPermissions.contains (eachPerm)) { 8444 continue; 8445 } 8446 for (PackageSetting pkg:sus.packages) { 8447 if (pkg.pkg != null && 8448 !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) && 8449 pkg.pkg.requestedPermissions.contains(eachPerm)) { 8450 used = true; 8451 break; 8452 } 8453 } 8454 if (!used) { 8455 // can safely delete this permission from list 8456 sus.grantedPermissions.remove(eachPerm); 8457 } 8458 } 8459 // Update gids 8460 int newGids[] = globalGids; 8461 for (String eachPerm : sus.grantedPermissions) { 8462 BasePermission bp = mPermissions.get(eachPerm); 8463 if (bp != null) { 8464 newGids = appendInts(newGids, bp.gids); 8465 } 8466 } 8467 sus.gids = newGids; 8468 } 8469 8470 private int removePackageLP(String name) { 8471 PackageSetting p = mPackages.get(name); 8472 if (p != null) { 8473 mPackages.remove(name); 8474 if (p.sharedUser != null) { 8475 p.sharedUser.packages.remove(p); 8476 if (p.sharedUser.packages.size() == 0) { 8477 mSharedUsers.remove(p.sharedUser.name); 8478 removeUserIdLP(p.sharedUser.userId); 8479 return p.sharedUser.userId; 8480 } 8481 } else { 8482 removeUserIdLP(p.userId); 8483 return p.userId; 8484 } 8485 } 8486 return -1; 8487 } 8488 8489 private void replacePackageLP(String name, PackageSetting newp) { 8490 PackageSetting p = mPackages.get(name); 8491 if (p != null) { 8492 if (p.sharedUser != null) { 8493 p.sharedUser.packages.remove(p); 8494 p.sharedUser.packages.add(newp); 8495 } else { 8496 replaceUserIdLP(p.userId, newp); 8497 } 8498 } 8499 mPackages.put(name, newp); 8500 } 8501 8502 private boolean addUserIdLP(int uid, Object obj, Object name) { 8503 if (uid >= FIRST_APPLICATION_UID + MAX_APPLICATION_UIDS) { 8504 return false; 8505 } 8506 8507 if (uid >= FIRST_APPLICATION_UID) { 8508 int N = mUserIds.size(); 8509 final int index = uid - FIRST_APPLICATION_UID; 8510 while (index >= N) { 8511 mUserIds.add(null); 8512 N++; 8513 } 8514 if (mUserIds.get(index) != null) { 8515 reportSettingsProblem(Log.ERROR, 8516 "Adding duplicate user id: " + uid 8517 + " name=" + name); 8518 return false; 8519 } 8520 mUserIds.set(index, obj); 8521 } else { 8522 if (mOtherUserIds.get(uid) != null) { 8523 reportSettingsProblem(Log.ERROR, 8524 "Adding duplicate shared id: " + uid 8525 + " name=" + name); 8526 return false; 8527 } 8528 mOtherUserIds.put(uid, obj); 8529 } 8530 return true; 8531 } 8532 8533 public Object getUserIdLP(int uid) { 8534 if (uid >= FIRST_APPLICATION_UID) { 8535 int N = mUserIds.size(); 8536 final int index = uid - FIRST_APPLICATION_UID; 8537 return index < N ? mUserIds.get(index) : null; 8538 } else { 8539 return mOtherUserIds.get(uid); 8540 } 8541 } 8542 8543 private Set<String> findPackagesWithFlag(int flag) { 8544 Set<String> ret = new HashSet<String>(); 8545 for (PackageSetting ps : mPackages.values()) { 8546 // Has to match atleast all the flag bits set on flag 8547 if ((ps.pkgFlags & flag) == flag) { 8548 ret.add(ps.name); 8549 } 8550 } 8551 return ret; 8552 } 8553 8554 private void removeUserIdLP(int uid) { 8555 if (uid >= FIRST_APPLICATION_UID) { 8556 int N = mUserIds.size(); 8557 final int index = uid - FIRST_APPLICATION_UID; 8558 if (index < N) mUserIds.set(index, null); 8559 } else { 8560 mOtherUserIds.remove(uid); 8561 } 8562 } 8563 8564 private void replaceUserIdLP(int uid, Object obj) { 8565 if (uid >= FIRST_APPLICATION_UID) { 8566 int N = mUserIds.size(); 8567 final int index = uid - FIRST_APPLICATION_UID; 8568 if (index < N) mUserIds.set(index, obj); 8569 } else { 8570 mOtherUserIds.put(uid, obj); 8571 } 8572 } 8573 8574 void writeLP() { 8575 //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024); 8576 8577 // Keep the old settings around until we know the new ones have 8578 // been successfully written. 8579 if (mSettingsFilename.exists()) { 8580 // Presence of backup settings file indicates that we failed 8581 // to persist settings earlier. So preserve the older 8582 // backup for future reference since the current settings 8583 // might have been corrupted. 8584 if (!mBackupSettingsFilename.exists()) { 8585 if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) { 8586 Slog.w(TAG, "Unable to backup package manager settings, current changes will be lost at reboot"); 8587 return; 8588 } 8589 } else { 8590 mSettingsFilename.delete(); 8591 Slog.w(TAG, "Preserving older settings backup"); 8592 } 8593 } 8594 8595 mPastSignatures.clear(); 8596 8597 try { 8598 FileOutputStream fstr = new FileOutputStream(mSettingsFilename); 8599 BufferedOutputStream str = new BufferedOutputStream(fstr); 8600 8601 //XmlSerializer serializer = XmlUtils.serializerInstance(); 8602 XmlSerializer serializer = new FastXmlSerializer(); 8603 serializer.setOutput(str, "utf-8"); 8604 serializer.startDocument(null, true); 8605 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 8606 8607 serializer.startTag(null, "packages"); 8608 8609 serializer.startTag(null, "last-platform-version"); 8610 serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform)); 8611 serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform)); 8612 serializer.endTag(null, "last-platform-version"); 8613 8614 serializer.startTag(null, "permission-trees"); 8615 for (BasePermission bp : mPermissionTrees.values()) { 8616 writePermission(serializer, bp); 8617 } 8618 serializer.endTag(null, "permission-trees"); 8619 8620 serializer.startTag(null, "permissions"); 8621 for (BasePermission bp : mPermissions.values()) { 8622 writePermission(serializer, bp); 8623 } 8624 serializer.endTag(null, "permissions"); 8625 8626 for (PackageSetting pkg : mPackages.values()) { 8627 writePackage(serializer, pkg); 8628 } 8629 8630 for (PackageSetting pkg : mDisabledSysPackages.values()) { 8631 writeDisabledSysPackage(serializer, pkg); 8632 } 8633 8634 serializer.startTag(null, "preferred-activities"); 8635 for (PreferredActivity pa : mPreferredActivities.filterSet()) { 8636 serializer.startTag(null, "item"); 8637 pa.writeToXml(serializer); 8638 serializer.endTag(null, "item"); 8639 } 8640 serializer.endTag(null, "preferred-activities"); 8641 8642 for (SharedUserSetting usr : mSharedUsers.values()) { 8643 serializer.startTag(null, "shared-user"); 8644 serializer.attribute(null, "name", usr.name); 8645 serializer.attribute(null, "userId", 8646 Integer.toString(usr.userId)); 8647 usr.signatures.writeXml(serializer, "sigs", mPastSignatures); 8648 serializer.startTag(null, "perms"); 8649 for (String name : usr.grantedPermissions) { 8650 serializer.startTag(null, "item"); 8651 serializer.attribute(null, "name", name); 8652 serializer.endTag(null, "item"); 8653 } 8654 serializer.endTag(null, "perms"); 8655 serializer.endTag(null, "shared-user"); 8656 } 8657 8658 if (mPackagesToBeCleaned.size() > 0) { 8659 for (int i=0; i<mPackagesToBeCleaned.size(); i++) { 8660 serializer.startTag(null, "cleaning-package"); 8661 serializer.attribute(null, "name", mPackagesToBeCleaned.get(i)); 8662 serializer.endTag(null, "cleaning-package"); 8663 } 8664 } 8665 8666 if (mRenamedPackages.size() > 0) { 8667 for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) { 8668 serializer.startTag(null, "renamed-package"); 8669 serializer.attribute(null, "new", e.getKey()); 8670 serializer.attribute(null, "old", e.getValue()); 8671 serializer.endTag(null, "renamed-package"); 8672 } 8673 } 8674 8675 serializer.endTag(null, "packages"); 8676 8677 serializer.endDocument(); 8678 8679 str.flush(); 8680 FileUtils.sync(fstr); 8681 str.close(); 8682 8683 // New settings successfully written, old ones are no longer 8684 // needed. 8685 mBackupSettingsFilename.delete(); 8686 FileUtils.setPermissions(mSettingsFilename.toString(), 8687 FileUtils.S_IRUSR|FileUtils.S_IWUSR 8688 |FileUtils.S_IRGRP|FileUtils.S_IWGRP 8689 |FileUtils.S_IROTH, 8690 -1, -1); 8691 8692 // Write package list file now, use a JournaledFile. 8693 // 8694 File tempFile = new File(mPackageListFilename.toString() + ".tmp"); 8695 JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile); 8696 8697 fstr = new FileOutputStream(journal.chooseForWrite()); 8698 str = new BufferedOutputStream(fstr); 8699 try { 8700 StringBuilder sb = new StringBuilder(); 8701 for (PackageSetting pkg : mPackages.values()) { 8702 ApplicationInfo ai = pkg.pkg.applicationInfo; 8703 String dataPath = ai.dataDir; 8704 boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 8705 8706 // Avoid any application that has a space in its path 8707 // or that is handled by the system. 8708 if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID) 8709 continue; 8710 8711 // we store on each line the following information for now: 8712 // 8713 // pkgName - package name 8714 // userId - application-specific user id 8715 // debugFlag - 0 or 1 if the package is debuggable. 8716 // dataPath - path to package's data path 8717 // 8718 // NOTE: We prefer not to expose all ApplicationInfo flags for now. 8719 // 8720 // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS 8721 // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: 8722 // system/core/run-as/run-as.c 8723 // 8724 sb.setLength(0); 8725 sb.append(ai.packageName); 8726 sb.append(" "); 8727 sb.append((int)ai.uid); 8728 sb.append(isDebug ? " 1 " : " 0 "); 8729 sb.append(dataPath); 8730 sb.append("\n"); 8731 str.write(sb.toString().getBytes()); 8732 } 8733 str.flush(); 8734 FileUtils.sync(fstr); 8735 str.close(); 8736 journal.commit(); 8737 } 8738 catch (Exception e) { 8739 journal.rollback(); 8740 } 8741 8742 FileUtils.setPermissions(mPackageListFilename.toString(), 8743 FileUtils.S_IRUSR|FileUtils.S_IWUSR 8744 |FileUtils.S_IRGRP|FileUtils.S_IWGRP 8745 |FileUtils.S_IROTH, 8746 -1, -1); 8747 8748 return; 8749 8750 } catch(XmlPullParserException e) { 8751 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e); 8752 } catch(java.io.IOException e) { 8753 Slog.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e); 8754 } 8755 // Clean up partially written files 8756 if (mSettingsFilename.exists()) { 8757 if (!mSettingsFilename.delete()) { 8758 Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename); 8759 } 8760 } 8761 //Debug.stopMethodTracing(); 8762 } 8763 8764 void writeDisabledSysPackage(XmlSerializer serializer, final PackageSetting pkg) 8765 throws java.io.IOException { 8766 serializer.startTag(null, "updated-package"); 8767 serializer.attribute(null, "name", pkg.name); 8768 if (pkg.realName != null) { 8769 serializer.attribute(null, "realName", pkg.realName); 8770 } 8771 serializer.attribute(null, "codePath", pkg.codePathString); 8772 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); 8773 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); 8774 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); 8775 serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); 8776 if (!pkg.resourcePathString.equals(pkg.codePathString)) { 8777 serializer.attribute(null, "resourcePath", pkg.resourcePathString); 8778 } 8779 if (pkg.nativeLibraryPathString != null) { 8780 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); 8781 } 8782 if (pkg.sharedUser == null) { 8783 serializer.attribute(null, "userId", 8784 Integer.toString(pkg.userId)); 8785 } else { 8786 serializer.attribute(null, "sharedUserId", 8787 Integer.toString(pkg.userId)); 8788 } 8789 serializer.startTag(null, "perms"); 8790 if (pkg.sharedUser == null) { 8791 // If this is a shared user, the permissions will 8792 // be written there. We still need to write an 8793 // empty permissions list so permissionsFixed will 8794 // be set. 8795 for (final String name : pkg.grantedPermissions) { 8796 BasePermission bp = mPermissions.get(name); 8797 if (bp != null) { 8798 // We only need to write signature or system permissions but this wont 8799 // match the semantics of grantedPermissions. So write all permissions. 8800 serializer.startTag(null, "item"); 8801 serializer.attribute(null, "name", name); 8802 serializer.endTag(null, "item"); 8803 } 8804 } 8805 } 8806 serializer.endTag(null, "perms"); 8807 serializer.endTag(null, "updated-package"); 8808 } 8809 8810 void writePackage(XmlSerializer serializer, final PackageSetting pkg) 8811 throws java.io.IOException { 8812 serializer.startTag(null, "package"); 8813 serializer.attribute(null, "name", pkg.name); 8814 if (pkg.realName != null) { 8815 serializer.attribute(null, "realName", pkg.realName); 8816 } 8817 serializer.attribute(null, "codePath", pkg.codePathString); 8818 if (!pkg.resourcePathString.equals(pkg.codePathString)) { 8819 serializer.attribute(null, "resourcePath", pkg.resourcePathString); 8820 } 8821 if (pkg.nativeLibraryPathString != null) { 8822 serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString); 8823 } 8824 serializer.attribute(null, "flags", 8825 Integer.toString(pkg.pkgFlags)); 8826 serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); 8827 serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); 8828 serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); 8829 serializer.attribute(null, "version", String.valueOf(pkg.versionCode)); 8830 if (pkg.sharedUser == null) { 8831 serializer.attribute(null, "userId", 8832 Integer.toString(pkg.userId)); 8833 } else { 8834 serializer.attribute(null, "sharedUserId", 8835 Integer.toString(pkg.userId)); 8836 } 8837 if (pkg.uidError) { 8838 serializer.attribute(null, "uidError", "true"); 8839 } 8840 if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) { 8841 serializer.attribute(null, "enabled", 8842 pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED 8843 ? "true" : "false"); 8844 } 8845 if(pkg.installStatus == PKG_INSTALL_INCOMPLETE) { 8846 serializer.attribute(null, "installStatus", "false"); 8847 } 8848 if (pkg.installerPackageName != null) { 8849 serializer.attribute(null, "installer", pkg.installerPackageName); 8850 } 8851 pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); 8852 if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { 8853 serializer.startTag(null, "perms"); 8854 if (pkg.sharedUser == null) { 8855 // If this is a shared user, the permissions will 8856 // be written there. We still need to write an 8857 // empty permissions list so permissionsFixed will 8858 // be set. 8859 for (final String name : pkg.grantedPermissions) { 8860 serializer.startTag(null, "item"); 8861 serializer.attribute(null, "name", name); 8862 serializer.endTag(null, "item"); 8863 } 8864 } 8865 serializer.endTag(null, "perms"); 8866 } 8867 if (pkg.disabledComponents.size() > 0) { 8868 serializer.startTag(null, "disabled-components"); 8869 for (final String name : pkg.disabledComponents) { 8870 serializer.startTag(null, "item"); 8871 serializer.attribute(null, "name", name); 8872 serializer.endTag(null, "item"); 8873 } 8874 serializer.endTag(null, "disabled-components"); 8875 } 8876 if (pkg.enabledComponents.size() > 0) { 8877 serializer.startTag(null, "enabled-components"); 8878 for (final String name : pkg.enabledComponents) { 8879 serializer.startTag(null, "item"); 8880 serializer.attribute(null, "name", name); 8881 serializer.endTag(null, "item"); 8882 } 8883 serializer.endTag(null, "enabled-components"); 8884 } 8885 8886 serializer.endTag(null, "package"); 8887 } 8888 8889 void writePermission(XmlSerializer serializer, BasePermission bp) 8890 throws XmlPullParserException, java.io.IOException { 8891 if (bp.type != BasePermission.TYPE_BUILTIN 8892 && bp.sourcePackage != null) { 8893 serializer.startTag(null, "item"); 8894 serializer.attribute(null, "name", bp.name); 8895 serializer.attribute(null, "package", bp.sourcePackage); 8896 if (bp.protectionLevel != 8897 PermissionInfo.PROTECTION_NORMAL) { 8898 serializer.attribute(null, "protection", 8899 Integer.toString(bp.protectionLevel)); 8900 } 8901 if (DEBUG_SETTINGS) Log.v(TAG, 8902 "Writing perm: name=" + bp.name + " type=" + bp.type); 8903 if (bp.type == BasePermission.TYPE_DYNAMIC) { 8904 PermissionInfo pi = bp.perm != null ? bp.perm.info 8905 : bp.pendingInfo; 8906 if (pi != null) { 8907 serializer.attribute(null, "type", "dynamic"); 8908 if (pi.icon != 0) { 8909 serializer.attribute(null, "icon", 8910 Integer.toString(pi.icon)); 8911 } 8912 if (pi.nonLocalizedLabel != null) { 8913 serializer.attribute(null, "label", 8914 pi.nonLocalizedLabel.toString()); 8915 } 8916 } 8917 } 8918 serializer.endTag(null, "item"); 8919 } 8920 } 8921 8922 String getReadMessagesLP() { 8923 return mReadMessages.toString(); 8924 } 8925 8926 ArrayList<PackageSetting> getListOfIncompleteInstallPackages() { 8927 HashSet<String> kList = new HashSet<String>(mPackages.keySet()); 8928 Iterator<String> its = kList.iterator(); 8929 ArrayList<PackageSetting> ret = new ArrayList<PackageSetting>(); 8930 while(its.hasNext()) { 8931 String key = its.next(); 8932 PackageSetting ps = mPackages.get(key); 8933 if(ps.getInstallStatus() == PKG_INSTALL_INCOMPLETE) { 8934 ret.add(ps); 8935 } 8936 } 8937 return ret; 8938 } 8939 8940 boolean readLP() { 8941 FileInputStream str = null; 8942 if (mBackupSettingsFilename.exists()) { 8943 try { 8944 str = new FileInputStream(mBackupSettingsFilename); 8945 mReadMessages.append("Reading from backup settings file\n"); 8946 reportSettingsProblem(Log.INFO, "Need to read from backup settings file"); 8947 if (mSettingsFilename.exists()) { 8948 // If both the backup and settings file exist, we 8949 // ignore the settings since it might have been 8950 // corrupted. 8951 Slog.w(TAG, "Cleaning up settings file " + mSettingsFilename); 8952 mSettingsFilename.delete(); 8953 } 8954 } catch (java.io.IOException e) { 8955 // We'll try for the normal settings file. 8956 } 8957 } 8958 8959 mPastSignatures.clear(); 8960 8961 try { 8962 if (str == null) { 8963 if (!mSettingsFilename.exists()) { 8964 mReadMessages.append("No settings file found\n"); 8965 reportSettingsProblem(Log.INFO, "No settings file; creating initial state"); 8966 return false; 8967 } 8968 str = new FileInputStream(mSettingsFilename); 8969 } 8970 XmlPullParser parser = Xml.newPullParser(); 8971 parser.setInput(str, null); 8972 8973 int type; 8974 while ((type=parser.next()) != XmlPullParser.START_TAG 8975 && type != XmlPullParser.END_DOCUMENT) { 8976 ; 8977 } 8978 8979 if (type != XmlPullParser.START_TAG) { 8980 mReadMessages.append("No start tag found in settings file\n"); 8981 reportSettingsProblem(Log.WARN, "No start tag found in package manager settings"); 8982 return false; 8983 } 8984 8985 int outerDepth = parser.getDepth(); 8986 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 8987 && (type != XmlPullParser.END_TAG 8988 || parser.getDepth() > outerDepth)) { 8989 if (type == XmlPullParser.END_TAG 8990 || type == XmlPullParser.TEXT) { 8991 continue; 8992 } 8993 8994 String tagName = parser.getName(); 8995 if (tagName.equals("package")) { 8996 readPackageLP(parser); 8997 } else if (tagName.equals("permissions")) { 8998 readPermissionsLP(mPermissions, parser); 8999 } else if (tagName.equals("permission-trees")) { 9000 readPermissionsLP(mPermissionTrees, parser); 9001 } else if (tagName.equals("shared-user")) { 9002 readSharedUserLP(parser); 9003 } else if (tagName.equals("preferred-packages")) { 9004 // no longer used. 9005 } else if (tagName.equals("preferred-activities")) { 9006 readPreferredActivitiesLP(parser); 9007 } else if(tagName.equals("updated-package")) { 9008 readDisabledSysPackageLP(parser); 9009 } else if (tagName.equals("cleaning-package")) { 9010 String name = parser.getAttributeValue(null, "name"); 9011 if (name != null) { 9012 mPackagesToBeCleaned.add(name); 9013 } 9014 } else if (tagName.equals("renamed-package")) { 9015 String nname = parser.getAttributeValue(null, "new"); 9016 String oname = parser.getAttributeValue(null, "old"); 9017 if (nname != null && oname != null) { 9018 mRenamedPackages.put(nname, oname); 9019 } 9020 } else if (tagName.equals("last-platform-version")) { 9021 mInternalSdkPlatform = mExternalSdkPlatform = 0; 9022 try { 9023 String internal = parser.getAttributeValue(null, "internal"); 9024 if (internal != null) { 9025 mInternalSdkPlatform = Integer.parseInt(internal); 9026 } 9027 String external = parser.getAttributeValue(null, "external"); 9028 if (external != null) { 9029 mExternalSdkPlatform = Integer.parseInt(external); 9030 } 9031 } catch (NumberFormatException e) { 9032 } 9033 } else { 9034 Slog.w(TAG, "Unknown element under <packages>: " 9035 + parser.getName()); 9036 XmlUtils.skipCurrentTag(parser); 9037 } 9038 } 9039 9040 str.close(); 9041 9042 } catch(XmlPullParserException e) { 9043 mReadMessages.append("Error reading: " + e.toString()); 9044 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); 9045 Slog.e(TAG, "Error reading package manager settings", e); 9046 9047 } catch(java.io.IOException e) { 9048 mReadMessages.append("Error reading: " + e.toString()); 9049 reportSettingsProblem(Log.ERROR, "Error reading settings: " + e); 9050 Slog.e(TAG, "Error reading package manager settings", e); 9051 9052 } 9053 9054 int N = mPendingPackages.size(); 9055 for (int i=0; i<N; i++) { 9056 final PendingPackage pp = mPendingPackages.get(i); 9057 Object idObj = getUserIdLP(pp.sharedId); 9058 if (idObj != null && idObj instanceof SharedUserSetting) { 9059 PackageSetting p = getPackageLP(pp.name, null, pp.realName, 9060 (SharedUserSetting) idObj, pp.codePath, pp.resourcePath, 9061 pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags, true, true); 9062 if (p == null) { 9063 reportSettingsProblem(Log.WARN, "Unable to create application package for " 9064 + pp.name); 9065 continue; 9066 } 9067 p.copyFrom(pp); 9068 } else if (idObj != null) { 9069 String msg = "Bad package setting: package " + pp.name 9070 + " has shared uid " + pp.sharedId 9071 + " that is not a shared uid\n"; 9072 mReadMessages.append(msg); 9073 reportSettingsProblem(Log.ERROR, msg); 9074 } else { 9075 String msg = "Bad package setting: package " + pp.name 9076 + " has shared uid " + pp.sharedId 9077 + " that is not defined\n"; 9078 mReadMessages.append(msg); 9079 reportSettingsProblem(Log.ERROR, msg); 9080 } 9081 } 9082 mPendingPackages.clear(); 9083 9084 /* 9085 * Make sure all the updated system packages have their shared users 9086 * associated with them. 9087 */ 9088 final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator(); 9089 while (disabledIt.hasNext()) { 9090 final PackageSetting disabledPs = disabledIt.next(); 9091 final Object id = getUserIdLP(disabledPs.userId); 9092 if (id != null && id instanceof SharedUserSetting) { 9093 disabledPs.sharedUser = (SharedUserSetting) id; 9094 } 9095 } 9096 9097 mReadMessages.append("Read completed successfully: " 9098 + mPackages.size() + " packages, " 9099 + mSharedUsers.size() + " shared uids\n"); 9100 9101 return true; 9102 } 9103 9104 private int readInt(XmlPullParser parser, String ns, String name, 9105 int defValue) { 9106 String v = parser.getAttributeValue(ns, name); 9107 try { 9108 if (v == null) { 9109 return defValue; 9110 } 9111 return Integer.parseInt(v); 9112 } catch (NumberFormatException e) { 9113 reportSettingsProblem(Log.WARN, 9114 "Error in package manager settings: attribute " + 9115 name + " has bad integer value " + v + " at " 9116 + parser.getPositionDescription()); 9117 } 9118 return defValue; 9119 } 9120 9121 private void readPermissionsLP(HashMap<String, BasePermission> out, 9122 XmlPullParser parser) 9123 throws IOException, XmlPullParserException { 9124 int outerDepth = parser.getDepth(); 9125 int type; 9126 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9127 && (type != XmlPullParser.END_TAG 9128 || parser.getDepth() > outerDepth)) { 9129 if (type == XmlPullParser.END_TAG 9130 || type == XmlPullParser.TEXT) { 9131 continue; 9132 } 9133 9134 String tagName = parser.getName(); 9135 if (tagName.equals("item")) { 9136 String name = parser.getAttributeValue(null, "name"); 9137 String sourcePackage = parser.getAttributeValue(null, "package"); 9138 String ptype = parser.getAttributeValue(null, "type"); 9139 if (name != null && sourcePackage != null) { 9140 boolean dynamic = "dynamic".equals(ptype); 9141 BasePermission bp = new BasePermission(name, sourcePackage, 9142 dynamic 9143 ? BasePermission.TYPE_DYNAMIC 9144 : BasePermission.TYPE_NORMAL); 9145 bp.protectionLevel = readInt(parser, null, "protection", 9146 PermissionInfo.PROTECTION_NORMAL); 9147 if (dynamic) { 9148 PermissionInfo pi = new PermissionInfo(); 9149 pi.packageName = sourcePackage.intern(); 9150 pi.name = name.intern(); 9151 pi.icon = readInt(parser, null, "icon", 0); 9152 pi.nonLocalizedLabel = parser.getAttributeValue( 9153 null, "label"); 9154 pi.protectionLevel = bp.protectionLevel; 9155 bp.pendingInfo = pi; 9156 } 9157 out.put(bp.name, bp); 9158 } else { 9159 reportSettingsProblem(Log.WARN, 9160 "Error in package manager settings: permissions has" 9161 + " no name at " + parser.getPositionDescription()); 9162 } 9163 } else { 9164 reportSettingsProblem(Log.WARN, 9165 "Unknown element reading permissions: " 9166 + parser.getName() + " at " 9167 + parser.getPositionDescription()); 9168 } 9169 XmlUtils.skipCurrentTag(parser); 9170 } 9171 } 9172 9173 private void readDisabledSysPackageLP(XmlPullParser parser) 9174 throws XmlPullParserException, IOException { 9175 String name = parser.getAttributeValue(null, "name"); 9176 String realName = parser.getAttributeValue(null, "realName"); 9177 String codePathStr = parser.getAttributeValue(null, "codePath"); 9178 String resourcePathStr = parser.getAttributeValue(null, "resourcePath"); 9179 String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); 9180 if (resourcePathStr == null) { 9181 resourcePathStr = codePathStr; 9182 } 9183 String version = parser.getAttributeValue(null, "version"); 9184 int versionCode = 0; 9185 if (version != null) { 9186 try { 9187 versionCode = Integer.parseInt(version); 9188 } catch (NumberFormatException e) { 9189 } 9190 } 9191 9192 int pkgFlags = 0; 9193 pkgFlags |= ApplicationInfo.FLAG_SYSTEM; 9194 PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), 9195 new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags); 9196 String timeStampStr = parser.getAttributeValue(null, "ft"); 9197 if (timeStampStr != null) { 9198 try { 9199 long timeStamp = Long.parseLong(timeStampStr, 16); 9200 ps.setTimeStamp(timeStamp); 9201 } catch (NumberFormatException e) { 9202 } 9203 } else { 9204 timeStampStr = parser.getAttributeValue(null, "ts"); 9205 if (timeStampStr != null) { 9206 try { 9207 long timeStamp = Long.parseLong(timeStampStr); 9208 ps.setTimeStamp(timeStamp); 9209 } catch (NumberFormatException e) { 9210 } 9211 } 9212 } 9213 timeStampStr = parser.getAttributeValue(null, "it"); 9214 if (timeStampStr != null) { 9215 try { 9216 ps.firstInstallTime = Long.parseLong(timeStampStr, 16); 9217 } catch (NumberFormatException e) { 9218 } 9219 } 9220 timeStampStr = parser.getAttributeValue(null, "ut"); 9221 if (timeStampStr != null) { 9222 try { 9223 ps.lastUpdateTime = Long.parseLong(timeStampStr, 16); 9224 } catch (NumberFormatException e) { 9225 } 9226 } 9227 String idStr = parser.getAttributeValue(null, "userId"); 9228 ps.userId = idStr != null ? Integer.parseInt(idStr) : 0; 9229 if(ps.userId <= 0) { 9230 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); 9231 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; 9232 } 9233 int outerDepth = parser.getDepth(); 9234 int type; 9235 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9236 && (type != XmlPullParser.END_TAG 9237 || parser.getDepth() > outerDepth)) { 9238 if (type == XmlPullParser.END_TAG 9239 || type == XmlPullParser.TEXT) { 9240 continue; 9241 } 9242 9243 String tagName = parser.getName(); 9244 if (tagName.equals("perms")) { 9245 readGrantedPermissionsLP(parser, 9246 ps.grantedPermissions); 9247 } else { 9248 reportSettingsProblem(Log.WARN, 9249 "Unknown element under <updated-package>: " 9250 + parser.getName()); 9251 XmlUtils.skipCurrentTag(parser); 9252 } 9253 } 9254 mDisabledSysPackages.put(name, ps); 9255 } 9256 9257 private void readPackageLP(XmlPullParser parser) 9258 throws XmlPullParserException, IOException { 9259 String name = null; 9260 String realName = null; 9261 String idStr = null; 9262 String sharedIdStr = null; 9263 String codePathStr = null; 9264 String resourcePathStr = null; 9265 String nativeLibraryPathStr = null; 9266 String systemStr = null; 9267 String installerPackageName = null; 9268 String uidError = null; 9269 int pkgFlags = 0; 9270 long timeStamp = 0; 9271 long firstInstallTime = 0; 9272 long lastUpdateTime = 0; 9273 PackageSettingBase packageSetting = null; 9274 String version = null; 9275 int versionCode = 0; 9276 try { 9277 name = parser.getAttributeValue(null, "name"); 9278 realName = parser.getAttributeValue(null, "realName"); 9279 idStr = parser.getAttributeValue(null, "userId"); 9280 uidError = parser.getAttributeValue(null, "uidError"); 9281 sharedIdStr = parser.getAttributeValue(null, "sharedUserId"); 9282 codePathStr = parser.getAttributeValue(null, "codePath"); 9283 resourcePathStr = parser.getAttributeValue(null, "resourcePath"); 9284 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); 9285 version = parser.getAttributeValue(null, "version"); 9286 if (version != null) { 9287 try { 9288 versionCode = Integer.parseInt(version); 9289 } catch (NumberFormatException e) { 9290 } 9291 } 9292 installerPackageName = parser.getAttributeValue(null, "installer"); 9293 9294 systemStr = parser.getAttributeValue(null, "flags"); 9295 if (systemStr != null) { 9296 try { 9297 pkgFlags = Integer.parseInt(systemStr); 9298 } catch (NumberFormatException e) { 9299 } 9300 } else { 9301 // For backward compatibility 9302 systemStr = parser.getAttributeValue(null, "system"); 9303 if (systemStr != null) { 9304 pkgFlags |= ("true".equalsIgnoreCase(systemStr)) ? ApplicationInfo.FLAG_SYSTEM : 0; 9305 } else { 9306 // Old settings that don't specify system... just treat 9307 // them as system, good enough. 9308 pkgFlags |= ApplicationInfo.FLAG_SYSTEM; 9309 } 9310 } 9311 String timeStampStr = parser.getAttributeValue(null, "ft"); 9312 if (timeStampStr != null) { 9313 try { 9314 timeStamp = Long.parseLong(timeStampStr, 16); 9315 } catch (NumberFormatException e) { 9316 } 9317 } else { 9318 timeStampStr = parser.getAttributeValue(null, "ts"); 9319 if (timeStampStr != null) { 9320 try { 9321 timeStamp = Long.parseLong(timeStampStr); 9322 } catch (NumberFormatException e) { 9323 } 9324 } 9325 } 9326 timeStampStr = parser.getAttributeValue(null, "it"); 9327 if (timeStampStr != null) { 9328 try { 9329 firstInstallTime = Long.parseLong(timeStampStr, 16); 9330 } catch (NumberFormatException e) { 9331 } 9332 } 9333 timeStampStr = parser.getAttributeValue(null, "ut"); 9334 if (timeStampStr != null) { 9335 try { 9336 lastUpdateTime = Long.parseLong(timeStampStr, 16); 9337 } catch (NumberFormatException e) { 9338 } 9339 } 9340 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name 9341 + " userId=" + idStr + " sharedUserId=" + sharedIdStr); 9342 int userId = idStr != null ? Integer.parseInt(idStr) : 0; 9343 if (resourcePathStr == null) { 9344 resourcePathStr = codePathStr; 9345 } 9346 if (realName != null) { 9347 realName = realName.intern(); 9348 } 9349 if (name == null) { 9350 reportSettingsProblem(Log.WARN, 9351 "Error in package manager settings: <package> has no name at " 9352 + parser.getPositionDescription()); 9353 } else if (codePathStr == null) { 9354 reportSettingsProblem(Log.WARN, 9355 "Error in package manager settings: <package> has no codePath at " 9356 + parser.getPositionDescription()); 9357 } else if (userId > 0) { 9358 packageSetting = addPackageLP(name.intern(), realName, new File(codePathStr), 9359 new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode, 9360 pkgFlags); 9361 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name 9362 + ": userId=" + userId + " pkg=" + packageSetting); 9363 if (packageSetting == null) { 9364 reportSettingsProblem(Log.ERROR, 9365 "Failure adding uid " + userId 9366 + " while parsing settings at " 9367 + parser.getPositionDescription()); 9368 } else { 9369 packageSetting.setTimeStamp(timeStamp); 9370 packageSetting.firstInstallTime = firstInstallTime; 9371 packageSetting.lastUpdateTime = lastUpdateTime; 9372 } 9373 } else if (sharedIdStr != null) { 9374 userId = sharedIdStr != null 9375 ? Integer.parseInt(sharedIdStr) : 0; 9376 if (userId > 0) { 9377 packageSetting = new PendingPackage(name.intern(), realName, 9378 new File(codePathStr), new File(resourcePathStr), 9379 nativeLibraryPathStr, userId, versionCode, pkgFlags); 9380 packageSetting.setTimeStamp(timeStamp); 9381 packageSetting.firstInstallTime = firstInstallTime; 9382 packageSetting.lastUpdateTime = lastUpdateTime; 9383 mPendingPackages.add((PendingPackage) packageSetting); 9384 if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name 9385 + ": sharedUserId=" + userId + " pkg=" 9386 + packageSetting); 9387 } else { 9388 reportSettingsProblem(Log.WARN, 9389 "Error in package manager settings: package " 9390 + name + " has bad sharedId " + sharedIdStr 9391 + " at " + parser.getPositionDescription()); 9392 } 9393 } else { 9394 reportSettingsProblem(Log.WARN, 9395 "Error in package manager settings: package " 9396 + name + " has bad userId " + idStr + " at " 9397 + parser.getPositionDescription()); 9398 } 9399 } catch (NumberFormatException e) { 9400 reportSettingsProblem(Log.WARN, 9401 "Error in package manager settings: package " 9402 + name + " has bad userId " + idStr + " at " 9403 + parser.getPositionDescription()); 9404 } 9405 if (packageSetting != null) { 9406 packageSetting.uidError = "true".equals(uidError); 9407 packageSetting.installerPackageName = installerPackageName; 9408 packageSetting.nativeLibraryPathString = nativeLibraryPathStr; 9409 final String enabledStr = parser.getAttributeValue(null, "enabled"); 9410 if (enabledStr != null) { 9411 if (enabledStr.equalsIgnoreCase("true")) { 9412 packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED; 9413 } else if (enabledStr.equalsIgnoreCase("false")) { 9414 packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED; 9415 } else if (enabledStr.equalsIgnoreCase("default")) { 9416 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; 9417 } else { 9418 reportSettingsProblem(Log.WARN, 9419 "Error in package manager settings: package " 9420 + name + " has bad enabled value: " + idStr 9421 + " at " + parser.getPositionDescription()); 9422 } 9423 } else { 9424 packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT; 9425 } 9426 final String installStatusStr = parser.getAttributeValue(null, "installStatus"); 9427 if (installStatusStr != null) { 9428 if (installStatusStr.equalsIgnoreCase("false")) { 9429 packageSetting.installStatus = PKG_INSTALL_INCOMPLETE; 9430 } else { 9431 packageSetting.installStatus = PKG_INSTALL_COMPLETE; 9432 } 9433 } 9434 9435 int outerDepth = parser.getDepth(); 9436 int type; 9437 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9438 && (type != XmlPullParser.END_TAG 9439 || parser.getDepth() > outerDepth)) { 9440 if (type == XmlPullParser.END_TAG 9441 || type == XmlPullParser.TEXT) { 9442 continue; 9443 } 9444 9445 String tagName = parser.getName(); 9446 if (tagName.equals("disabled-components")) { 9447 readDisabledComponentsLP(packageSetting, parser); 9448 } else if (tagName.equals("enabled-components")) { 9449 readEnabledComponentsLP(packageSetting, parser); 9450 } else if (tagName.equals("sigs")) { 9451 packageSetting.signatures.readXml(parser, mPastSignatures); 9452 } else if (tagName.equals("perms")) { 9453 readGrantedPermissionsLP(parser, 9454 packageSetting.grantedPermissions); 9455 packageSetting.permissionsFixed = true; 9456 } else { 9457 reportSettingsProblem(Log.WARN, 9458 "Unknown element under <package>: " 9459 + parser.getName()); 9460 XmlUtils.skipCurrentTag(parser); 9461 } 9462 } 9463 } else { 9464 XmlUtils.skipCurrentTag(parser); 9465 } 9466 } 9467 9468 private void readDisabledComponentsLP(PackageSettingBase packageSetting, 9469 XmlPullParser parser) 9470 throws IOException, XmlPullParserException { 9471 int outerDepth = parser.getDepth(); 9472 int type; 9473 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9474 && (type != XmlPullParser.END_TAG 9475 || parser.getDepth() > outerDepth)) { 9476 if (type == XmlPullParser.END_TAG 9477 || type == XmlPullParser.TEXT) { 9478 continue; 9479 } 9480 9481 String tagName = parser.getName(); 9482 if (tagName.equals("item")) { 9483 String name = parser.getAttributeValue(null, "name"); 9484 if (name != null) { 9485 packageSetting.disabledComponents.add(name.intern()); 9486 } else { 9487 reportSettingsProblem(Log.WARN, 9488 "Error in package manager settings: <disabled-components> has" 9489 + " no name at " + parser.getPositionDescription()); 9490 } 9491 } else { 9492 reportSettingsProblem(Log.WARN, 9493 "Unknown element under <disabled-components>: " 9494 + parser.getName()); 9495 } 9496 XmlUtils.skipCurrentTag(parser); 9497 } 9498 } 9499 9500 private void readEnabledComponentsLP(PackageSettingBase packageSetting, 9501 XmlPullParser parser) 9502 throws IOException, XmlPullParserException { 9503 int outerDepth = parser.getDepth(); 9504 int type; 9505 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9506 && (type != XmlPullParser.END_TAG 9507 || parser.getDepth() > outerDepth)) { 9508 if (type == XmlPullParser.END_TAG 9509 || type == XmlPullParser.TEXT) { 9510 continue; 9511 } 9512 9513 String tagName = parser.getName(); 9514 if (tagName.equals("item")) { 9515 String name = parser.getAttributeValue(null, "name"); 9516 if (name != null) { 9517 packageSetting.enabledComponents.add(name.intern()); 9518 } else { 9519 reportSettingsProblem(Log.WARN, 9520 "Error in package manager settings: <enabled-components> has" 9521 + " no name at " + parser.getPositionDescription()); 9522 } 9523 } else { 9524 reportSettingsProblem(Log.WARN, 9525 "Unknown element under <enabled-components>: " 9526 + parser.getName()); 9527 } 9528 XmlUtils.skipCurrentTag(parser); 9529 } 9530 } 9531 9532 private void readSharedUserLP(XmlPullParser parser) 9533 throws XmlPullParserException, IOException { 9534 String name = null; 9535 String idStr = null; 9536 int pkgFlags = 0; 9537 SharedUserSetting su = null; 9538 try { 9539 name = parser.getAttributeValue(null, "name"); 9540 idStr = parser.getAttributeValue(null, "userId"); 9541 int userId = idStr != null ? Integer.parseInt(idStr) : 0; 9542 if ("true".equals(parser.getAttributeValue(null, "system"))) { 9543 pkgFlags |= ApplicationInfo.FLAG_SYSTEM; 9544 } 9545 if (name == null) { 9546 reportSettingsProblem(Log.WARN, 9547 "Error in package manager settings: <shared-user> has no name at " 9548 + parser.getPositionDescription()); 9549 } else if (userId == 0) { 9550 reportSettingsProblem(Log.WARN, 9551 "Error in package manager settings: shared-user " 9552 + name + " has bad userId " + idStr + " at " 9553 + parser.getPositionDescription()); 9554 } else { 9555 if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) { 9556 reportSettingsProblem(Log.ERROR, 9557 "Occurred while parsing settings at " 9558 + parser.getPositionDescription()); 9559 } 9560 } 9561 } catch (NumberFormatException e) { 9562 reportSettingsProblem(Log.WARN, 9563 "Error in package manager settings: package " 9564 + name + " has bad userId " + idStr + " at " 9565 + parser.getPositionDescription()); 9566 }; 9567 9568 if (su != null) { 9569 int outerDepth = parser.getDepth(); 9570 int type; 9571 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9572 && (type != XmlPullParser.END_TAG 9573 || parser.getDepth() > outerDepth)) { 9574 if (type == XmlPullParser.END_TAG 9575 || type == XmlPullParser.TEXT) { 9576 continue; 9577 } 9578 9579 String tagName = parser.getName(); 9580 if (tagName.equals("sigs")) { 9581 su.signatures.readXml(parser, mPastSignatures); 9582 } else if (tagName.equals("perms")) { 9583 readGrantedPermissionsLP(parser, su.grantedPermissions); 9584 } else { 9585 reportSettingsProblem(Log.WARN, 9586 "Unknown element under <shared-user>: " 9587 + parser.getName()); 9588 XmlUtils.skipCurrentTag(parser); 9589 } 9590 } 9591 9592 } else { 9593 XmlUtils.skipCurrentTag(parser); 9594 } 9595 } 9596 9597 private void readGrantedPermissionsLP(XmlPullParser parser, 9598 HashSet<String> outPerms) throws IOException, XmlPullParserException { 9599 int outerDepth = parser.getDepth(); 9600 int type; 9601 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9602 && (type != XmlPullParser.END_TAG 9603 || parser.getDepth() > outerDepth)) { 9604 if (type == XmlPullParser.END_TAG 9605 || type == XmlPullParser.TEXT) { 9606 continue; 9607 } 9608 9609 String tagName = parser.getName(); 9610 if (tagName.equals("item")) { 9611 String name = parser.getAttributeValue(null, "name"); 9612 if (name != null) { 9613 outPerms.add(name.intern()); 9614 } else { 9615 reportSettingsProblem(Log.WARN, 9616 "Error in package manager settings: <perms> has" 9617 + " no name at " + parser.getPositionDescription()); 9618 } 9619 } else { 9620 reportSettingsProblem(Log.WARN, 9621 "Unknown element under <perms>: " 9622 + parser.getName()); 9623 } 9624 XmlUtils.skipCurrentTag(parser); 9625 } 9626 } 9627 9628 private void readPreferredActivitiesLP(XmlPullParser parser) 9629 throws XmlPullParserException, IOException { 9630 int outerDepth = parser.getDepth(); 9631 int type; 9632 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 9633 && (type != XmlPullParser.END_TAG 9634 || parser.getDepth() > outerDepth)) { 9635 if (type == XmlPullParser.END_TAG 9636 || type == XmlPullParser.TEXT) { 9637 continue; 9638 } 9639 9640 String tagName = parser.getName(); 9641 if (tagName.equals("item")) { 9642 PreferredActivity pa = new PreferredActivity(parser); 9643 if (pa.mParseError == null) { 9644 mPreferredActivities.addFilter(pa); 9645 } else { 9646 reportSettingsProblem(Log.WARN, 9647 "Error in package manager settings: <preferred-activity> " 9648 + pa.mParseError + " at " 9649 + parser.getPositionDescription()); 9650 } 9651 } else { 9652 reportSettingsProblem(Log.WARN, 9653 "Unknown element under <preferred-activities>: " 9654 + parser.getName()); 9655 XmlUtils.skipCurrentTag(parser); 9656 } 9657 } 9658 } 9659 9660 // Returns -1 if we could not find an available UserId to assign 9661 private int newUserIdLP(Object obj) { 9662 // Let's be stupidly inefficient for now... 9663 final int N = mUserIds.size(); 9664 for (int i=0; i<N; i++) { 9665 if (mUserIds.get(i) == null) { 9666 mUserIds.set(i, obj); 9667 return FIRST_APPLICATION_UID + i; 9668 } 9669 } 9670 9671 // None left? 9672 if (N >= MAX_APPLICATION_UIDS) { 9673 return -1; 9674 } 9675 9676 mUserIds.add(obj); 9677 return FIRST_APPLICATION_UID + N; 9678 } 9679 9680 public PackageSetting getDisabledSystemPkg(String name) { 9681 synchronized(mPackages) { 9682 PackageSetting ps = mDisabledSysPackages.get(name); 9683 return ps; 9684 } 9685 } 9686 9687 boolean isEnabledLP(ComponentInfo componentInfo, int flags) { 9688 if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { 9689 return true; 9690 } 9691 final PackageSetting packageSettings = mPackages.get(componentInfo.packageName); 9692 if (Config.LOGV) { 9693 Log.v(TAG, "isEnabledLock - packageName = " + componentInfo.packageName 9694 + " componentName = " + componentInfo.name); 9695 Log.v(TAG, "enabledComponents: " 9696 + Arrays.toString(packageSettings.enabledComponents.toArray())); 9697 Log.v(TAG, "disabledComponents: " 9698 + Arrays.toString(packageSettings.disabledComponents.toArray())); 9699 } 9700 if (packageSettings == null) { 9701 if (false) { 9702 Log.w(TAG, "WAITING FOR DEBUGGER"); 9703 Debug.waitForDebugger(); 9704 Log.i(TAG, "We will crash!"); 9705 } 9706 return false; 9707 } 9708 if (packageSettings.enabled == COMPONENT_ENABLED_STATE_DISABLED 9709 || (packageSettings.pkg != null && !packageSettings.pkg.applicationInfo.enabled 9710 && packageSettings.enabled == COMPONENT_ENABLED_STATE_DEFAULT)) { 9711 return false; 9712 } 9713 if (packageSettings.enabledComponents.contains(componentInfo.name)) { 9714 return true; 9715 } 9716 if (packageSettings.disabledComponents.contains(componentInfo.name)) { 9717 return false; 9718 } 9719 return componentInfo.enabled; 9720 } 9721 } 9722 9723 // ------- apps on sdcard specific code ------- 9724 static final boolean DEBUG_SD_INSTALL = false; 9725 private static final String SD_ENCRYPTION_KEYSTORE_NAME = "AppsOnSD"; 9726 private static final String SD_ENCRYPTION_ALGORITHM = "AES"; 9727 static final int MAX_CONTAINERS = 250; 9728 private boolean mMediaMounted = false; 9729 9730 private String getEncryptKey() { 9731 try { 9732 String sdEncKey = SystemKeyStore.getInstance().retrieveKeyHexString( 9733 SD_ENCRYPTION_KEYSTORE_NAME); 9734 if (sdEncKey == null) { 9735 sdEncKey = SystemKeyStore.getInstance().generateNewKeyHexString(128, 9736 SD_ENCRYPTION_ALGORITHM, SD_ENCRYPTION_KEYSTORE_NAME); 9737 if (sdEncKey == null) { 9738 Slog.e(TAG, "Failed to create encryption keys"); 9739 return null; 9740 } 9741 } 9742 return sdEncKey; 9743 } catch (NoSuchAlgorithmException nsae) { 9744 Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae); 9745 return null; 9746 } catch (IOException ioe) { 9747 Slog.e(TAG, "Failed to retrieve encryption keys with exception: " 9748 + ioe); 9749 return null; 9750 } 9751 9752 } 9753 9754 /* package */ static String getTempContainerId() { 9755 int tmpIdx = 1; 9756 String list[] = PackageHelper.getSecureContainerList(); 9757 if (list != null) { 9758 for (final String name : list) { 9759 // Ignore null and non-temporary container entries 9760 if (name == null || !name.startsWith(mTempContainerPrefix)) { 9761 continue; 9762 } 9763 9764 String subStr = name.substring(mTempContainerPrefix.length()); 9765 try { 9766 int cid = Integer.parseInt(subStr); 9767 if (cid >= tmpIdx) { 9768 tmpIdx = cid + 1; 9769 } 9770 } catch (NumberFormatException e) { 9771 } 9772 } 9773 } 9774 return mTempContainerPrefix + tmpIdx; 9775 } 9776 9777 /* 9778 * Update media status on PackageManager. 9779 */ 9780 public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) { 9781 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 9782 throw new SecurityException("Media status can only be updated by the system"); 9783 } 9784 synchronized (mPackages) { 9785 Log.i(TAG, "Updating external media status from " + 9786 (mMediaMounted ? "mounted" : "unmounted") + " to " + 9787 (mediaStatus ? "mounted" : "unmounted")); 9788 if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" + 9789 mediaStatus+", mMediaMounted=" + mMediaMounted); 9790 if (mediaStatus == mMediaMounted) { 9791 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, 9792 reportStatus ? 1 : 0, -1); 9793 mHandler.sendMessage(msg); 9794 return; 9795 } 9796 mMediaMounted = mediaStatus; 9797 } 9798 // Queue up an async operation since the package installation may take a little while. 9799 mHandler.post(new Runnable() { 9800 public void run() { 9801 mHandler.removeCallbacks(this); 9802 updateExternalMediaStatusInner(mediaStatus, reportStatus); 9803 } 9804 }); 9805 } 9806 9807 /* 9808 * Collect information of applications on external media, map them 9809 * against existing containers and update information based on current 9810 * mount status. Please note that we always have to report status 9811 * if reportStatus has been set to true especially when unloading packages. 9812 */ 9813 private void updateExternalMediaStatusInner(boolean mediaStatus, 9814 boolean reportStatus) { 9815 // Collection of uids 9816 int uidArr[] = null; 9817 // Collection of stale containers 9818 HashSet<String> removeCids = new HashSet<String>(); 9819 // Collection of packages on external media with valid containers. 9820 HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>(); 9821 // Get list of secure containers. 9822 final String list[] = PackageHelper.getSecureContainerList(); 9823 if (list == null || list.length == 0) { 9824 Log.i(TAG, "No secure containers on sdcard"); 9825 } else { 9826 // Process list of secure containers and categorize them 9827 // as active or stale based on their package internal state. 9828 int uidList[] = new int[list.length]; 9829 int num = 0; 9830 synchronized (mPackages) { 9831 for (String cid : list) { 9832 SdInstallArgs args = new SdInstallArgs(cid); 9833 if (DEBUG_SD_INSTALL) Log.i(TAG, "Processing container " + cid); 9834 String pkgName = args.getPackageName(); 9835 if (pkgName == null) { 9836 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale"); 9837 removeCids.add(cid); 9838 continue; 9839 } 9840 if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName); 9841 PackageSetting ps = mSettings.mPackages.get(pkgName); 9842 // The package status is changed only if the code path 9843 // matches between settings and the container id. 9844 if (ps != null && ps.codePathString != null && 9845 ps.codePathString.equals(args.getCodePath())) { 9846 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + 9847 " corresponds to pkg : " + pkgName + 9848 " at code path: " + ps.codePathString); 9849 // We do have a valid package installed on sdcard 9850 processCids.put(args, ps.codePathString); 9851 int uid = ps.userId; 9852 if (uid != -1) { 9853 uidList[num++] = uid; 9854 } 9855 } else { 9856 // Stale container on sdcard. Just delete 9857 if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid + " stale"); 9858 removeCids.add(cid); 9859 } 9860 } 9861 } 9862 9863 if (num > 0) { 9864 // Sort uid list 9865 Arrays.sort(uidList, 0, num); 9866 // Throw away duplicates 9867 uidArr = new int[num]; 9868 uidArr[0] = uidList[0]; 9869 int di = 0; 9870 for (int i = 1; i < num; i++) { 9871 if (uidList[i-1] != uidList[i]) { 9872 uidArr[di++] = uidList[i]; 9873 } 9874 } 9875 } 9876 } 9877 // Process packages with valid entries. 9878 if (mediaStatus) { 9879 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); 9880 loadMediaPackages(processCids, uidArr, removeCids); 9881 startCleaningPackages(); 9882 } else { 9883 if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading packages"); 9884 unloadMediaPackages(processCids, uidArr, reportStatus); 9885 } 9886 } 9887 9888 private void sendResourcesChangedBroadcast(boolean mediaStatus, 9889 ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) { 9890 int size = pkgList.size(); 9891 if (size > 0) { 9892 // Send broadcasts here 9893 Bundle extras = new Bundle(); 9894 extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, 9895 pkgList.toArray(new String[size])); 9896 if (uidArr != null) { 9897 extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr); 9898 } 9899 String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 9900 : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE; 9901 sendPackageBroadcast(action, null, extras, finishedReceiver); 9902 } 9903 } 9904 9905 /* 9906 * Look at potentially valid container ids from processCids 9907 * If package information doesn't match the one on record 9908 * or package scanning fails, the cid is added to list of 9909 * removeCids. We currently don't delete stale containers. 9910 */ 9911 private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, 9912 int uidArr[], HashSet<String> removeCids) { 9913 ArrayList<String> pkgList = new ArrayList<String>(); 9914 Set<SdInstallArgs> keys = processCids.keySet(); 9915 boolean doGc = false; 9916 for (SdInstallArgs args : keys) { 9917 String codePath = processCids.get(args); 9918 if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading container : " 9919 + args.cid); 9920 int retCode = PackageManager.INSTALL_FAILED_CONTAINER_ERROR; 9921 try { 9922 // Make sure there are no container errors first. 9923 if (args.doPreInstall(PackageManager.INSTALL_SUCCEEDED) 9924 != PackageManager.INSTALL_SUCCEEDED) { 9925 Slog.e(TAG, "Failed to mount cid : " + args.cid + 9926 " when installing from sdcard"); 9927 continue; 9928 } 9929 // Check code path here. 9930 if (codePath == null || !codePath.equals(args.getCodePath())) { 9931 Slog.e(TAG, "Container " + args.cid + " cachepath " + args.getCodePath()+ 9932 " does not match one in settings " + codePath); 9933 continue; 9934 } 9935 // Parse package 9936 int parseFlags = PackageParser.PARSE_ON_SDCARD | mDefParseFlags; 9937 doGc = true; 9938 synchronized (mInstallLock) { 9939 final PackageParser.Package pkg = scanPackageLI(new File(codePath), 9940 parseFlags, 0, 0); 9941 // Scan the package 9942 if (pkg != null) { 9943 synchronized (mPackages) { 9944 retCode = PackageManager.INSTALL_SUCCEEDED; 9945 pkgList.add(pkg.packageName); 9946 // Post process args 9947 args.doPostInstall(PackageManager.INSTALL_SUCCEEDED); 9948 } 9949 } else { 9950 Slog.i(TAG, "Failed to install pkg from " + 9951 codePath + " from sdcard"); 9952 } 9953 } 9954 9955 } finally { 9956 if (retCode != PackageManager.INSTALL_SUCCEEDED) { 9957 // Don't destroy container here. Wait till gc clears things up. 9958 removeCids.add(args.cid); 9959 } 9960 } 9961 } 9962 synchronized (mPackages) { 9963 // If the platform SDK has changed since the last time we booted, 9964 // we need to re-grant app permission to catch any new ones that 9965 // appear. This is really a hack, and means that apps can in some 9966 // cases get permissions that the user didn't initially explicitly 9967 // allow... it would be nice to have some better way to handle 9968 // this situation. 9969 final boolean regrantPermissions = mSettings.mExternalSdkPlatform 9970 != mSdkVersion; 9971 if (regrantPermissions) Slog.i(TAG, "Platform changed from " 9972 + mSettings.mExternalSdkPlatform + " to " + mSdkVersion 9973 + "; regranting permissions for external storage"); 9974 mSettings.mExternalSdkPlatform = mSdkVersion; 9975 9976 // Make sure group IDs have been assigned, and any permission 9977 // changes in other apps are accounted for 9978 updatePermissionsLP(null, null, true, regrantPermissions, regrantPermissions); 9979 // Persist settings 9980 mSettings.writeLP(); 9981 } 9982 // Send a broadcast to let everyone know we are done processing 9983 if (pkgList.size() > 0) { 9984 sendResourcesChangedBroadcast(true, pkgList, uidArr, null); 9985 } 9986 // Force gc to avoid any stale parser references that we might have. 9987 if (doGc) { 9988 Runtime.getRuntime().gc(); 9989 } 9990 // List stale containers and destroy stale temporary containers. 9991 if (removeCids != null) { 9992 for (String cid : removeCids) { 9993 if (cid.startsWith(mTempContainerPrefix)) { 9994 Log.i(TAG, "Destroying stale temporary container " + cid); 9995 PackageHelper.destroySdDir(cid); 9996 } else { 9997 Log.w(TAG, "Container " + cid + " is stale"); 9998 } 9999 } 10000 } 10001 } 10002 10003 /* 10004 * Utility method to unload a list of specified containers 10005 */ 10006 private void unloadAllContainers(Set<SdInstallArgs> cidArgs) { 10007 // Just unmount all valid containers. 10008 for (SdInstallArgs arg : cidArgs) { 10009 synchronized (mInstallLock) { 10010 arg.doPostDeleteLI(false); 10011 } 10012 } 10013 } 10014 10015 /* 10016 * Unload packages mounted on external media. This involves deleting 10017 * package data from internal structures, sending broadcasts about 10018 * diabled packages, gc'ing to free up references, unmounting all 10019 * secure containers corresponding to packages on external media, and 10020 * posting a UPDATED_MEDIA_STATUS message if status has been requested. 10021 * Please note that we always have to post this message if status has 10022 * been requested no matter what. 10023 */ 10024 private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, 10025 int uidArr[], final boolean reportStatus) { 10026 if (DEBUG_SD_INSTALL) Log.i(TAG, "unloading media packages"); 10027 ArrayList<String> pkgList = new ArrayList<String>(); 10028 ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>(); 10029 final Set<SdInstallArgs> keys = processCids.keySet(); 10030 for (SdInstallArgs args : keys) { 10031 String cid = args.cid; 10032 String pkgName = args.getPackageName(); 10033 if (DEBUG_SD_INSTALL) Log.i(TAG, "Trying to unload pkg : " + pkgName); 10034 // Delete package internally 10035 PackageRemovedInfo outInfo = new PackageRemovedInfo(); 10036 synchronized (mInstallLock) { 10037 boolean res = deletePackageLI(pkgName, false, 10038 PackageManager.DONT_DELETE_DATA, outInfo, false); 10039 if (res) { 10040 pkgList.add(pkgName); 10041 } else { 10042 Slog.e(TAG, "Failed to delete pkg from sdcard : " + pkgName); 10043 failedList.add(args); 10044 } 10045 } 10046 } 10047 10048 synchronized (mPackages) { 10049 // We didn't update the settings after removing each package; 10050 // write them now for all packages. 10051 mSettings.writeLP(); 10052 } 10053 10054 // We have to absolutely send UPDATED_MEDIA_STATUS only 10055 // after confirming that all the receivers processed the ordered 10056 // broadcast when packages get disabled, force a gc to clean things up. 10057 // and unload all the containers. 10058 if (pkgList.size() > 0) { 10059 sendResourcesChangedBroadcast(false, pkgList, uidArr, new IIntentReceiver.Stub() { 10060 public void performReceive(Intent intent, int resultCode, String data, Bundle extras, 10061 boolean ordered, boolean sticky) throws RemoteException { 10062 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, 10063 reportStatus ? 1 : 0, 1, keys); 10064 mHandler.sendMessage(msg); 10065 } 10066 }); 10067 } else { 10068 Message msg = mHandler.obtainMessage(UPDATED_MEDIA_STATUS, 10069 reportStatus ? 1 : 0, -1, keys); 10070 mHandler.sendMessage(msg); 10071 } 10072 } 10073 10074 public void movePackage(final String packageName, 10075 final IPackageMoveObserver observer, final int flags) { 10076 mContext.enforceCallingOrSelfPermission( 10077 android.Manifest.permission.MOVE_PACKAGE, null); 10078 int returnCode = PackageManager.MOVE_SUCCEEDED; 10079 int currFlags = 0; 10080 int newFlags = 0; 10081 synchronized (mPackages) { 10082 PackageParser.Package pkg = mPackages.get(packageName); 10083 if (pkg == null) { 10084 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; 10085 } else { 10086 // Disable moving fwd locked apps and system packages 10087 if (pkg.applicationInfo != null && isSystemApp(pkg)) { 10088 Slog.w(TAG, "Cannot move system application"); 10089 returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE; 10090 } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) { 10091 Slog.w(TAG, "Cannot move forward locked app."); 10092 returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED; 10093 } else if (pkg.mOperationPending) { 10094 Slog.w(TAG, "Attempt to move package which has pending operations"); 10095 returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING; 10096 } else { 10097 // Find install location first 10098 if ((flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 && 10099 (flags & PackageManager.MOVE_INTERNAL) != 0) { 10100 Slog.w(TAG, "Ambigous flags specified for move location."); 10101 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; 10102 } else { 10103 newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ? 10104 PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL; 10105 currFlags = isExternal(pkg) ? PackageManager.INSTALL_EXTERNAL 10106 : PackageManager.INSTALL_INTERNAL; 10107 if (newFlags == currFlags) { 10108 Slog.w(TAG, "No move required. Trying to move to same location"); 10109 returnCode = PackageManager.MOVE_FAILED_INVALID_LOCATION; 10110 } 10111 } 10112 if (returnCode == PackageManager.MOVE_SUCCEEDED) { 10113 pkg.mOperationPending = true; 10114 } 10115 } 10116 } 10117 if (returnCode != PackageManager.MOVE_SUCCEEDED) { 10118 processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode); 10119 } else { 10120 Message msg = mHandler.obtainMessage(INIT_COPY); 10121 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir, 10122 pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir); 10123 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName, 10124 pkg.applicationInfo.dataDir); 10125 msg.obj = mp; 10126 mHandler.sendMessage(msg); 10127 } 10128 } 10129 } 10130 10131 private void processPendingMove(final MoveParams mp, final int currentStatus) { 10132 // Queue up an async operation since the package deletion may take a little while. 10133 mHandler.post(new Runnable() { 10134 public void run() { 10135 mHandler.removeCallbacks(this); 10136 int returnCode = currentStatus; 10137 if (currentStatus == PackageManager.MOVE_SUCCEEDED) { 10138 int uidArr[] = null; 10139 ArrayList<String> pkgList = null; 10140 synchronized (mPackages) { 10141 PackageParser.Package pkg = mPackages.get(mp.packageName); 10142 if (pkg == null) { 10143 Slog.w(TAG, " Package " + mp.packageName + 10144 " doesn't exist. Aborting move"); 10145 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; 10146 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) { 10147 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " + 10148 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir + 10149 " Aborting move and returning error"); 10150 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; 10151 } else { 10152 uidArr = new int[] { pkg.applicationInfo.uid }; 10153 pkgList = new ArrayList<String>(); 10154 pkgList.add(mp.packageName); 10155 } 10156 } 10157 if (returnCode == PackageManager.MOVE_SUCCEEDED) { 10158 // Send resources unavailable broadcast 10159 sendResourcesChangedBroadcast(false, pkgList, uidArr, null); 10160 // Update package code and resource paths 10161 synchronized (mInstallLock) { 10162 synchronized (mPackages) { 10163 PackageParser.Package pkg = mPackages.get(mp.packageName); 10164 // Recheck for package again. 10165 if (pkg == null) { 10166 Slog.w(TAG, " Package " + mp.packageName 10167 + " doesn't exist. Aborting move"); 10168 returnCode = PackageManager.MOVE_FAILED_DOESNT_EXIST; 10169 } else if (!mp.srcArgs.getCodePath().equals(pkg.applicationInfo.sourceDir)) { 10170 Slog.w(TAG, "Package " + mp.packageName + " code path changed from " + 10171 mp.srcArgs.getCodePath() + " to " + pkg.applicationInfo.sourceDir + 10172 " Aborting move and returning error"); 10173 returnCode = PackageManager.MOVE_FAILED_INTERNAL_ERROR; 10174 } else { 10175 final String oldCodePath = pkg.mPath; 10176 final String newCodePath = mp.targetArgs.getCodePath(); 10177 final String newResPath = mp.targetArgs.getResourcePath(); 10178 final String newNativePath = mp.targetArgs.getNativeLibraryPath(); 10179 10180 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) == 0) { 10181 if (mInstaller 10182 .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { 10183 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; 10184 } else { 10185 NativeLibraryHelper.copyNativeBinariesLI( 10186 new File(newCodePath), new File(newNativePath)); 10187 } 10188 } else { 10189 if (mInstaller.linkNativeLibraryDirectory( 10190 pkg.applicationInfo.dataDir, newNativePath) < 0) { 10191 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; 10192 } 10193 } 10194 10195 if (returnCode == PackageManager.MOVE_SUCCEEDED) { 10196 pkg.mPath = newCodePath; 10197 // Move dex files around 10198 if (moveDexFilesLI(pkg) != PackageManager.INSTALL_SUCCEEDED) { 10199 // Moving of dex files failed. Set 10200 // error code and abort move. 10201 pkg.mPath = pkg.mScanPath; 10202 returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; 10203 } 10204 } 10205 10206 if (returnCode == PackageManager.MOVE_SUCCEEDED) { 10207 pkg.mScanPath = newCodePath; 10208 pkg.applicationInfo.sourceDir = newCodePath; 10209 pkg.applicationInfo.publicSourceDir = newResPath; 10210 pkg.applicationInfo.nativeLibraryDir = newNativePath; 10211 PackageSetting ps = (PackageSetting) pkg.mExtras; 10212 ps.codePath = new File(pkg.applicationInfo.sourceDir); 10213 ps.codePathString = ps.codePath.getPath(); 10214 ps.resourcePath = new File(pkg.applicationInfo.publicSourceDir); 10215 ps.resourcePathString = ps.resourcePath.getPath(); 10216 ps.nativeLibraryPathString = newNativePath; 10217 // Set the application info flag correctly. 10218 if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) { 10219 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; 10220 } else { 10221 pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE; 10222 } 10223 ps.setFlags(pkg.applicationInfo.flags); 10224 mAppDirs.remove(oldCodePath); 10225 mAppDirs.put(newCodePath, pkg); 10226 // Persist settings 10227 mSettings.writeLP(); 10228 } 10229 } 10230 } 10231 } 10232 // Send resources available broadcast 10233 sendResourcesChangedBroadcast(true, pkgList, uidArr, null); 10234 } 10235 } 10236 if (returnCode != PackageManager.MOVE_SUCCEEDED){ 10237 // Clean up failed installation 10238 if (mp.targetArgs != null) { 10239 mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR); 10240 } 10241 } else { 10242 // Force a gc to clear things up. 10243 Runtime.getRuntime().gc(); 10244 // Delete older code 10245 synchronized (mInstallLock) { 10246 mp.srcArgs.doPostDeleteLI(true); 10247 } 10248 } 10249 10250 // Allow more operations on this file if we didn't fail because 10251 // an operation was already pending for this package. 10252 if (returnCode != PackageManager.MOVE_FAILED_OPERATION_PENDING) { 10253 synchronized (mPackages) { 10254 PackageParser.Package pkg = mPackages.get(mp.packageName); 10255 if (pkg != null) { 10256 pkg.mOperationPending = false; 10257 } 10258 } 10259 } 10260 10261 IPackageMoveObserver observer = mp.observer; 10262 if (observer != null) { 10263 try { 10264 observer.packageMoved(mp.packageName, returnCode); 10265 } catch (RemoteException e) { 10266 Log.i(TAG, "Observer no longer exists."); 10267 } 10268 } 10269 } 10270 }); 10271 } 10272 10273 public boolean setInstallLocation(int loc) { 10274 mContext.enforceCallingOrSelfPermission( 10275 android.Manifest.permission.WRITE_SECURE_SETTINGS, null); 10276 if (getInstallLocation() == loc) { 10277 return true; 10278 } 10279 if (loc == PackageHelper.APP_INSTALL_AUTO || 10280 loc == PackageHelper.APP_INSTALL_INTERNAL || 10281 loc == PackageHelper.APP_INSTALL_EXTERNAL) { 10282 android.provider.Settings.System.putInt(mContext.getContentResolver(), 10283 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, loc); 10284 return true; 10285 } 10286 return false; 10287 } 10288 10289 public int getInstallLocation() { 10290 return android.provider.Settings.System.getInt(mContext.getContentResolver(), 10291 android.provider.Settings.Secure.DEFAULT_INSTALL_LOCATION, PackageHelper.APP_INSTALL_AUTO); 10292 } 10293 } 10294