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