ContextImpl.java revision 1d0d1188d71ed086b3910cfe1d244fdeee47f182
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 17package android.app; 18 19import com.android.internal.policy.PolicyManager; 20import com.android.internal.util.XmlUtils; 21import com.google.android.collect.Maps; 22 23import org.xmlpull.v1.XmlPullParserException; 24 25import android.content.BroadcastReceiver; 26import android.content.ComponentName; 27import android.content.ContentResolver; 28import android.content.Context; 29import android.content.ContextWrapper; 30import android.content.IContentProvider; 31import android.content.Intent; 32import android.content.IntentFilter; 33import android.content.IIntentReceiver; 34import android.content.IntentSender; 35import android.content.ReceiverCallNotAllowedException; 36import android.content.ServiceConnection; 37import android.content.SharedPreferences; 38import android.content.pm.ActivityInfo; 39import android.content.pm.ApplicationInfo; 40import android.content.pm.ComponentInfo; 41import android.content.pm.FeatureInfo; 42import android.content.pm.IPackageDataObserver; 43import android.content.pm.IPackageDeleteObserver; 44import android.content.pm.IPackageInstallObserver; 45import android.content.pm.IPackageMoveObserver; 46import android.content.pm.IPackageManager; 47import android.content.pm.IPackageStatsObserver; 48import android.content.pm.InstrumentationInfo; 49import android.content.pm.PackageInfo; 50import android.content.pm.PackageManager; 51import android.content.pm.PermissionGroupInfo; 52import android.content.pm.PermissionInfo; 53import android.content.pm.ProviderInfo; 54import android.content.pm.ResolveInfo; 55import android.content.pm.ServiceInfo; 56import android.content.res.AssetManager; 57import android.content.res.Resources; 58import android.content.res.XmlResourceParser; 59import android.database.sqlite.SQLiteDatabase; 60import android.database.sqlite.SQLiteDatabase.CursorFactory; 61import android.graphics.Bitmap; 62import android.graphics.drawable.Drawable; 63import android.hardware.SensorManager; 64import android.location.ILocationManager; 65import android.location.LocationManager; 66import android.media.AudioManager; 67import android.net.ConnectivityManager; 68import android.net.IConnectivityManager; 69import android.net.ThrottleManager; 70import android.net.IThrottleManager; 71import android.net.Uri; 72import android.net.wifi.IWifiManager; 73import android.net.wifi.WifiManager; 74import android.nfc.NfcManager; 75import android.os.Binder; 76import android.os.Bundle; 77import android.os.DropBoxManager; 78import android.os.Environment; 79import android.os.FileUtils; 80import android.os.Handler; 81import android.os.IBinder; 82import android.os.IPowerManager; 83import android.os.Looper; 84import android.os.PowerManager; 85import android.os.Process; 86import android.os.RemoteException; 87import android.os.ServiceManager; 88import android.os.Vibrator; 89import android.os.FileUtils.FileStatus; 90import android.os.storage.StorageManager; 91import android.telephony.TelephonyManager; 92import android.text.ClipboardManager; 93import android.util.AndroidRuntimeException; 94import android.util.Log; 95import android.view.ContextThemeWrapper; 96import android.view.LayoutInflater; 97import android.view.WindowManagerImpl; 98import android.view.accessibility.AccessibilityManager; 99import android.view.inputmethod.InputMethodManager; 100import android.accounts.AccountManager; 101import android.accounts.IAccountManager; 102import android.app.admin.DevicePolicyManager; 103import com.android.internal.os.IDropBoxManagerService; 104 105import java.io.File; 106import java.io.FileInputStream; 107import java.io.FileNotFoundException; 108import java.io.FileOutputStream; 109import java.io.IOException; 110import java.io.InputStream; 111import java.lang.ref.WeakReference; 112import java.util.ArrayList; 113import java.util.HashMap; 114import java.util.HashSet; 115import java.util.Iterator; 116import java.util.List; 117import java.util.Map; 118import java.util.Map.Entry; 119import java.util.Set; 120import java.util.WeakHashMap; 121import java.util.concurrent.CountDownLatch; 122import java.util.concurrent.ExecutorService; 123 124class ReceiverRestrictedContext extends ContextWrapper { 125 ReceiverRestrictedContext(Context base) { 126 super(base); 127 } 128 129 @Override 130 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 131 return registerReceiver(receiver, filter, null, null); 132 } 133 134 @Override 135 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 136 String broadcastPermission, Handler scheduler) { 137 throw new ReceiverCallNotAllowedException( 138 "IntentReceiver components are not allowed to register to receive intents"); 139 //ex.fillInStackTrace(); 140 //Log.e("IntentReceiver", ex.getMessage(), ex); 141 //return mContext.registerReceiver(receiver, filter, broadcastPermission, 142 // scheduler); 143 } 144 145 @Override 146 public boolean bindService(Intent service, ServiceConnection conn, int flags) { 147 throw new ReceiverCallNotAllowedException( 148 "IntentReceiver components are not allowed to bind to services"); 149 //ex.fillInStackTrace(); 150 //Log.e("IntentReceiver", ex.getMessage(), ex); 151 //return mContext.bindService(service, interfaceName, conn, flags); 152 } 153} 154 155/** 156 * Common implementation of Context API, which provides the base 157 * context object for Activity and other application components. 158 */ 159class ContextImpl extends Context { 160 private final static String TAG = "ApplicationContext"; 161 private final static boolean DEBUG = false; 162 private final static boolean DEBUG_ICONS = false; 163 164 private static final Object sSync = new Object(); 165 private static AlarmManager sAlarmManager; 166 private static PowerManager sPowerManager; 167 private static ConnectivityManager sConnectivityManager; 168 private static ThrottleManager sThrottleManager; 169 private static WifiManager sWifiManager; 170 private static LocationManager sLocationManager; 171 private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs = 172 new HashMap<String, SharedPreferencesImpl>(); 173 174 private AudioManager mAudioManager; 175 /*package*/ LoadedApk mPackageInfo; 176 private Resources mResources; 177 /*package*/ ActivityThread mMainThread; 178 private Context mOuterContext; 179 private IBinder mActivityToken = null; 180 private ApplicationContentResolver mContentResolver; 181 private int mThemeResource = 0; 182 private Resources.Theme mTheme = null; 183 private PackageManager mPackageManager; 184 private NotificationManager mNotificationManager = null; 185 private ActivityManager mActivityManager = null; 186 private WallpaperManager mWallpaperManager = null; 187 private Context mReceiverRestrictedContext = null; 188 private SearchManager mSearchManager = null; 189 private SensorManager mSensorManager = null; 190 private StorageManager mStorageManager = null; 191 private Vibrator mVibrator = null; 192 private LayoutInflater mLayoutInflater = null; 193 private StatusBarManager mStatusBarManager = null; 194 private TelephonyManager mTelephonyManager = null; 195 private ClipboardManager mClipboardManager = null; 196 private boolean mRestricted; 197 private AccountManager mAccountManager; // protected by mSync 198 private DropBoxManager mDropBoxManager = null; 199 private DevicePolicyManager mDevicePolicyManager = null; 200 private UiModeManager mUiModeManager = null; 201 private DownloadManager mDownloadManager = null; 202 private NfcManager mNfcManager = null; 203 204 private final Object mSync = new Object(); 205 206 private File mDatabasesDir; 207 private File mPreferencesDir; 208 private File mFilesDir; 209 private File mCacheDir; 210 private File mExternalFilesDir; 211 private File mExternalCacheDir; 212 213 private static long sInstanceCount = 0; 214 215 private static final String[] EMPTY_FILE_LIST = {}; 216 217 // For debug only 218 /* 219 @Override 220 protected void finalize() throws Throwable { 221 super.finalize(); 222 --sInstanceCount; 223 } 224 */ 225 226 public static long getInstanceCount() { 227 return sInstanceCount; 228 } 229 230 @Override 231 public AssetManager getAssets() { 232 return mResources.getAssets(); 233 } 234 235 @Override 236 public Resources getResources() { 237 return mResources; 238 } 239 240 @Override 241 public PackageManager getPackageManager() { 242 if (mPackageManager != null) { 243 return mPackageManager; 244 } 245 246 IPackageManager pm = ActivityThread.getPackageManager(); 247 if (pm != null) { 248 // Doesn't matter if we make more than one instance. 249 return (mPackageManager = new ApplicationPackageManager(this, pm)); 250 } 251 252 return null; 253 } 254 255 @Override 256 public ContentResolver getContentResolver() { 257 return mContentResolver; 258 } 259 260 @Override 261 public Looper getMainLooper() { 262 return mMainThread.getLooper(); 263 } 264 265 @Override 266 public Context getApplicationContext() { 267 return (mPackageInfo != null) ? 268 mPackageInfo.getApplication() : mMainThread.getApplication(); 269 } 270 271 @Override 272 public void setTheme(int resid) { 273 mThemeResource = resid; 274 } 275 276 @Override 277 public Resources.Theme getTheme() { 278 if (mTheme == null) { 279 if (mThemeResource == 0) { 280 mThemeResource = com.android.internal.R.style.Theme; 281 } 282 mTheme = mResources.newTheme(); 283 mTheme.applyStyle(mThemeResource, true); 284 } 285 return mTheme; 286 } 287 288 @Override 289 public ClassLoader getClassLoader() { 290 return mPackageInfo != null ? 291 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader(); 292 } 293 294 @Override 295 public String getPackageName() { 296 if (mPackageInfo != null) { 297 return mPackageInfo.getPackageName(); 298 } 299 throw new RuntimeException("Not supported in system context"); 300 } 301 302 @Override 303 public ApplicationInfo getApplicationInfo() { 304 if (mPackageInfo != null) { 305 return mPackageInfo.getApplicationInfo(); 306 } 307 throw new RuntimeException("Not supported in system context"); 308 } 309 310 @Override 311 public String getPackageResourcePath() { 312 if (mPackageInfo != null) { 313 return mPackageInfo.getResDir(); 314 } 315 throw new RuntimeException("Not supported in system context"); 316 } 317 318 @Override 319 public String getPackageCodePath() { 320 if (mPackageInfo != null) { 321 return mPackageInfo.getAppDir(); 322 } 323 throw new RuntimeException("Not supported in system context"); 324 } 325 326 private static File makeBackupFile(File prefsFile) { 327 return new File(prefsFile.getPath() + ".bak"); 328 } 329 330 public File getSharedPrefsFile(String name) { 331 return makeFilename(getPreferencesDir(), name + ".xml"); 332 } 333 334 @Override 335 public SharedPreferences getSharedPreferences(String name, int mode) { 336 SharedPreferencesImpl sp; 337 File prefsFile; 338 boolean needInitialLoad = false; 339 synchronized (sSharedPrefs) { 340 sp = sSharedPrefs.get(name); 341 if (sp != null && !sp.hasFileChangedUnexpectedly()) { 342 return sp; 343 } 344 prefsFile = getSharedPrefsFile(name); 345 if (sp == null) { 346 sp = new SharedPreferencesImpl(prefsFile, mode, null); 347 sSharedPrefs.put(name, sp); 348 needInitialLoad = true; 349 } 350 } 351 352 synchronized (sp) { 353 if (needInitialLoad && sp.isLoaded()) { 354 // lost the race to load; another thread handled it 355 return sp; 356 } 357 File backup = makeBackupFile(prefsFile); 358 if (backup.exists()) { 359 prefsFile.delete(); 360 backup.renameTo(prefsFile); 361 } 362 363 // Debugging 364 if (prefsFile.exists() && !prefsFile.canRead()) { 365 Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission"); 366 } 367 368 Map map = null; 369 FileStatus stat = new FileStatus(); 370 if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) { 371 try { 372 FileInputStream str = new FileInputStream(prefsFile); 373 map = XmlUtils.readMapXml(str); 374 str.close(); 375 } catch (org.xmlpull.v1.XmlPullParserException e) { 376 Log.w(TAG, "getSharedPreferences", e); 377 } catch (FileNotFoundException e) { 378 Log.w(TAG, "getSharedPreferences", e); 379 } catch (IOException e) { 380 Log.w(TAG, "getSharedPreferences", e); 381 } 382 } 383 sp.replace(map, stat); 384 } 385 return sp; 386 } 387 388 private File getPreferencesDir() { 389 synchronized (mSync) { 390 if (mPreferencesDir == null) { 391 mPreferencesDir = new File(getDataDirFile(), "shared_prefs"); 392 } 393 return mPreferencesDir; 394 } 395 } 396 397 @Override 398 public FileInputStream openFileInput(String name) 399 throws FileNotFoundException { 400 File f = makeFilename(getFilesDir(), name); 401 return new FileInputStream(f); 402 } 403 404 @Override 405 public FileOutputStream openFileOutput(String name, int mode) 406 throws FileNotFoundException { 407 final boolean append = (mode&MODE_APPEND) != 0; 408 File f = makeFilename(getFilesDir(), name); 409 try { 410 FileOutputStream fos = new FileOutputStream(f, append); 411 setFilePermissionsFromMode(f.getPath(), mode, 0); 412 return fos; 413 } catch (FileNotFoundException e) { 414 } 415 416 File parent = f.getParentFile(); 417 parent.mkdir(); 418 FileUtils.setPermissions( 419 parent.getPath(), 420 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 421 -1, -1); 422 FileOutputStream fos = new FileOutputStream(f, append); 423 setFilePermissionsFromMode(f.getPath(), mode, 0); 424 return fos; 425 } 426 427 @Override 428 public boolean deleteFile(String name) { 429 File f = makeFilename(getFilesDir(), name); 430 return f.delete(); 431 } 432 433 @Override 434 public File getFilesDir() { 435 synchronized (mSync) { 436 if (mFilesDir == null) { 437 mFilesDir = new File(getDataDirFile(), "files"); 438 } 439 if (!mFilesDir.exists()) { 440 if(!mFilesDir.mkdirs()) { 441 Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath()); 442 return null; 443 } 444 FileUtils.setPermissions( 445 mFilesDir.getPath(), 446 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 447 -1, -1); 448 } 449 return mFilesDir; 450 } 451 } 452 453 @Override 454 public File getExternalFilesDir(String type) { 455 synchronized (mSync) { 456 if (mExternalFilesDir == null) { 457 mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory( 458 getPackageName()); 459 } 460 if (!mExternalFilesDir.exists()) { 461 try { 462 (new File(Environment.getExternalStorageAndroidDataDir(), 463 ".nomedia")).createNewFile(); 464 } catch (IOException e) { 465 } 466 if (!mExternalFilesDir.mkdirs()) { 467 Log.w(TAG, "Unable to create external files directory"); 468 return null; 469 } 470 } 471 if (type == null) { 472 return mExternalFilesDir; 473 } 474 File dir = new File(mExternalFilesDir, type); 475 if (!dir.exists()) { 476 if (!dir.mkdirs()) { 477 Log.w(TAG, "Unable to create external media directory " + dir); 478 return null; 479 } 480 } 481 return dir; 482 } 483 } 484 485 @Override 486 public File getCacheDir() { 487 synchronized (mSync) { 488 if (mCacheDir == null) { 489 mCacheDir = new File(getDataDirFile(), "cache"); 490 } 491 if (!mCacheDir.exists()) { 492 if(!mCacheDir.mkdirs()) { 493 Log.w(TAG, "Unable to create cache directory"); 494 return null; 495 } 496 FileUtils.setPermissions( 497 mCacheDir.getPath(), 498 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 499 -1, -1); 500 } 501 } 502 return mCacheDir; 503 } 504 505 @Override 506 public File getExternalCacheDir() { 507 synchronized (mSync) { 508 if (mExternalCacheDir == null) { 509 mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory( 510 getPackageName()); 511 } 512 if (!mExternalCacheDir.exists()) { 513 try { 514 (new File(Environment.getExternalStorageAndroidDataDir(), 515 ".nomedia")).createNewFile(); 516 } catch (IOException e) { 517 } 518 if (!mExternalCacheDir.mkdirs()) { 519 Log.w(TAG, "Unable to create external cache directory"); 520 return null; 521 } 522 } 523 return mExternalCacheDir; 524 } 525 } 526 527 @Override 528 public File getFileStreamPath(String name) { 529 return makeFilename(getFilesDir(), name); 530 } 531 532 @Override 533 public String[] fileList() { 534 final String[] list = getFilesDir().list(); 535 return (list != null) ? list : EMPTY_FILE_LIST; 536 } 537 538 @Override 539 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) { 540 File f = validateFilePath(name, true); 541 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory); 542 setFilePermissionsFromMode(f.getPath(), mode, 0); 543 return db; 544 } 545 546 @Override 547 public boolean deleteDatabase(String name) { 548 try { 549 File f = validateFilePath(name, false); 550 return f.delete(); 551 } catch (Exception e) { 552 } 553 return false; 554 } 555 556 @Override 557 public File getDatabasePath(String name) { 558 return validateFilePath(name, false); 559 } 560 561 @Override 562 public String[] databaseList() { 563 final String[] list = getDatabasesDir().list(); 564 return (list != null) ? list : EMPTY_FILE_LIST; 565 } 566 567 568 private File getDatabasesDir() { 569 synchronized (mSync) { 570 if (mDatabasesDir == null) { 571 mDatabasesDir = new File(getDataDirFile(), "databases"); 572 } 573 if (mDatabasesDir.getPath().equals("databases")) { 574 mDatabasesDir = new File("/data/system"); 575 } 576 return mDatabasesDir; 577 } 578 } 579 580 @Override 581 public Drawable getWallpaper() { 582 return getWallpaperManager().getDrawable(); 583 } 584 585 @Override 586 public Drawable peekWallpaper() { 587 return getWallpaperManager().peekDrawable(); 588 } 589 590 @Override 591 public int getWallpaperDesiredMinimumWidth() { 592 return getWallpaperManager().getDesiredMinimumWidth(); 593 } 594 595 @Override 596 public int getWallpaperDesiredMinimumHeight() { 597 return getWallpaperManager().getDesiredMinimumHeight(); 598 } 599 600 @Override 601 public void setWallpaper(Bitmap bitmap) throws IOException { 602 getWallpaperManager().setBitmap(bitmap); 603 } 604 605 @Override 606 public void setWallpaper(InputStream data) throws IOException { 607 getWallpaperManager().setStream(data); 608 } 609 610 @Override 611 public void clearWallpaper() throws IOException { 612 getWallpaperManager().clear(); 613 } 614 615 @Override 616 public void startActivity(Intent intent) { 617 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 618 throw new AndroidRuntimeException( 619 "Calling startActivity() from outside of an Activity " 620 + " context requires the FLAG_ACTIVITY_NEW_TASK flag." 621 + " Is this really what you want?"); 622 } 623 mMainThread.getInstrumentation().execStartActivity( 624 getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1); 625 } 626 627 @Override 628 public void startIntentSender(IntentSender intent, 629 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 630 throws IntentSender.SendIntentException { 631 try { 632 String resolvedType = null; 633 if (fillInIntent != null) { 634 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); 635 } 636 int result = ActivityManagerNative.getDefault() 637 .startActivityIntentSender(mMainThread.getApplicationThread(), intent, 638 fillInIntent, resolvedType, null, null, 639 0, flagsMask, flagsValues); 640 if (result == IActivityManager.START_CANCELED) { 641 throw new IntentSender.SendIntentException(); 642 } 643 Instrumentation.checkStartActivityResult(result, null); 644 } catch (RemoteException e) { 645 } 646 } 647 648 @Override 649 public void sendBroadcast(Intent intent) { 650 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 651 try { 652 ActivityManagerNative.getDefault().broadcastIntent( 653 mMainThread.getApplicationThread(), intent, resolvedType, null, 654 Activity.RESULT_OK, null, null, null, false, false); 655 } catch (RemoteException e) { 656 } 657 } 658 659 @Override 660 public void sendBroadcast(Intent intent, String receiverPermission) { 661 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 662 try { 663 ActivityManagerNative.getDefault().broadcastIntent( 664 mMainThread.getApplicationThread(), intent, resolvedType, null, 665 Activity.RESULT_OK, null, null, receiverPermission, false, false); 666 } catch (RemoteException e) { 667 } 668 } 669 670 @Override 671 public void sendOrderedBroadcast(Intent intent, 672 String receiverPermission) { 673 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 674 try { 675 ActivityManagerNative.getDefault().broadcastIntent( 676 mMainThread.getApplicationThread(), intent, resolvedType, null, 677 Activity.RESULT_OK, null, null, receiverPermission, true, false); 678 } catch (RemoteException e) { 679 } 680 } 681 682 @Override 683 public void sendOrderedBroadcast(Intent intent, 684 String receiverPermission, BroadcastReceiver resultReceiver, 685 Handler scheduler, int initialCode, String initialData, 686 Bundle initialExtras) { 687 IIntentReceiver rd = null; 688 if (resultReceiver != null) { 689 if (mPackageInfo != null) { 690 if (scheduler == null) { 691 scheduler = mMainThread.getHandler(); 692 } 693 rd = mPackageInfo.getReceiverDispatcher( 694 resultReceiver, getOuterContext(), scheduler, 695 mMainThread.getInstrumentation(), false); 696 } else { 697 if (scheduler == null) { 698 scheduler = mMainThread.getHandler(); 699 } 700 rd = new LoadedApk.ReceiverDispatcher( 701 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); 702 } 703 } 704 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 705 try { 706 ActivityManagerNative.getDefault().broadcastIntent( 707 mMainThread.getApplicationThread(), intent, resolvedType, rd, 708 initialCode, initialData, initialExtras, receiverPermission, 709 true, false); 710 } catch (RemoteException e) { 711 } 712 } 713 714 @Override 715 public void sendStickyBroadcast(Intent intent) { 716 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 717 try { 718 ActivityManagerNative.getDefault().broadcastIntent( 719 mMainThread.getApplicationThread(), intent, resolvedType, null, 720 Activity.RESULT_OK, null, null, null, false, true); 721 } catch (RemoteException e) { 722 } 723 } 724 725 @Override 726 public void sendStickyOrderedBroadcast(Intent intent, 727 BroadcastReceiver resultReceiver, 728 Handler scheduler, int initialCode, String initialData, 729 Bundle initialExtras) { 730 IIntentReceiver rd = null; 731 if (resultReceiver != null) { 732 if (mPackageInfo != null) { 733 if (scheduler == null) { 734 scheduler = mMainThread.getHandler(); 735 } 736 rd = mPackageInfo.getReceiverDispatcher( 737 resultReceiver, getOuterContext(), scheduler, 738 mMainThread.getInstrumentation(), false); 739 } else { 740 if (scheduler == null) { 741 scheduler = mMainThread.getHandler(); 742 } 743 rd = new LoadedApk.ReceiverDispatcher( 744 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); 745 } 746 } 747 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 748 try { 749 ActivityManagerNative.getDefault().broadcastIntent( 750 mMainThread.getApplicationThread(), intent, resolvedType, rd, 751 initialCode, initialData, initialExtras, null, 752 true, true); 753 } catch (RemoteException e) { 754 } 755 } 756 757 @Override 758 public void removeStickyBroadcast(Intent intent) { 759 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); 760 if (resolvedType != null) { 761 intent = new Intent(intent); 762 intent.setDataAndType(intent.getData(), resolvedType); 763 } 764 try { 765 ActivityManagerNative.getDefault().unbroadcastIntent( 766 mMainThread.getApplicationThread(), intent); 767 } catch (RemoteException e) { 768 } 769 } 770 771 @Override 772 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 773 return registerReceiver(receiver, filter, null, null); 774 } 775 776 @Override 777 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 778 String broadcastPermission, Handler scheduler) { 779 return registerReceiverInternal(receiver, filter, broadcastPermission, 780 scheduler, getOuterContext()); 781 } 782 783 private Intent registerReceiverInternal(BroadcastReceiver receiver, 784 IntentFilter filter, String broadcastPermission, 785 Handler scheduler, Context context) { 786 IIntentReceiver rd = null; 787 if (receiver != null) { 788 if (mPackageInfo != null && context != null) { 789 if (scheduler == null) { 790 scheduler = mMainThread.getHandler(); 791 } 792 rd = mPackageInfo.getReceiverDispatcher( 793 receiver, context, scheduler, 794 mMainThread.getInstrumentation(), true); 795 } else { 796 if (scheduler == null) { 797 scheduler = mMainThread.getHandler(); 798 } 799 rd = new LoadedApk.ReceiverDispatcher( 800 receiver, context, scheduler, null, true).getIIntentReceiver(); 801 } 802 } 803 try { 804 return ActivityManagerNative.getDefault().registerReceiver( 805 mMainThread.getApplicationThread(), 806 rd, filter, broadcastPermission); 807 } catch (RemoteException e) { 808 return null; 809 } 810 } 811 812 @Override 813 public void unregisterReceiver(BroadcastReceiver receiver) { 814 if (mPackageInfo != null) { 815 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( 816 getOuterContext(), receiver); 817 try { 818 ActivityManagerNative.getDefault().unregisterReceiver(rd); 819 } catch (RemoteException e) { 820 } 821 } else { 822 throw new RuntimeException("Not supported in system context"); 823 } 824 } 825 826 @Override 827 public ComponentName startService(Intent service) { 828 try { 829 ComponentName cn = ActivityManagerNative.getDefault().startService( 830 mMainThread.getApplicationThread(), service, 831 service.resolveTypeIfNeeded(getContentResolver())); 832 if (cn != null && cn.getPackageName().equals("!")) { 833 throw new SecurityException( 834 "Not allowed to start service " + service 835 + " without permission " + cn.getClassName()); 836 } 837 return cn; 838 } catch (RemoteException e) { 839 return null; 840 } 841 } 842 843 @Override 844 public boolean stopService(Intent service) { 845 try { 846 int res = ActivityManagerNative.getDefault().stopService( 847 mMainThread.getApplicationThread(), service, 848 service.resolveTypeIfNeeded(getContentResolver())); 849 if (res < 0) { 850 throw new SecurityException( 851 "Not allowed to stop service " + service); 852 } 853 return res != 0; 854 } catch (RemoteException e) { 855 return false; 856 } 857 } 858 859 @Override 860 public boolean bindService(Intent service, ServiceConnection conn, 861 int flags) { 862 IServiceConnection sd; 863 if (mPackageInfo != null) { 864 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), 865 mMainThread.getHandler(), flags); 866 } else { 867 throw new RuntimeException("Not supported in system context"); 868 } 869 try { 870 int res = ActivityManagerNative.getDefault().bindService( 871 mMainThread.getApplicationThread(), getActivityToken(), 872 service, service.resolveTypeIfNeeded(getContentResolver()), 873 sd, flags); 874 if (res < 0) { 875 throw new SecurityException( 876 "Not allowed to bind to service " + service); 877 } 878 return res != 0; 879 } catch (RemoteException e) { 880 return false; 881 } 882 } 883 884 @Override 885 public void unbindService(ServiceConnection conn) { 886 if (mPackageInfo != null) { 887 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( 888 getOuterContext(), conn); 889 try { 890 ActivityManagerNative.getDefault().unbindService(sd); 891 } catch (RemoteException e) { 892 } 893 } else { 894 throw new RuntimeException("Not supported in system context"); 895 } 896 } 897 898 @Override 899 public boolean startInstrumentation(ComponentName className, 900 String profileFile, Bundle arguments) { 901 try { 902 return ActivityManagerNative.getDefault().startInstrumentation( 903 className, profileFile, 0, arguments, null); 904 } catch (RemoteException e) { 905 // System has crashed, nothing we can do. 906 } 907 return false; 908 } 909 910 @Override 911 public Object getSystemService(String name) { 912 if (WINDOW_SERVICE.equals(name)) { 913 return WindowManagerImpl.getDefault(); 914 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) { 915 synchronized (mSync) { 916 LayoutInflater inflater = mLayoutInflater; 917 if (inflater != null) { 918 return inflater; 919 } 920 mLayoutInflater = inflater = 921 PolicyManager.makeNewLayoutInflater(getOuterContext()); 922 return inflater; 923 } 924 } else if (ACTIVITY_SERVICE.equals(name)) { 925 return getActivityManager(); 926 } else if (INPUT_METHOD_SERVICE.equals(name)) { 927 return InputMethodManager.getInstance(this); 928 } else if (ALARM_SERVICE.equals(name)) { 929 return getAlarmManager(); 930 } else if (ACCOUNT_SERVICE.equals(name)) { 931 return getAccountManager(); 932 } else if (POWER_SERVICE.equals(name)) { 933 return getPowerManager(); 934 } else if (CONNECTIVITY_SERVICE.equals(name)) { 935 return getConnectivityManager(); 936 } else if (THROTTLE_SERVICE.equals(name)) { 937 return getThrottleManager(); 938 } else if (WIFI_SERVICE.equals(name)) { 939 return getWifiManager(); 940 } else if (NOTIFICATION_SERVICE.equals(name)) { 941 return getNotificationManager(); 942 } else if (KEYGUARD_SERVICE.equals(name)) { 943 return new KeyguardManager(); 944 } else if (ACCESSIBILITY_SERVICE.equals(name)) { 945 return AccessibilityManager.getInstance(this); 946 } else if (LOCATION_SERVICE.equals(name)) { 947 return getLocationManager(); 948 } else if (SEARCH_SERVICE.equals(name)) { 949 return getSearchManager(); 950 } else if (SENSOR_SERVICE.equals(name)) { 951 return getSensorManager(); 952 } else if (STORAGE_SERVICE.equals(name)) { 953 return getStorageManager(); 954 } else if (VIBRATOR_SERVICE.equals(name)) { 955 return getVibrator(); 956 } else if (STATUS_BAR_SERVICE.equals(name)) { 957 synchronized (mSync) { 958 if (mStatusBarManager == null) { 959 mStatusBarManager = new StatusBarManager(getOuterContext()); 960 } 961 return mStatusBarManager; 962 } 963 } else if (AUDIO_SERVICE.equals(name)) { 964 return getAudioManager(); 965 } else if (TELEPHONY_SERVICE.equals(name)) { 966 return getTelephonyManager(); 967 } else if (CLIPBOARD_SERVICE.equals(name)) { 968 return getClipboardManager(); 969 } else if (WALLPAPER_SERVICE.equals(name)) { 970 return getWallpaperManager(); 971 } else if (DROPBOX_SERVICE.equals(name)) { 972 return getDropBoxManager(); 973 } else if (DEVICE_POLICY_SERVICE.equals(name)) { 974 return getDevicePolicyManager(); 975 } else if (UI_MODE_SERVICE.equals(name)) { 976 return getUiModeManager(); 977 } else if (DOWNLOAD_SERVICE.equals(name)) { 978 return getDownloadManager(); 979 } else if (NFC_SERVICE.equals(name)) { 980 return getNfcManager(); 981 } 982 983 return null; 984 } 985 986 private AccountManager getAccountManager() { 987 synchronized (mSync) { 988 if (mAccountManager == null) { 989 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE); 990 IAccountManager service = IAccountManager.Stub.asInterface(b); 991 mAccountManager = new AccountManager(this, service); 992 } 993 return mAccountManager; 994 } 995 } 996 997 private ActivityManager getActivityManager() { 998 synchronized (mSync) { 999 if (mActivityManager == null) { 1000 mActivityManager = new ActivityManager(getOuterContext(), 1001 mMainThread.getHandler()); 1002 } 1003 } 1004 return mActivityManager; 1005 } 1006 1007 private AlarmManager getAlarmManager() { 1008 synchronized (sSync) { 1009 if (sAlarmManager == null) { 1010 IBinder b = ServiceManager.getService(ALARM_SERVICE); 1011 IAlarmManager service = IAlarmManager.Stub.asInterface(b); 1012 sAlarmManager = new AlarmManager(service); 1013 } 1014 } 1015 return sAlarmManager; 1016 } 1017 1018 private PowerManager getPowerManager() { 1019 synchronized (sSync) { 1020 if (sPowerManager == null) { 1021 IBinder b = ServiceManager.getService(POWER_SERVICE); 1022 IPowerManager service = IPowerManager.Stub.asInterface(b); 1023 sPowerManager = new PowerManager(service, mMainThread.getHandler()); 1024 } 1025 } 1026 return sPowerManager; 1027 } 1028 1029 private ConnectivityManager getConnectivityManager() 1030 { 1031 synchronized (sSync) { 1032 if (sConnectivityManager == null) { 1033 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE); 1034 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 1035 sConnectivityManager = new ConnectivityManager(service); 1036 } 1037 } 1038 return sConnectivityManager; 1039 } 1040 1041 private ThrottleManager getThrottleManager() 1042 { 1043 synchronized (sSync) { 1044 if (sThrottleManager == null) { 1045 IBinder b = ServiceManager.getService(THROTTLE_SERVICE); 1046 IThrottleManager service = IThrottleManager.Stub.asInterface(b); 1047 sThrottleManager = new ThrottleManager(service); 1048 } 1049 } 1050 return sThrottleManager; 1051 } 1052 1053 private WifiManager getWifiManager() 1054 { 1055 synchronized (sSync) { 1056 if (sWifiManager == null) { 1057 IBinder b = ServiceManager.getService(WIFI_SERVICE); 1058 IWifiManager service = IWifiManager.Stub.asInterface(b); 1059 sWifiManager = new WifiManager(service, mMainThread.getHandler()); 1060 } 1061 } 1062 return sWifiManager; 1063 } 1064 1065 private NotificationManager getNotificationManager() { 1066 synchronized (mSync) { 1067 if (mNotificationManager == null) { 1068 mNotificationManager = new NotificationManager( 1069 new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog), 1070 mMainThread.getHandler()); 1071 } 1072 } 1073 return mNotificationManager; 1074 } 1075 1076 private WallpaperManager getWallpaperManager() { 1077 synchronized (mSync) { 1078 if (mWallpaperManager == null) { 1079 mWallpaperManager = new WallpaperManager(getOuterContext(), 1080 mMainThread.getHandler()); 1081 } 1082 } 1083 return mWallpaperManager; 1084 } 1085 1086 private TelephonyManager getTelephonyManager() { 1087 synchronized (mSync) { 1088 if (mTelephonyManager == null) { 1089 mTelephonyManager = new TelephonyManager(getOuterContext()); 1090 } 1091 } 1092 return mTelephonyManager; 1093 } 1094 1095 private ClipboardManager getClipboardManager() { 1096 synchronized (mSync) { 1097 if (mClipboardManager == null) { 1098 mClipboardManager = new ClipboardManager(getOuterContext(), 1099 mMainThread.getHandler()); 1100 } 1101 } 1102 return mClipboardManager; 1103 } 1104 1105 private LocationManager getLocationManager() { 1106 synchronized (sSync) { 1107 if (sLocationManager == null) { 1108 IBinder b = ServiceManager.getService(LOCATION_SERVICE); 1109 ILocationManager service = ILocationManager.Stub.asInterface(b); 1110 sLocationManager = new LocationManager(service); 1111 } 1112 } 1113 return sLocationManager; 1114 } 1115 1116 private SearchManager getSearchManager() { 1117 synchronized (mSync) { 1118 if (mSearchManager == null) { 1119 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler()); 1120 } 1121 } 1122 return mSearchManager; 1123 } 1124 1125 private SensorManager getSensorManager() { 1126 synchronized (mSync) { 1127 if (mSensorManager == null) { 1128 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper()); 1129 } 1130 } 1131 return mSensorManager; 1132 } 1133 1134 private StorageManager getStorageManager() { 1135 synchronized (mSync) { 1136 if (mStorageManager == null) { 1137 try { 1138 mStorageManager = new StorageManager(mMainThread.getHandler().getLooper()); 1139 } catch (RemoteException rex) { 1140 Log.e(TAG, "Failed to create StorageManager", rex); 1141 mStorageManager = null; 1142 } 1143 } 1144 } 1145 return mStorageManager; 1146 } 1147 1148 private Vibrator getVibrator() { 1149 synchronized (mSync) { 1150 if (mVibrator == null) { 1151 mVibrator = new Vibrator(); 1152 } 1153 } 1154 return mVibrator; 1155 } 1156 1157 private AudioManager getAudioManager() 1158 { 1159 if (mAudioManager == null) { 1160 mAudioManager = new AudioManager(this); 1161 } 1162 return mAudioManager; 1163 } 1164 1165 /* package */ static DropBoxManager createDropBoxManager() { 1166 IBinder b = ServiceManager.getService(DROPBOX_SERVICE); 1167 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b); 1168 return new DropBoxManager(service); 1169 } 1170 1171 private DropBoxManager getDropBoxManager() { 1172 synchronized (mSync) { 1173 if (mDropBoxManager == null) { 1174 mDropBoxManager = createDropBoxManager(); 1175 } 1176 } 1177 return mDropBoxManager; 1178 } 1179 1180 private DevicePolicyManager getDevicePolicyManager() { 1181 synchronized (mSync) { 1182 if (mDevicePolicyManager == null) { 1183 mDevicePolicyManager = DevicePolicyManager.create(this, 1184 mMainThread.getHandler()); 1185 } 1186 } 1187 return mDevicePolicyManager; 1188 } 1189 1190 private UiModeManager getUiModeManager() { 1191 synchronized (mSync) { 1192 if (mUiModeManager == null) { 1193 mUiModeManager = new UiModeManager(); 1194 } 1195 } 1196 return mUiModeManager; 1197 } 1198 1199 private DownloadManager getDownloadManager() { 1200 synchronized (mSync) { 1201 if (mDownloadManager == null) { 1202 mDownloadManager = new DownloadManager(getContentResolver(), getPackageName()); 1203 } 1204 } 1205 return mDownloadManager; 1206 } 1207 1208 private NfcManager getNfcManager() { 1209 synchronized (mSync) { 1210 if (mNfcManager == null) { 1211 mNfcManager = new NfcManager(this); 1212 } 1213 } 1214 return mNfcManager; 1215 } 1216 1217 @Override 1218 public int checkPermission(String permission, int pid, int uid) { 1219 if (permission == null) { 1220 throw new IllegalArgumentException("permission is null"); 1221 } 1222 1223 if (!Process.supportsProcesses()) { 1224 return PackageManager.PERMISSION_GRANTED; 1225 } 1226 try { 1227 return ActivityManagerNative.getDefault().checkPermission( 1228 permission, pid, uid); 1229 } catch (RemoteException e) { 1230 return PackageManager.PERMISSION_DENIED; 1231 } 1232 } 1233 1234 @Override 1235 public int checkCallingPermission(String permission) { 1236 if (permission == null) { 1237 throw new IllegalArgumentException("permission is null"); 1238 } 1239 1240 if (!Process.supportsProcesses()) { 1241 return PackageManager.PERMISSION_GRANTED; 1242 } 1243 int pid = Binder.getCallingPid(); 1244 if (pid != Process.myPid()) { 1245 return checkPermission(permission, pid, 1246 Binder.getCallingUid()); 1247 } 1248 return PackageManager.PERMISSION_DENIED; 1249 } 1250 1251 @Override 1252 public int checkCallingOrSelfPermission(String permission) { 1253 if (permission == null) { 1254 throw new IllegalArgumentException("permission is null"); 1255 } 1256 1257 return checkPermission(permission, Binder.getCallingPid(), 1258 Binder.getCallingUid()); 1259 } 1260 1261 private void enforce( 1262 String permission, int resultOfCheck, 1263 boolean selfToo, int uid, String message) { 1264 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { 1265 throw new SecurityException( 1266 (message != null ? (message + ": ") : "") + 1267 (selfToo 1268 ? "Neither user " + uid + " nor current process has " 1269 : "User " + uid + " does not have ") + 1270 permission + 1271 "."); 1272 } 1273 } 1274 1275 public void enforcePermission( 1276 String permission, int pid, int uid, String message) { 1277 enforce(permission, 1278 checkPermission(permission, pid, uid), 1279 false, 1280 uid, 1281 message); 1282 } 1283 1284 public void enforceCallingPermission(String permission, String message) { 1285 enforce(permission, 1286 checkCallingPermission(permission), 1287 false, 1288 Binder.getCallingUid(), 1289 message); 1290 } 1291 1292 public void enforceCallingOrSelfPermission( 1293 String permission, String message) { 1294 enforce(permission, 1295 checkCallingOrSelfPermission(permission), 1296 true, 1297 Binder.getCallingUid(), 1298 message); 1299 } 1300 1301 @Override 1302 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) { 1303 try { 1304 ActivityManagerNative.getDefault().grantUriPermission( 1305 mMainThread.getApplicationThread(), toPackage, uri, 1306 modeFlags); 1307 } catch (RemoteException e) { 1308 } 1309 } 1310 1311 @Override 1312 public void revokeUriPermission(Uri uri, int modeFlags) { 1313 try { 1314 ActivityManagerNative.getDefault().revokeUriPermission( 1315 mMainThread.getApplicationThread(), uri, 1316 modeFlags); 1317 } catch (RemoteException e) { 1318 } 1319 } 1320 1321 @Override 1322 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { 1323 if (!Process.supportsProcesses()) { 1324 return PackageManager.PERMISSION_GRANTED; 1325 } 1326 try { 1327 return ActivityManagerNative.getDefault().checkUriPermission( 1328 uri, pid, uid, modeFlags); 1329 } catch (RemoteException e) { 1330 return PackageManager.PERMISSION_DENIED; 1331 } 1332 } 1333 1334 @Override 1335 public int checkCallingUriPermission(Uri uri, int modeFlags) { 1336 if (!Process.supportsProcesses()) { 1337 return PackageManager.PERMISSION_GRANTED; 1338 } 1339 int pid = Binder.getCallingPid(); 1340 if (pid != Process.myPid()) { 1341 return checkUriPermission(uri, pid, 1342 Binder.getCallingUid(), modeFlags); 1343 } 1344 return PackageManager.PERMISSION_DENIED; 1345 } 1346 1347 @Override 1348 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { 1349 return checkUriPermission(uri, Binder.getCallingPid(), 1350 Binder.getCallingUid(), modeFlags); 1351 } 1352 1353 @Override 1354 public int checkUriPermission(Uri uri, String readPermission, 1355 String writePermission, int pid, int uid, int modeFlags) { 1356 if (DEBUG) { 1357 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission=" 1358 + readPermission + " writePermission=" + writePermission 1359 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags); 1360 } 1361 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { 1362 if (readPermission == null 1363 || checkPermission(readPermission, pid, uid) 1364 == PackageManager.PERMISSION_GRANTED) { 1365 return PackageManager.PERMISSION_GRANTED; 1366 } 1367 } 1368 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { 1369 if (writePermission == null 1370 || checkPermission(writePermission, pid, uid) 1371 == PackageManager.PERMISSION_GRANTED) { 1372 return PackageManager.PERMISSION_GRANTED; 1373 } 1374 } 1375 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags) 1376 : PackageManager.PERMISSION_DENIED; 1377 } 1378 1379 private String uriModeFlagToString(int uriModeFlags) { 1380 switch (uriModeFlags) { 1381 case Intent.FLAG_GRANT_READ_URI_PERMISSION | 1382 Intent.FLAG_GRANT_WRITE_URI_PERMISSION: 1383 return "read and write"; 1384 case Intent.FLAG_GRANT_READ_URI_PERMISSION: 1385 return "read"; 1386 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION: 1387 return "write"; 1388 } 1389 throw new IllegalArgumentException( 1390 "Unknown permission mode flags: " + uriModeFlags); 1391 } 1392 1393 private void enforceForUri( 1394 int modeFlags, int resultOfCheck, boolean selfToo, 1395 int uid, Uri uri, String message) { 1396 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { 1397 throw new SecurityException( 1398 (message != null ? (message + ": ") : "") + 1399 (selfToo 1400 ? "Neither user " + uid + " nor current process has " 1401 : "User " + uid + " does not have ") + 1402 uriModeFlagToString(modeFlags) + 1403 " permission on " + 1404 uri + 1405 "."); 1406 } 1407 } 1408 1409 public void enforceUriPermission( 1410 Uri uri, int pid, int uid, int modeFlags, String message) { 1411 enforceForUri( 1412 modeFlags, checkUriPermission(uri, pid, uid, modeFlags), 1413 false, uid, uri, message); 1414 } 1415 1416 public void enforceCallingUriPermission( 1417 Uri uri, int modeFlags, String message) { 1418 enforceForUri( 1419 modeFlags, checkCallingUriPermission(uri, modeFlags), 1420 false, Binder.getCallingUid(), uri, message); 1421 } 1422 1423 public void enforceCallingOrSelfUriPermission( 1424 Uri uri, int modeFlags, String message) { 1425 enforceForUri( 1426 modeFlags, 1427 checkCallingOrSelfUriPermission(uri, modeFlags), true, 1428 Binder.getCallingUid(), uri, message); 1429 } 1430 1431 public void enforceUriPermission( 1432 Uri uri, String readPermission, String writePermission, 1433 int pid, int uid, int modeFlags, String message) { 1434 enforceForUri(modeFlags, 1435 checkUriPermission( 1436 uri, readPermission, writePermission, pid, uid, 1437 modeFlags), 1438 false, 1439 uid, 1440 uri, 1441 message); 1442 } 1443 1444 @Override 1445 public Context createPackageContext(String packageName, int flags) 1446 throws PackageManager.NameNotFoundException { 1447 if (packageName.equals("system") || packageName.equals("android")) { 1448 return new ContextImpl(mMainThread.getSystemContext()); 1449 } 1450 1451 LoadedApk pi = 1452 mMainThread.getPackageInfo(packageName, flags); 1453 if (pi != null) { 1454 ContextImpl c = new ContextImpl(); 1455 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; 1456 c.init(pi, null, mMainThread, mResources); 1457 if (c.mResources != null) { 1458 return c; 1459 } 1460 } 1461 1462 // Should be a better exception. 1463 throw new PackageManager.NameNotFoundException( 1464 "Application package " + packageName + " not found"); 1465 } 1466 1467 @Override 1468 public boolean isRestricted() { 1469 return mRestricted; 1470 } 1471 1472 private File getDataDirFile() { 1473 if (mPackageInfo != null) { 1474 return mPackageInfo.getDataDirFile(); 1475 } 1476 throw new RuntimeException("Not supported in system context"); 1477 } 1478 1479 @Override 1480 public File getDir(String name, int mode) { 1481 name = "app_" + name; 1482 File file = makeFilename(getDataDirFile(), name); 1483 if (!file.exists()) { 1484 file.mkdir(); 1485 setFilePermissionsFromMode(file.getPath(), mode, 1486 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH); 1487 } 1488 return file; 1489 } 1490 1491 static ContextImpl createSystemContext(ActivityThread mainThread) { 1492 ContextImpl context = new ContextImpl(); 1493 context.init(Resources.getSystem(), mainThread); 1494 return context; 1495 } 1496 1497 ContextImpl() { 1498 // For debug only 1499 //++sInstanceCount; 1500 mOuterContext = this; 1501 } 1502 1503 /** 1504 * Create a new ApplicationContext from an existing one. The new one 1505 * works and operates the same as the one it is copying. 1506 * 1507 * @param context Existing application context. 1508 */ 1509 public ContextImpl(ContextImpl context) { 1510 ++sInstanceCount; 1511 mPackageInfo = context.mPackageInfo; 1512 mResources = context.mResources; 1513 mMainThread = context.mMainThread; 1514 mContentResolver = context.mContentResolver; 1515 mOuterContext = this; 1516 } 1517 1518 final void init(LoadedApk packageInfo, 1519 IBinder activityToken, ActivityThread mainThread) { 1520 init(packageInfo, activityToken, mainThread, null); 1521 } 1522 1523 final void init(LoadedApk packageInfo, 1524 IBinder activityToken, ActivityThread mainThread, 1525 Resources container) { 1526 mPackageInfo = packageInfo; 1527 mResources = mPackageInfo.getResources(mainThread); 1528 1529 if (mResources != null && container != null 1530 && container.getCompatibilityInfo().applicationScale != 1531 mResources.getCompatibilityInfo().applicationScale) { 1532 if (DEBUG) { 1533 Log.d(TAG, "loaded context has different scaling. Using container's" + 1534 " compatiblity info:" + container.getDisplayMetrics()); 1535 } 1536 mResources = mainThread.getTopLevelResources( 1537 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy()); 1538 } 1539 mMainThread = mainThread; 1540 mContentResolver = new ApplicationContentResolver(this, mainThread); 1541 1542 setActivityToken(activityToken); 1543 } 1544 1545 final void init(Resources resources, ActivityThread mainThread) { 1546 mPackageInfo = null; 1547 mResources = resources; 1548 mMainThread = mainThread; 1549 mContentResolver = new ApplicationContentResolver(this, mainThread); 1550 } 1551 1552 final void scheduleFinalCleanup(String who, String what) { 1553 mMainThread.scheduleContextCleanup(this, who, what); 1554 } 1555 1556 final void performFinalCleanup(String who, String what) { 1557 //Log.i(TAG, "Cleanup up context: " + this); 1558 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what); 1559 } 1560 1561 final Context getReceiverRestrictedContext() { 1562 if (mReceiverRestrictedContext != null) { 1563 return mReceiverRestrictedContext; 1564 } 1565 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext()); 1566 } 1567 1568 final void setActivityToken(IBinder token) { 1569 mActivityToken = token; 1570 } 1571 1572 final void setOuterContext(Context context) { 1573 mOuterContext = context; 1574 } 1575 1576 final Context getOuterContext() { 1577 return mOuterContext; 1578 } 1579 1580 final IBinder getActivityToken() { 1581 return mActivityToken; 1582 } 1583 1584 private static void setFilePermissionsFromMode(String name, int mode, 1585 int extraPermissions) { 1586 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR 1587 |FileUtils.S_IRGRP|FileUtils.S_IWGRP 1588 |extraPermissions; 1589 if ((mode&MODE_WORLD_READABLE) != 0) { 1590 perms |= FileUtils.S_IROTH; 1591 } 1592 if ((mode&MODE_WORLD_WRITEABLE) != 0) { 1593 perms |= FileUtils.S_IWOTH; 1594 } 1595 if (DEBUG) { 1596 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode) 1597 + ", perms=0x" + Integer.toHexString(perms)); 1598 } 1599 FileUtils.setPermissions(name, perms, -1, -1); 1600 } 1601 1602 private File validateFilePath(String name, boolean createDirectory) { 1603 File dir; 1604 File f; 1605 1606 if (name.charAt(0) == File.separatorChar) { 1607 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar)); 1608 dir = new File(dirPath); 1609 name = name.substring(name.lastIndexOf(File.separatorChar)); 1610 f = new File(dir, name); 1611 } else { 1612 dir = getDatabasesDir(); 1613 f = makeFilename(dir, name); 1614 } 1615 1616 if (createDirectory && !dir.isDirectory() && dir.mkdir()) { 1617 FileUtils.setPermissions(dir.getPath(), 1618 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 1619 -1, -1); 1620 } 1621 1622 return f; 1623 } 1624 1625 private File makeFilename(File base, String name) { 1626 if (name.indexOf(File.separatorChar) < 0) { 1627 return new File(base, name); 1628 } 1629 throw new IllegalArgumentException( 1630 "File " + name + " contains a path separator"); 1631 } 1632 1633 // ---------------------------------------------------------------------- 1634 // ---------------------------------------------------------------------- 1635 // ---------------------------------------------------------------------- 1636 1637 private static final class ApplicationContentResolver extends ContentResolver { 1638 public ApplicationContentResolver(Context context, ActivityThread mainThread) { 1639 super(context); 1640 mMainThread = mainThread; 1641 } 1642 1643 @Override 1644 protected IContentProvider acquireProvider(Context context, String name) { 1645 return mMainThread.acquireProvider(context, name); 1646 } 1647 1648 @Override 1649 protected IContentProvider acquireExistingProvider(Context context, String name) { 1650 return mMainThread.acquireExistingProvider(context, name); 1651 } 1652 1653 @Override 1654 public boolean releaseProvider(IContentProvider provider) { 1655 return mMainThread.releaseProvider(provider); 1656 } 1657 1658 private final ActivityThread mMainThread; 1659 } 1660 1661 // ---------------------------------------------------------------------- 1662 // ---------------------------------------------------------------------- 1663 // ---------------------------------------------------------------------- 1664 1665 /*package*/ 1666 static final class ApplicationPackageManager extends PackageManager { 1667 @Override 1668 public PackageInfo getPackageInfo(String packageName, int flags) 1669 throws NameNotFoundException { 1670 try { 1671 PackageInfo pi = mPM.getPackageInfo(packageName, flags); 1672 if (pi != null) { 1673 return pi; 1674 } 1675 } catch (RemoteException e) { 1676 throw new RuntimeException("Package manager has died", e); 1677 } 1678 1679 throw new NameNotFoundException(packageName); 1680 } 1681 1682 @Override 1683 public String[] currentToCanonicalPackageNames(String[] names) { 1684 try { 1685 return mPM.currentToCanonicalPackageNames(names); 1686 } catch (RemoteException e) { 1687 throw new RuntimeException("Package manager has died", e); 1688 } 1689 } 1690 1691 @Override 1692 public String[] canonicalToCurrentPackageNames(String[] names) { 1693 try { 1694 return mPM.canonicalToCurrentPackageNames(names); 1695 } catch (RemoteException e) { 1696 throw new RuntimeException("Package manager has died", e); 1697 } 1698 } 1699 1700 @Override 1701 public Intent getLaunchIntentForPackage(String packageName) { 1702 // First see if the package has an INFO activity; the existence of 1703 // such an activity is implied to be the desired front-door for the 1704 // overall package (such as if it has multiple launcher entries). 1705 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1706 intentToResolve.addCategory(Intent.CATEGORY_INFO); 1707 intentToResolve.setPackage(packageName); 1708 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0); 1709 1710 // Otherwise, try to find a main launcher activity. 1711 if (resolveInfo == null) { 1712 // reuse the intent instance 1713 intentToResolve.removeCategory(Intent.CATEGORY_INFO); 1714 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 1715 intentToResolve.setPackage(packageName); 1716 resolveInfo = resolveActivity(intentToResolve, 0); 1717 } 1718 if (resolveInfo == null) { 1719 return null; 1720 } 1721 Intent intent = new Intent(intentToResolve); 1722 intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName, 1723 resolveInfo.activityInfo.name); 1724 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1725 return intent; 1726 } 1727 1728 @Override 1729 public int[] getPackageGids(String packageName) 1730 throws NameNotFoundException { 1731 try { 1732 int[] gids = mPM.getPackageGids(packageName); 1733 if (gids == null || gids.length > 0) { 1734 return gids; 1735 } 1736 } catch (RemoteException e) { 1737 throw new RuntimeException("Package manager has died", e); 1738 } 1739 1740 throw new NameNotFoundException(packageName); 1741 } 1742 1743 @Override 1744 public PermissionInfo getPermissionInfo(String name, int flags) 1745 throws NameNotFoundException { 1746 try { 1747 PermissionInfo pi = mPM.getPermissionInfo(name, flags); 1748 if (pi != null) { 1749 return pi; 1750 } 1751 } catch (RemoteException e) { 1752 throw new RuntimeException("Package manager has died", e); 1753 } 1754 1755 throw new NameNotFoundException(name); 1756 } 1757 1758 @Override 1759 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) 1760 throws NameNotFoundException { 1761 try { 1762 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags); 1763 if (pi != null) { 1764 return pi; 1765 } 1766 } catch (RemoteException e) { 1767 throw new RuntimeException("Package manager has died", e); 1768 } 1769 1770 throw new NameNotFoundException(group); 1771 } 1772 1773 @Override 1774 public PermissionGroupInfo getPermissionGroupInfo(String name, 1775 int flags) throws NameNotFoundException { 1776 try { 1777 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags); 1778 if (pgi != null) { 1779 return pgi; 1780 } 1781 } catch (RemoteException e) { 1782 throw new RuntimeException("Package manager has died", e); 1783 } 1784 1785 throw new NameNotFoundException(name); 1786 } 1787 1788 @Override 1789 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 1790 try { 1791 return mPM.getAllPermissionGroups(flags); 1792 } catch (RemoteException e) { 1793 throw new RuntimeException("Package manager has died", e); 1794 } 1795 } 1796 1797 @Override 1798 public ApplicationInfo getApplicationInfo(String packageName, int flags) 1799 throws NameNotFoundException { 1800 try { 1801 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags); 1802 if (ai != null) { 1803 return ai; 1804 } 1805 } catch (RemoteException e) { 1806 throw new RuntimeException("Package manager has died", e); 1807 } 1808 1809 throw new NameNotFoundException(packageName); 1810 } 1811 1812 @Override 1813 public ActivityInfo getActivityInfo(ComponentName className, int flags) 1814 throws NameNotFoundException { 1815 try { 1816 ActivityInfo ai = mPM.getActivityInfo(className, flags); 1817 if (ai != null) { 1818 return ai; 1819 } 1820 } catch (RemoteException e) { 1821 throw new RuntimeException("Package manager has died", e); 1822 } 1823 1824 throw new NameNotFoundException(className.toString()); 1825 } 1826 1827 @Override 1828 public ActivityInfo getReceiverInfo(ComponentName className, int flags) 1829 throws NameNotFoundException { 1830 try { 1831 ActivityInfo ai = mPM.getReceiverInfo(className, flags); 1832 if (ai != null) { 1833 return ai; 1834 } 1835 } catch (RemoteException e) { 1836 throw new RuntimeException("Package manager has died", e); 1837 } 1838 1839 throw new NameNotFoundException(className.toString()); 1840 } 1841 1842 @Override 1843 public ServiceInfo getServiceInfo(ComponentName className, int flags) 1844 throws NameNotFoundException { 1845 try { 1846 ServiceInfo si = mPM.getServiceInfo(className, flags); 1847 if (si != null) { 1848 return si; 1849 } 1850 } catch (RemoteException e) { 1851 throw new RuntimeException("Package manager has died", e); 1852 } 1853 1854 throw new NameNotFoundException(className.toString()); 1855 } 1856 1857 @Override 1858 public ProviderInfo getProviderInfo(ComponentName className, int flags) 1859 throws NameNotFoundException { 1860 try { 1861 ProviderInfo pi = mPM.getProviderInfo(className, flags); 1862 if (pi != null) { 1863 return pi; 1864 } 1865 } catch (RemoteException e) { 1866 throw new RuntimeException("Package manager has died", e); 1867 } 1868 1869 throw new NameNotFoundException(className.toString()); 1870 } 1871 1872 @Override 1873 public String[] getSystemSharedLibraryNames() { 1874 try { 1875 return mPM.getSystemSharedLibraryNames(); 1876 } catch (RemoteException e) { 1877 throw new RuntimeException("Package manager has died", e); 1878 } 1879 } 1880 1881 @Override 1882 public FeatureInfo[] getSystemAvailableFeatures() { 1883 try { 1884 return mPM.getSystemAvailableFeatures(); 1885 } catch (RemoteException e) { 1886 throw new RuntimeException("Package manager has died", e); 1887 } 1888 } 1889 1890 @Override 1891 public boolean hasSystemFeature(String name) { 1892 try { 1893 return mPM.hasSystemFeature(name); 1894 } catch (RemoteException e) { 1895 throw new RuntimeException("Package manager has died", e); 1896 } 1897 } 1898 1899 @Override 1900 public int checkPermission(String permName, String pkgName) { 1901 try { 1902 return mPM.checkPermission(permName, pkgName); 1903 } catch (RemoteException e) { 1904 throw new RuntimeException("Package manager has died", e); 1905 } 1906 } 1907 1908 @Override 1909 public boolean addPermission(PermissionInfo info) { 1910 try { 1911 return mPM.addPermission(info); 1912 } catch (RemoteException e) { 1913 throw new RuntimeException("Package manager has died", e); 1914 } 1915 } 1916 1917 @Override 1918 public boolean addPermissionAsync(PermissionInfo info) { 1919 try { 1920 return mPM.addPermissionAsync(info); 1921 } catch (RemoteException e) { 1922 throw new RuntimeException("Package manager has died", e); 1923 } 1924 } 1925 1926 @Override 1927 public void removePermission(String name) { 1928 try { 1929 mPM.removePermission(name); 1930 } catch (RemoteException e) { 1931 throw new RuntimeException("Package manager has died", e); 1932 } 1933 } 1934 1935 @Override 1936 public int checkSignatures(String pkg1, String pkg2) { 1937 try { 1938 return mPM.checkSignatures(pkg1, pkg2); 1939 } catch (RemoteException e) { 1940 throw new RuntimeException("Package manager has died", e); 1941 } 1942 } 1943 1944 @Override 1945 public int checkSignatures(int uid1, int uid2) { 1946 try { 1947 return mPM.checkUidSignatures(uid1, uid2); 1948 } catch (RemoteException e) { 1949 throw new RuntimeException("Package manager has died", e); 1950 } 1951 } 1952 1953 @Override 1954 public String[] getPackagesForUid(int uid) { 1955 try { 1956 return mPM.getPackagesForUid(uid); 1957 } catch (RemoteException e) { 1958 throw new RuntimeException("Package manager has died", e); 1959 } 1960 } 1961 1962 @Override 1963 public String getNameForUid(int uid) { 1964 try { 1965 return mPM.getNameForUid(uid); 1966 } catch (RemoteException e) { 1967 throw new RuntimeException("Package manager has died", e); 1968 } 1969 } 1970 1971 @Override 1972 public int getUidForSharedUser(String sharedUserName) 1973 throws NameNotFoundException { 1974 try { 1975 int uid = mPM.getUidForSharedUser(sharedUserName); 1976 if(uid != -1) { 1977 return uid; 1978 } 1979 } catch (RemoteException e) { 1980 throw new RuntimeException("Package manager has died", e); 1981 } 1982 throw new NameNotFoundException("No shared userid for user:"+sharedUserName); 1983 } 1984 1985 @Override 1986 public List<PackageInfo> getInstalledPackages(int flags) { 1987 try { 1988 return mPM.getInstalledPackages(flags); 1989 } catch (RemoteException e) { 1990 throw new RuntimeException("Package manager has died", e); 1991 } 1992 } 1993 1994 @Override 1995 public List<ApplicationInfo> getInstalledApplications(int flags) { 1996 try { 1997 return mPM.getInstalledApplications(flags); 1998 } catch (RemoteException e) { 1999 throw new RuntimeException("Package manager has died", e); 2000 } 2001 } 2002 2003 @Override 2004 public ResolveInfo resolveActivity(Intent intent, int flags) { 2005 try { 2006 return mPM.resolveIntent( 2007 intent, 2008 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2009 flags); 2010 } catch (RemoteException e) { 2011 throw new RuntimeException("Package manager has died", e); 2012 } 2013 } 2014 2015 @Override 2016 public List<ResolveInfo> queryIntentActivities(Intent intent, 2017 int flags) { 2018 try { 2019 return mPM.queryIntentActivities( 2020 intent, 2021 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2022 flags); 2023 } catch (RemoteException e) { 2024 throw new RuntimeException("Package manager has died", e); 2025 } 2026 } 2027 2028 @Override 2029 public List<ResolveInfo> queryIntentActivityOptions( 2030 ComponentName caller, Intent[] specifics, Intent intent, 2031 int flags) { 2032 final ContentResolver resolver = mContext.getContentResolver(); 2033 2034 String[] specificTypes = null; 2035 if (specifics != null) { 2036 final int N = specifics.length; 2037 for (int i=0; i<N; i++) { 2038 Intent sp = specifics[i]; 2039 if (sp != null) { 2040 String t = sp.resolveTypeIfNeeded(resolver); 2041 if (t != null) { 2042 if (specificTypes == null) { 2043 specificTypes = new String[N]; 2044 } 2045 specificTypes[i] = t; 2046 } 2047 } 2048 } 2049 } 2050 2051 try { 2052 return mPM.queryIntentActivityOptions(caller, specifics, 2053 specificTypes, intent, intent.resolveTypeIfNeeded(resolver), 2054 flags); 2055 } catch (RemoteException e) { 2056 throw new RuntimeException("Package manager has died", e); 2057 } 2058 } 2059 2060 @Override 2061 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { 2062 try { 2063 return mPM.queryIntentReceivers( 2064 intent, 2065 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2066 flags); 2067 } catch (RemoteException e) { 2068 throw new RuntimeException("Package manager has died", e); 2069 } 2070 } 2071 2072 @Override 2073 public ResolveInfo resolveService(Intent intent, int flags) { 2074 try { 2075 return mPM.resolveService( 2076 intent, 2077 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2078 flags); 2079 } catch (RemoteException e) { 2080 throw new RuntimeException("Package manager has died", e); 2081 } 2082 } 2083 2084 @Override 2085 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) { 2086 try { 2087 return mPM.queryIntentServices( 2088 intent, 2089 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2090 flags); 2091 } catch (RemoteException e) { 2092 throw new RuntimeException("Package manager has died", e); 2093 } 2094 } 2095 2096 @Override 2097 public ProviderInfo resolveContentProvider(String name, 2098 int flags) { 2099 try { 2100 return mPM.resolveContentProvider(name, flags); 2101 } catch (RemoteException e) { 2102 throw new RuntimeException("Package manager has died", e); 2103 } 2104 } 2105 2106 @Override 2107 public List<ProviderInfo> queryContentProviders(String processName, 2108 int uid, int flags) { 2109 try { 2110 return mPM.queryContentProviders(processName, uid, flags); 2111 } catch (RemoteException e) { 2112 throw new RuntimeException("Package manager has died", e); 2113 } 2114 } 2115 2116 @Override 2117 public InstrumentationInfo getInstrumentationInfo( 2118 ComponentName className, int flags) 2119 throws NameNotFoundException { 2120 try { 2121 InstrumentationInfo ii = mPM.getInstrumentationInfo( 2122 className, flags); 2123 if (ii != null) { 2124 return ii; 2125 } 2126 } catch (RemoteException e) { 2127 throw new RuntimeException("Package manager has died", e); 2128 } 2129 2130 throw new NameNotFoundException(className.toString()); 2131 } 2132 2133 @Override 2134 public List<InstrumentationInfo> queryInstrumentation( 2135 String targetPackage, int flags) { 2136 try { 2137 return mPM.queryInstrumentation(targetPackage, flags); 2138 } catch (RemoteException e) { 2139 throw new RuntimeException("Package manager has died", e); 2140 } 2141 } 2142 2143 @Override public Drawable getDrawable(String packageName, int resid, 2144 ApplicationInfo appInfo) { 2145 ResourceName name = new ResourceName(packageName, resid); 2146 Drawable dr = getCachedIcon(name); 2147 if (dr != null) { 2148 return dr; 2149 } 2150 if (appInfo == null) { 2151 try { 2152 appInfo = getApplicationInfo(packageName, 0); 2153 } catch (NameNotFoundException e) { 2154 return null; 2155 } 2156 } 2157 try { 2158 Resources r = getResourcesForApplication(appInfo); 2159 dr = r.getDrawable(resid); 2160 if (false) { 2161 RuntimeException e = new RuntimeException("here"); 2162 e.fillInStackTrace(); 2163 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid) 2164 + " from package " + packageName 2165 + ": app scale=" + r.getCompatibilityInfo().applicationScale 2166 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale, 2167 e); 2168 } 2169 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x" 2170 + Integer.toHexString(resid) + " from " + r 2171 + ": " + dr); 2172 putCachedIcon(name, dr); 2173 return dr; 2174 } catch (NameNotFoundException e) { 2175 Log.w("PackageManager", "Failure retrieving resources for" 2176 + appInfo.packageName); 2177 } catch (RuntimeException e) { 2178 // If an exception was thrown, fall through to return 2179 // default icon. 2180 Log.w("PackageManager", "Failure retrieving icon 0x" 2181 + Integer.toHexString(resid) + " in package " 2182 + packageName, e); 2183 } 2184 return null; 2185 } 2186 2187 @Override public Drawable getActivityIcon(ComponentName activityName) 2188 throws NameNotFoundException { 2189 return getActivityInfo(activityName, 0).loadIcon(this); 2190 } 2191 2192 @Override public Drawable getActivityIcon(Intent intent) 2193 throws NameNotFoundException { 2194 if (intent.getComponent() != null) { 2195 return getActivityIcon(intent.getComponent()); 2196 } 2197 2198 ResolveInfo info = resolveActivity( 2199 intent, PackageManager.MATCH_DEFAULT_ONLY); 2200 if (info != null) { 2201 return info.activityInfo.loadIcon(this); 2202 } 2203 2204 throw new NameNotFoundException(intent.toURI()); 2205 } 2206 2207 @Override public Drawable getDefaultActivityIcon() { 2208 return Resources.getSystem().getDrawable( 2209 com.android.internal.R.drawable.sym_def_app_icon); 2210 } 2211 2212 @Override public Drawable getApplicationIcon(ApplicationInfo info) { 2213 return info.loadIcon(this); 2214 } 2215 2216 @Override public Drawable getApplicationIcon(String packageName) 2217 throws NameNotFoundException { 2218 return getApplicationIcon(getApplicationInfo(packageName, 0)); 2219 } 2220 2221 @Override 2222 public Drawable getActivityLogo(ComponentName activityName) 2223 throws NameNotFoundException { 2224 return getActivityInfo(activityName, 0).loadLogo(this); 2225 } 2226 2227 @Override 2228 public Drawable getActivityLogo(Intent intent) 2229 throws NameNotFoundException { 2230 if (intent.getComponent() != null) { 2231 return getActivityLogo(intent.getComponent()); 2232 } 2233 2234 ResolveInfo info = resolveActivity( 2235 intent, PackageManager.MATCH_DEFAULT_ONLY); 2236 if (info != null) { 2237 return info.activityInfo.loadLogo(this); 2238 } 2239 2240 throw new NameNotFoundException(intent.toUri(0)); 2241 } 2242 2243 @Override 2244 public Drawable getApplicationLogo(ApplicationInfo info) { 2245 return info.loadLogo(this); 2246 } 2247 2248 @Override 2249 public Drawable getApplicationLogo(String packageName) 2250 throws NameNotFoundException { 2251 return getApplicationLogo(getApplicationInfo(packageName, 0)); 2252 } 2253 2254 @Override public Resources getResourcesForActivity( 2255 ComponentName activityName) throws NameNotFoundException { 2256 return getResourcesForApplication( 2257 getActivityInfo(activityName, 0).applicationInfo); 2258 } 2259 2260 @Override public Resources getResourcesForApplication( 2261 ApplicationInfo app) throws NameNotFoundException { 2262 if (app.packageName.equals("system")) { 2263 return mContext.mMainThread.getSystemContext().getResources(); 2264 } 2265 Resources r = mContext.mMainThread.getTopLevelResources( 2266 app.uid == Process.myUid() ? app.sourceDir 2267 : app.publicSourceDir, mContext.mPackageInfo); 2268 if (r != null) { 2269 return r; 2270 } 2271 throw new NameNotFoundException("Unable to open " + app.publicSourceDir); 2272 } 2273 2274 @Override public Resources getResourcesForApplication( 2275 String appPackageName) throws NameNotFoundException { 2276 return getResourcesForApplication( 2277 getApplicationInfo(appPackageName, 0)); 2278 } 2279 2280 int mCachedSafeMode = -1; 2281 @Override public boolean isSafeMode() { 2282 try { 2283 if (mCachedSafeMode < 0) { 2284 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0; 2285 } 2286 return mCachedSafeMode != 0; 2287 } catch (RemoteException e) { 2288 throw new RuntimeException("Package manager has died", e); 2289 } 2290 } 2291 2292 static void configurationChanged() { 2293 synchronized (sSync) { 2294 sIconCache.clear(); 2295 sStringCache.clear(); 2296 } 2297 } 2298 2299 ApplicationPackageManager(ContextImpl context, 2300 IPackageManager pm) { 2301 mContext = context; 2302 mPM = pm; 2303 } 2304 2305 private Drawable getCachedIcon(ResourceName name) { 2306 synchronized (sSync) { 2307 WeakReference<Drawable> wr = sIconCache.get(name); 2308 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for " 2309 + name + ": " + wr); 2310 if (wr != null) { // we have the activity 2311 Drawable dr = wr.get(); 2312 if (dr != null) { 2313 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for " 2314 + name + ": " + dr); 2315 return dr; 2316 } 2317 // our entry has been purged 2318 sIconCache.remove(name); 2319 } 2320 } 2321 return null; 2322 } 2323 2324 private void putCachedIcon(ResourceName name, Drawable dr) { 2325 synchronized (sSync) { 2326 sIconCache.put(name, new WeakReference<Drawable>(dr)); 2327 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for " 2328 + name + ": " + dr); 2329 } 2330 } 2331 2332 static final void handlePackageBroadcast(int cmd, String[] pkgList, 2333 boolean hasPkgInfo) { 2334 boolean immediateGc = false; 2335 if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) { 2336 immediateGc = true; 2337 } 2338 if (pkgList != null && (pkgList.length > 0)) { 2339 boolean needCleanup = false; 2340 for (String ssp : pkgList) { 2341 synchronized (sSync) { 2342 if (sIconCache.size() > 0) { 2343 Iterator<ResourceName> it = sIconCache.keySet().iterator(); 2344 while (it.hasNext()) { 2345 ResourceName nm = it.next(); 2346 if (nm.packageName.equals(ssp)) { 2347 //Log.i(TAG, "Removing cached drawable for " + nm); 2348 it.remove(); 2349 needCleanup = true; 2350 } 2351 } 2352 } 2353 if (sStringCache.size() > 0) { 2354 Iterator<ResourceName> it = sStringCache.keySet().iterator(); 2355 while (it.hasNext()) { 2356 ResourceName nm = it.next(); 2357 if (nm.packageName.equals(ssp)) { 2358 //Log.i(TAG, "Removing cached string for " + nm); 2359 it.remove(); 2360 needCleanup = true; 2361 } 2362 } 2363 } 2364 } 2365 } 2366 if (needCleanup || hasPkgInfo) { 2367 if (immediateGc) { 2368 // Schedule an immediate gc. 2369 Runtime.getRuntime().gc(); 2370 } else { 2371 ActivityThread.currentActivityThread().scheduleGcIdler(); 2372 } 2373 } 2374 } 2375 } 2376 2377 private static final class ResourceName { 2378 final String packageName; 2379 final int iconId; 2380 2381 ResourceName(String _packageName, int _iconId) { 2382 packageName = _packageName; 2383 iconId = _iconId; 2384 } 2385 2386 ResourceName(ApplicationInfo aInfo, int _iconId) { 2387 this(aInfo.packageName, _iconId); 2388 } 2389 2390 ResourceName(ComponentInfo cInfo, int _iconId) { 2391 this(cInfo.applicationInfo.packageName, _iconId); 2392 } 2393 2394 ResourceName(ResolveInfo rInfo, int _iconId) { 2395 this(rInfo.activityInfo.applicationInfo.packageName, _iconId); 2396 } 2397 2398 @Override 2399 public boolean equals(Object o) { 2400 if (this == o) return true; 2401 if (o == null || getClass() != o.getClass()) return false; 2402 2403 ResourceName that = (ResourceName) o; 2404 2405 if (iconId != that.iconId) return false; 2406 return !(packageName != null ? 2407 !packageName.equals(that.packageName) : that.packageName != null); 2408 2409 } 2410 2411 @Override 2412 public int hashCode() { 2413 int result; 2414 result = packageName.hashCode(); 2415 result = 31 * result + iconId; 2416 return result; 2417 } 2418 2419 @Override 2420 public String toString() { 2421 return "{ResourceName " + packageName + " / " + iconId + "}"; 2422 } 2423 } 2424 2425 private CharSequence getCachedString(ResourceName name) { 2426 synchronized (sSync) { 2427 WeakReference<CharSequence> wr = sStringCache.get(name); 2428 if (wr != null) { // we have the activity 2429 CharSequence cs = wr.get(); 2430 if (cs != null) { 2431 return cs; 2432 } 2433 // our entry has been purged 2434 sStringCache.remove(name); 2435 } 2436 } 2437 return null; 2438 } 2439 2440 private void putCachedString(ResourceName name, CharSequence cs) { 2441 synchronized (sSync) { 2442 sStringCache.put(name, new WeakReference<CharSequence>(cs)); 2443 } 2444 } 2445 2446 @Override 2447 public CharSequence getText(String packageName, int resid, 2448 ApplicationInfo appInfo) { 2449 ResourceName name = new ResourceName(packageName, resid); 2450 CharSequence text = getCachedString(name); 2451 if (text != null) { 2452 return text; 2453 } 2454 if (appInfo == null) { 2455 try { 2456 appInfo = getApplicationInfo(packageName, 0); 2457 } catch (NameNotFoundException e) { 2458 return null; 2459 } 2460 } 2461 try { 2462 Resources r = getResourcesForApplication(appInfo); 2463 text = r.getText(resid); 2464 putCachedString(name, text); 2465 return text; 2466 } catch (NameNotFoundException e) { 2467 Log.w("PackageManager", "Failure retrieving resources for" 2468 + appInfo.packageName); 2469 } catch (RuntimeException e) { 2470 // If an exception was thrown, fall through to return 2471 // default icon. 2472 Log.w("PackageManager", "Failure retrieving text 0x" 2473 + Integer.toHexString(resid) + " in package " 2474 + packageName, e); 2475 } 2476 return null; 2477 } 2478 2479 @Override 2480 public XmlResourceParser getXml(String packageName, int resid, 2481 ApplicationInfo appInfo) { 2482 if (appInfo == null) { 2483 try { 2484 appInfo = getApplicationInfo(packageName, 0); 2485 } catch (NameNotFoundException e) { 2486 return null; 2487 } 2488 } 2489 try { 2490 Resources r = getResourcesForApplication(appInfo); 2491 return r.getXml(resid); 2492 } catch (RuntimeException e) { 2493 // If an exception was thrown, fall through to return 2494 // default icon. 2495 Log.w("PackageManager", "Failure retrieving xml 0x" 2496 + Integer.toHexString(resid) + " in package " 2497 + packageName, e); 2498 } catch (NameNotFoundException e) { 2499 Log.w("PackageManager", "Failure retrieving resources for" 2500 + appInfo.packageName); 2501 } 2502 return null; 2503 } 2504 2505 @Override 2506 public CharSequence getApplicationLabel(ApplicationInfo info) { 2507 return info.loadLabel(this); 2508 } 2509 2510 @Override 2511 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, 2512 String installerPackageName) { 2513 try { 2514 mPM.installPackage(packageURI, observer, flags, installerPackageName); 2515 } catch (RemoteException e) { 2516 // Should never happen! 2517 } 2518 } 2519 2520 @Override 2521 public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { 2522 try { 2523 mPM.movePackage(packageName, observer, flags); 2524 } catch (RemoteException e) { 2525 // Should never happen! 2526 } 2527 } 2528 2529 @Override 2530 public String getInstallerPackageName(String packageName) { 2531 try { 2532 return mPM.getInstallerPackageName(packageName); 2533 } catch (RemoteException e) { 2534 // Should never happen! 2535 } 2536 return null; 2537 } 2538 2539 @Override 2540 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 2541 try { 2542 mPM.deletePackage(packageName, observer, flags); 2543 } catch (RemoteException e) { 2544 // Should never happen! 2545 } 2546 } 2547 @Override 2548 public void clearApplicationUserData(String packageName, 2549 IPackageDataObserver observer) { 2550 try { 2551 mPM.clearApplicationUserData(packageName, observer); 2552 } catch (RemoteException e) { 2553 // Should never happen! 2554 } 2555 } 2556 @Override 2557 public void deleteApplicationCacheFiles(String packageName, 2558 IPackageDataObserver observer) { 2559 try { 2560 mPM.deleteApplicationCacheFiles(packageName, observer); 2561 } catch (RemoteException e) { 2562 // Should never happen! 2563 } 2564 } 2565 @Override 2566 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) { 2567 try { 2568 mPM.freeStorageAndNotify(idealStorageSize, observer); 2569 } catch (RemoteException e) { 2570 // Should never happen! 2571 } 2572 } 2573 2574 @Override 2575 public void freeStorage(long freeStorageSize, IntentSender pi) { 2576 try { 2577 mPM.freeStorage(freeStorageSize, pi); 2578 } catch (RemoteException e) { 2579 // Should never happen! 2580 } 2581 } 2582 2583 @Override 2584 public void getPackageSizeInfo(String packageName, 2585 IPackageStatsObserver observer) { 2586 try { 2587 mPM.getPackageSizeInfo(packageName, observer); 2588 } catch (RemoteException e) { 2589 // Should never happen! 2590 } 2591 } 2592 @Override 2593 public void addPackageToPreferred(String packageName) { 2594 try { 2595 mPM.addPackageToPreferred(packageName); 2596 } catch (RemoteException e) { 2597 // Should never happen! 2598 } 2599 } 2600 2601 @Override 2602 public void removePackageFromPreferred(String packageName) { 2603 try { 2604 mPM.removePackageFromPreferred(packageName); 2605 } catch (RemoteException e) { 2606 // Should never happen! 2607 } 2608 } 2609 2610 @Override 2611 public List<PackageInfo> getPreferredPackages(int flags) { 2612 try { 2613 return mPM.getPreferredPackages(flags); 2614 } catch (RemoteException e) { 2615 // Should never happen! 2616 } 2617 return new ArrayList<PackageInfo>(); 2618 } 2619 2620 @Override 2621 public void addPreferredActivity(IntentFilter filter, 2622 int match, ComponentName[] set, ComponentName activity) { 2623 try { 2624 mPM.addPreferredActivity(filter, match, set, activity); 2625 } catch (RemoteException e) { 2626 // Should never happen! 2627 } 2628 } 2629 2630 @Override 2631 public void replacePreferredActivity(IntentFilter filter, 2632 int match, ComponentName[] set, ComponentName activity) { 2633 try { 2634 mPM.replacePreferredActivity(filter, match, set, activity); 2635 } catch (RemoteException e) { 2636 // Should never happen! 2637 } 2638 } 2639 2640 @Override 2641 public void clearPackagePreferredActivities(String packageName) { 2642 try { 2643 mPM.clearPackagePreferredActivities(packageName); 2644 } catch (RemoteException e) { 2645 // Should never happen! 2646 } 2647 } 2648 2649 @Override 2650 public int getPreferredActivities(List<IntentFilter> outFilters, 2651 List<ComponentName> outActivities, String packageName) { 2652 try { 2653 return mPM.getPreferredActivities(outFilters, outActivities, packageName); 2654 } catch (RemoteException e) { 2655 // Should never happen! 2656 } 2657 return 0; 2658 } 2659 2660 @Override 2661 public void setComponentEnabledSetting(ComponentName componentName, 2662 int newState, int flags) { 2663 try { 2664 mPM.setComponentEnabledSetting(componentName, newState, flags); 2665 } catch (RemoteException e) { 2666 // Should never happen! 2667 } 2668 } 2669 2670 @Override 2671 public int getComponentEnabledSetting(ComponentName componentName) { 2672 try { 2673 return mPM.getComponentEnabledSetting(componentName); 2674 } catch (RemoteException e) { 2675 // Should never happen! 2676 } 2677 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2678 } 2679 2680 @Override 2681 public void setApplicationEnabledSetting(String packageName, 2682 int newState, int flags) { 2683 try { 2684 mPM.setApplicationEnabledSetting(packageName, newState, flags); 2685 } catch (RemoteException e) { 2686 // Should never happen! 2687 } 2688 } 2689 2690 @Override 2691 public int getApplicationEnabledSetting(String packageName) { 2692 try { 2693 return mPM.getApplicationEnabledSetting(packageName); 2694 } catch (RemoteException e) { 2695 // Should never happen! 2696 } 2697 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2698 } 2699 2700 @Override 2701 public void setPackageObbPath(String packageName, String path) { 2702 try { 2703 mPM.setPackageObbPath(packageName, path); 2704 } catch (RemoteException e) { 2705 // Should never happen! 2706 } 2707 } 2708 2709 private final ContextImpl mContext; 2710 private final IPackageManager mPM; 2711 2712 private static final Object sSync = new Object(); 2713 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache 2714 = new HashMap<ResourceName, WeakReference<Drawable> >(); 2715 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache 2716 = new HashMap<ResourceName, WeakReference<CharSequence> >(); 2717 } 2718 2719 // ---------------------------------------------------------------------- 2720 // ---------------------------------------------------------------------- 2721 // ---------------------------------------------------------------------- 2722 2723 private static final class SharedPreferencesImpl implements SharedPreferences { 2724 2725 // Lock ordering rules: 2726 // - acquire SharedPreferencesImpl.this before EditorImpl.this 2727 // - acquire mWritingToDiskLock before EditorImpl.this 2728 2729 private final File mFile; 2730 private final File mBackupFile; 2731 private final int mMode; 2732 2733 private Map<String, Object> mMap; // guarded by 'this' 2734 private int mDiskWritesInFlight = 0; // guarded by 'this' 2735 private boolean mLoaded = false; // guarded by 'this' 2736 private long mStatTimestamp; // guarded by 'this' 2737 private long mStatSize; // guarded by 'this' 2738 2739 private final Object mWritingToDiskLock = new Object(); 2740 private static final Object mContent = new Object(); 2741 private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners; 2742 2743 SharedPreferencesImpl( 2744 File file, int mode, Map initialContents) { 2745 mFile = file; 2746 mBackupFile = makeBackupFile(file); 2747 mMode = mode; 2748 mLoaded = initialContents != null; 2749 mMap = initialContents != null ? initialContents : new HashMap<String, Object>(); 2750 FileStatus stat = new FileStatus(); 2751 if (FileUtils.getFileStatus(file.getPath(), stat)) { 2752 mStatTimestamp = stat.mtime; 2753 } 2754 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); 2755 } 2756 2757 // Has this SharedPreferences ever had values assigned to it? 2758 boolean isLoaded() { 2759 synchronized (this) { 2760 return mLoaded; 2761 } 2762 } 2763 2764 // Has the file changed out from under us? i.e. writes that 2765 // we didn't instigate. 2766 public boolean hasFileChangedUnexpectedly() { 2767 synchronized (this) { 2768 if (mDiskWritesInFlight > 0) { 2769 // If we know we caused it, it's not unexpected. 2770 if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected."); 2771 return false; 2772 } 2773 } 2774 FileStatus stat = new FileStatus(); 2775 if (!FileUtils.getFileStatus(mFile.getPath(), stat)) { 2776 return true; 2777 } 2778 synchronized (this) { 2779 return mStatTimestamp != stat.mtime || mStatSize != stat.size; 2780 } 2781 } 2782 2783 /* package */ void replace(Map newContents, FileStatus stat) { 2784 synchronized (this) { 2785 mLoaded = true; 2786 if (newContents != null) { 2787 mMap = newContents; 2788 } 2789 if (stat != null) { 2790 mStatTimestamp = stat.mtime; 2791 mStatSize = stat.size; 2792 } 2793 } 2794 } 2795 2796 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 2797 synchronized(this) { 2798 mListeners.put(listener, mContent); 2799 } 2800 } 2801 2802 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 2803 synchronized(this) { 2804 mListeners.remove(listener); 2805 } 2806 } 2807 2808 public Map<String, ?> getAll() { 2809 synchronized(this) { 2810 //noinspection unchecked 2811 return new HashMap<String, Object>(mMap); 2812 } 2813 } 2814 2815 public String getString(String key, String defValue) { 2816 synchronized (this) { 2817 String v = (String)mMap.get(key); 2818 return v != null ? v : defValue; 2819 } 2820 } 2821 2822 public int getInt(String key, int defValue) { 2823 synchronized (this) { 2824 Integer v = (Integer)mMap.get(key); 2825 return v != null ? v : defValue; 2826 } 2827 } 2828 public long getLong(String key, long defValue) { 2829 synchronized (this) { 2830 Long v = (Long)mMap.get(key); 2831 return v != null ? v : defValue; 2832 } 2833 } 2834 public float getFloat(String key, float defValue) { 2835 synchronized (this) { 2836 Float v = (Float)mMap.get(key); 2837 return v != null ? v : defValue; 2838 } 2839 } 2840 public boolean getBoolean(String key, boolean defValue) { 2841 synchronized (this) { 2842 Boolean v = (Boolean)mMap.get(key); 2843 return v != null ? v : defValue; 2844 } 2845 } 2846 2847 public boolean contains(String key) { 2848 synchronized (this) { 2849 return mMap.containsKey(key); 2850 } 2851 } 2852 2853 public Editor edit() { 2854 return new EditorImpl(); 2855 } 2856 2857 // Return value from EditorImpl#commitToMemory() 2858 private static class MemoryCommitResult { 2859 public boolean changesMade; // any keys different? 2860 public List<String> keysModified; // may be null 2861 public Set<OnSharedPreferenceChangeListener> listeners; // may be null 2862 public Map<?, ?> mapToWriteToDisk; 2863 public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1); 2864 public volatile boolean writeToDiskResult = false; 2865 2866 public void setDiskWriteResult(boolean result) { 2867 writeToDiskResult = result; 2868 writtenToDiskLatch.countDown(); 2869 } 2870 } 2871 2872 public final class EditorImpl implements Editor { 2873 private final Map<String, Object> mModified = Maps.newHashMap(); 2874 private boolean mClear = false; 2875 2876 public Editor putString(String key, String value) { 2877 synchronized (this) { 2878 mModified.put(key, value); 2879 return this; 2880 } 2881 } 2882 public Editor putInt(String key, int value) { 2883 synchronized (this) { 2884 mModified.put(key, value); 2885 return this; 2886 } 2887 } 2888 public Editor putLong(String key, long value) { 2889 synchronized (this) { 2890 mModified.put(key, value); 2891 return this; 2892 } 2893 } 2894 public Editor putFloat(String key, float value) { 2895 synchronized (this) { 2896 mModified.put(key, value); 2897 return this; 2898 } 2899 } 2900 public Editor putBoolean(String key, boolean value) { 2901 synchronized (this) { 2902 mModified.put(key, value); 2903 return this; 2904 } 2905 } 2906 2907 public Editor remove(String key) { 2908 synchronized (this) { 2909 mModified.put(key, this); 2910 return this; 2911 } 2912 } 2913 2914 public Editor clear() { 2915 synchronized (this) { 2916 mClear = true; 2917 return this; 2918 } 2919 } 2920 2921 public void apply() { 2922 final MemoryCommitResult mcr = commitToMemory(); 2923 final Runnable awaitCommit = new Runnable() { 2924 public void run() { 2925 try { 2926 mcr.writtenToDiskLatch.await(); 2927 } catch (InterruptedException ignored) { 2928 } 2929 } 2930 }; 2931 2932 QueuedWork.add(awaitCommit); 2933 2934 Runnable postWriteRunnable = new Runnable() { 2935 public void run() { 2936 awaitCommit.run(); 2937 QueuedWork.remove(awaitCommit); 2938 } 2939 }; 2940 2941 SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable); 2942 2943 // Okay to notify the listeners before it's hit disk 2944 // because the listeners should always get the same 2945 // SharedPreferences instance back, which has the 2946 // changes reflected in memory. 2947 notifyListeners(mcr); 2948 } 2949 2950 // Returns true if any changes were made 2951 private MemoryCommitResult commitToMemory() { 2952 MemoryCommitResult mcr = new MemoryCommitResult(); 2953 synchronized (SharedPreferencesImpl.this) { 2954 // We optimistically don't make a deep copy until 2955 // a memory commit comes in when we're already 2956 // writing to disk. 2957 if (mDiskWritesInFlight > 0) { 2958 // We can't modify our mMap as a currently 2959 // in-flight write owns it. Clone it before 2960 // modifying it. 2961 // noinspection unchecked 2962 mMap = new HashMap<String, Object>(mMap); 2963 } 2964 mcr.mapToWriteToDisk = mMap; 2965 mDiskWritesInFlight++; 2966 2967 boolean hasListeners = mListeners.size() > 0; 2968 if (hasListeners) { 2969 mcr.keysModified = new ArrayList<String>(); 2970 mcr.listeners = 2971 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet()); 2972 } 2973 2974 synchronized (this) { 2975 if (mClear) { 2976 if (!mMap.isEmpty()) { 2977 mcr.changesMade = true; 2978 mMap.clear(); 2979 } 2980 mClear = false; 2981 } 2982 2983 for (Entry<String, Object> e : mModified.entrySet()) { 2984 String k = e.getKey(); 2985 Object v = e.getValue(); 2986 if (v == this) { // magic value for a removal mutation 2987 if (!mMap.containsKey(k)) { 2988 continue; 2989 } 2990 mMap.remove(k); 2991 } else { 2992 boolean isSame = false; 2993 if (mMap.containsKey(k)) { 2994 Object existingValue = mMap.get(k); 2995 if (existingValue != null && existingValue.equals(v)) { 2996 continue; 2997 } 2998 } 2999 mMap.put(k, v); 3000 } 3001 3002 mcr.changesMade = true; 3003 if (hasListeners) { 3004 mcr.keysModified.add(k); 3005 } 3006 } 3007 3008 mModified.clear(); 3009 } 3010 } 3011 return mcr; 3012 } 3013 3014 public boolean commit() { 3015 MemoryCommitResult mcr = commitToMemory(); 3016 SharedPreferencesImpl.this.enqueueDiskWrite( 3017 mcr, null /* sync write on this thread okay */); 3018 try { 3019 mcr.writtenToDiskLatch.await(); 3020 } catch (InterruptedException e) { 3021 return false; 3022 } 3023 notifyListeners(mcr); 3024 return mcr.writeToDiskResult; 3025 } 3026 3027 private void notifyListeners(final MemoryCommitResult mcr) { 3028 if (mcr.listeners == null || mcr.keysModified == null || 3029 mcr.keysModified.size() == 0) { 3030 return; 3031 } 3032 if (Looper.myLooper() == Looper.getMainLooper()) { 3033 for (int i = mcr.keysModified.size() - 1; i >= 0; i--) { 3034 final String key = mcr.keysModified.get(i); 3035 for (OnSharedPreferenceChangeListener listener : mcr.listeners) { 3036 if (listener != null) { 3037 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key); 3038 } 3039 } 3040 } 3041 } else { 3042 // Run this function on the main thread. 3043 ActivityThread.sMainThreadHandler.post(new Runnable() { 3044 public void run() { 3045 notifyListeners(mcr); 3046 } 3047 }); 3048 } 3049 } 3050 } 3051 3052 /** 3053 * Enqueue an already-committed-to-memory result to be written 3054 * to disk. 3055 * 3056 * They will be written to disk one-at-a-time in the order 3057 * that they're enqueued. 3058 * 3059 * @param postWriteRunnable if non-null, we're being called 3060 * from apply() and this is the runnable to run after 3061 * the write proceeds. if null (from a regular commit()), 3062 * then we're allowed to do this disk write on the main 3063 * thread (which in addition to reducing allocations and 3064 * creating a background thread, this has the advantage that 3065 * we catch them in userdebug StrictMode reports to convert 3066 * them where possible to apply() ...) 3067 */ 3068 private void enqueueDiskWrite(final MemoryCommitResult mcr, 3069 final Runnable postWriteRunnable) { 3070 final Runnable writeToDiskRunnable = new Runnable() { 3071 public void run() { 3072 synchronized (mWritingToDiskLock) { 3073 writeToFile(mcr); 3074 } 3075 synchronized (SharedPreferencesImpl.this) { 3076 mDiskWritesInFlight--; 3077 } 3078 if (postWriteRunnable != null) { 3079 postWriteRunnable.run(); 3080 } 3081 } 3082 }; 3083 3084 final boolean isFromSyncCommit = (postWriteRunnable == null); 3085 3086 // Typical #commit() path with fewer allocations, doing a write on 3087 // the current thread. 3088 if (isFromSyncCommit) { 3089 boolean wasEmpty = false; 3090 synchronized (SharedPreferencesImpl.this) { 3091 wasEmpty = mDiskWritesInFlight == 1; 3092 } 3093 if (wasEmpty) { 3094 writeToDiskRunnable.run(); 3095 return; 3096 } 3097 } 3098 3099 QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable); 3100 } 3101 3102 private static FileOutputStream createFileOutputStream(File file) { 3103 FileOutputStream str = null; 3104 try { 3105 str = new FileOutputStream(file); 3106 } catch (FileNotFoundException e) { 3107 File parent = file.getParentFile(); 3108 if (!parent.mkdir()) { 3109 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file); 3110 return null; 3111 } 3112 FileUtils.setPermissions( 3113 parent.getPath(), 3114 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 3115 -1, -1); 3116 try { 3117 str = new FileOutputStream(file); 3118 } catch (FileNotFoundException e2) { 3119 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2); 3120 } 3121 } 3122 return str; 3123 } 3124 3125 // Note: must hold mWritingToDiskLock 3126 private void writeToFile(MemoryCommitResult mcr) { 3127 // Rename the current file so it may be used as a backup during the next read 3128 if (mFile.exists()) { 3129 if (!mcr.changesMade) { 3130 // If the file already exists, but no changes were 3131 // made to the underlying map, it's wasteful to 3132 // re-write the file. Return as if we wrote it 3133 // out. 3134 mcr.setDiskWriteResult(true); 3135 return; 3136 } 3137 if (!mBackupFile.exists()) { 3138 if (!mFile.renameTo(mBackupFile)) { 3139 Log.e(TAG, "Couldn't rename file " + mFile 3140 + " to backup file " + mBackupFile); 3141 mcr.setDiskWriteResult(false); 3142 return; 3143 } 3144 } else { 3145 mFile.delete(); 3146 } 3147 } 3148 3149 // Attempt to write the file, delete the backup and return true as atomically as 3150 // possible. If any exception occurs, delete the new file; next time we will restore 3151 // from the backup. 3152 try { 3153 FileOutputStream str = createFileOutputStream(mFile); 3154 if (str == null) { 3155 mcr.setDiskWriteResult(false); 3156 return; 3157 } 3158 XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str); 3159 FileUtils.sync(str); 3160 str.close(); 3161 setFilePermissionsFromMode(mFile.getPath(), mMode, 0); 3162 FileStatus stat = new FileStatus(); 3163 if (FileUtils.getFileStatus(mFile.getPath(), stat)) { 3164 synchronized (this) { 3165 mStatTimestamp = stat.mtime; 3166 mStatSize = stat.size; 3167 } 3168 } 3169 // Writing was successful, delete the backup file if there is one. 3170 mBackupFile.delete(); 3171 mcr.setDiskWriteResult(true); 3172 return; 3173 } catch (XmlPullParserException e) { 3174 Log.w(TAG, "writeToFile: Got exception:", e); 3175 } catch (IOException e) { 3176 Log.w(TAG, "writeToFile: Got exception:", e); 3177 } 3178 // Clean up an unsuccessfully written file 3179 if (mFile.exists()) { 3180 if (!mFile.delete()) { 3181 Log.e(TAG, "Couldn't clean up partially-written file " + mFile); 3182 } 3183 } 3184 mcr.setDiskWriteResult(false); 3185 } 3186 } 3187} 3188