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