ContextImpl.java revision ec062f63a2f5fb49f825544da348e594dbf5bf3c
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.android.internal.os.IDropBoxManagerService; 107 108import java.io.File; 109import java.io.FileInputStream; 110import java.io.FileNotFoundException; 111import java.io.FileOutputStream; 112import java.io.IOException; 113import java.io.InputStream; 114import java.lang.ref.WeakReference; 115import java.util.ArrayList; 116import java.util.HashMap; 117import java.util.HashSet; 118import java.util.Iterator; 119import java.util.List; 120import java.util.Map; 121import java.util.Map.Entry; 122import java.util.Set; 123import java.util.WeakHashMap; 124import java.util.concurrent.CountDownLatch; 125import java.util.concurrent.ExecutorService; 126 127class ReceiverRestrictedContext extends ContextWrapper { 128 ReceiverRestrictedContext(Context base) { 129 super(base); 130 } 131 132 @Override 133 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 134 return registerReceiver(receiver, filter, null, null); 135 } 136 137 @Override 138 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 139 String broadcastPermission, Handler scheduler) { 140 throw new ReceiverCallNotAllowedException( 141 "IntentReceiver components are not allowed to register to receive intents"); 142 //ex.fillInStackTrace(); 143 //Log.e("IntentReceiver", ex.getMessage(), ex); 144 //return mContext.registerReceiver(receiver, filter, broadcastPermission, 145 // scheduler); 146 } 147 148 @Override 149 public boolean bindService(Intent service, ServiceConnection conn, int flags) { 150 throw new ReceiverCallNotAllowedException( 151 "IntentReceiver components are not allowed to bind to services"); 152 //ex.fillInStackTrace(); 153 //Log.e("IntentReceiver", ex.getMessage(), ex); 154 //return mContext.bindService(service, interfaceName, conn, flags); 155 } 156} 157 158/** 159 * Common implementation of Context API, which provides the base 160 * context object for Activity and other application components. 161 */ 162class ContextImpl extends Context { 163 private final static String TAG = "ApplicationContext"; 164 private final static boolean DEBUG = false; 165 private final static boolean DEBUG_ICONS = false; 166 167 private static final Object sSync = new Object(); 168 private static AlarmManager sAlarmManager; 169 private static PowerManager sPowerManager; 170 private static ConnectivityManager sConnectivityManager; 171 private static ThrottleManager sThrottleManager; 172 private static WifiManager sWifiManager; 173 private static LocationManager sLocationManager; 174 private static CountryDetector sCountryDetector; 175 private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs = 176 new HashMap<String, SharedPreferencesImpl>(); 177 178 private AudioManager mAudioManager; 179 /*package*/ LoadedApk mPackageInfo; 180 private Resources mResources; 181 /*package*/ ActivityThread mMainThread; 182 private Context mOuterContext; 183 private IBinder mActivityToken = null; 184 private ApplicationContentResolver mContentResolver; 185 private int mThemeResource = 0; 186 private Resources.Theme mTheme = null; 187 private PackageManager mPackageManager; 188 private NotificationManager mNotificationManager = null; 189 private ActivityManager mActivityManager = null; 190 private WallpaperManager mWallpaperManager = null; 191 private Context mReceiverRestrictedContext = null; 192 private SearchManager mSearchManager = null; 193 private SensorManager mSensorManager = null; 194 private StorageManager mStorageManager = null; 195 private Vibrator mVibrator = null; 196 private LayoutInflater mLayoutInflater = null; 197 private StatusBarManager mStatusBarManager = null; 198 private TelephonyManager mTelephonyManager = null; 199 private ClipboardManager mClipboardManager = null; 200 private boolean mRestricted; 201 private AccountManager mAccountManager; // protected by mSync 202 private DropBoxManager mDropBoxManager = null; 203 private DevicePolicyManager mDevicePolicyManager = null; 204 private UiModeManager mUiModeManager = null; 205 private DownloadManager mDownloadManager = null; 206 207 private final Object mSync = new Object(); 208 209 private File mDatabasesDir; 210 private File mPreferencesDir; 211 private File mFilesDir; 212 private File mCacheDir; 213 private File mExternalFilesDir; 214 private File mExternalCacheDir; 215 216 private static final String[] EMPTY_FILE_LIST = {}; 217 218 @Override 219 public AssetManager getAssets() { 220 return mResources.getAssets(); 221 } 222 223 @Override 224 public Resources getResources() { 225 return mResources; 226 } 227 228 @Override 229 public PackageManager getPackageManager() { 230 if (mPackageManager != null) { 231 return mPackageManager; 232 } 233 234 IPackageManager pm = ActivityThread.getPackageManager(); 235 if (pm != null) { 236 // Doesn't matter if we make more than one instance. 237 return (mPackageManager = new ApplicationPackageManager(this, pm)); 238 } 239 240 return null; 241 } 242 243 @Override 244 public ContentResolver getContentResolver() { 245 return mContentResolver; 246 } 247 248 @Override 249 public Looper getMainLooper() { 250 return mMainThread.getLooper(); 251 } 252 253 @Override 254 public Context getApplicationContext() { 255 return (mPackageInfo != null) ? 256 mPackageInfo.getApplication() : mMainThread.getApplication(); 257 } 258 259 @Override 260 public void setTheme(int resid) { 261 mThemeResource = resid; 262 } 263 264 @Override 265 public Resources.Theme getTheme() { 266 if (mTheme == null) { 267 if (mThemeResource == 0) { 268 final Context outerContext = getOuterContext(); 269 mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion 270 >= Build.VERSION_CODES.HONEYCOMB) 271 ? com.android.internal.R.style.Theme_Holo 272 : 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 (DROPBOX_SERVICE.equals(name)) { 975 return getDropBoxManager(); 976 } else if (DEVICE_POLICY_SERVICE.equals(name)) { 977 return getDevicePolicyManager(); 978 } else if (UI_MODE_SERVICE.equals(name)) { 979 return getUiModeManager(); 980 } else if (DOWNLOAD_SERVICE.equals(name)) { 981 return getDownloadManager(); 982 } 983 984 return null; 985 } 986 987 private AccountManager getAccountManager() { 988 synchronized (mSync) { 989 if (mAccountManager == null) { 990 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE); 991 IAccountManager service = IAccountManager.Stub.asInterface(b); 992 mAccountManager = new AccountManager(this, service); 993 } 994 return mAccountManager; 995 } 996 } 997 998 private ActivityManager getActivityManager() { 999 synchronized (mSync) { 1000 if (mActivityManager == null) { 1001 mActivityManager = new ActivityManager(getOuterContext(), 1002 mMainThread.getHandler()); 1003 } 1004 } 1005 return mActivityManager; 1006 } 1007 1008 private AlarmManager getAlarmManager() { 1009 synchronized (sSync) { 1010 if (sAlarmManager == null) { 1011 IBinder b = ServiceManager.getService(ALARM_SERVICE); 1012 IAlarmManager service = IAlarmManager.Stub.asInterface(b); 1013 sAlarmManager = new AlarmManager(service); 1014 } 1015 } 1016 return sAlarmManager; 1017 } 1018 1019 private PowerManager getPowerManager() { 1020 synchronized (sSync) { 1021 if (sPowerManager == null) { 1022 IBinder b = ServiceManager.getService(POWER_SERVICE); 1023 IPowerManager service = IPowerManager.Stub.asInterface(b); 1024 sPowerManager = new PowerManager(service, mMainThread.getHandler()); 1025 } 1026 } 1027 return sPowerManager; 1028 } 1029 1030 private ConnectivityManager getConnectivityManager() 1031 { 1032 synchronized (sSync) { 1033 if (sConnectivityManager == null) { 1034 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE); 1035 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 1036 sConnectivityManager = new ConnectivityManager(service); 1037 } 1038 } 1039 return sConnectivityManager; 1040 } 1041 1042 private ThrottleManager getThrottleManager() 1043 { 1044 synchronized (sSync) { 1045 if (sThrottleManager == null) { 1046 IBinder b = ServiceManager.getService(THROTTLE_SERVICE); 1047 IThrottleManager service = IThrottleManager.Stub.asInterface(b); 1048 sThrottleManager = new ThrottleManager(service); 1049 } 1050 } 1051 return sThrottleManager; 1052 } 1053 1054 private WifiManager getWifiManager() 1055 { 1056 synchronized (sSync) { 1057 if (sWifiManager == null) { 1058 IBinder b = ServiceManager.getService(WIFI_SERVICE); 1059 IWifiManager service = IWifiManager.Stub.asInterface(b); 1060 sWifiManager = new WifiManager(service, mMainThread.getHandler()); 1061 } 1062 } 1063 return sWifiManager; 1064 } 1065 1066 private NotificationManager getNotificationManager() { 1067 synchronized (mSync) { 1068 if (mNotificationManager == null) { 1069 final Context outerContext = getOuterContext(); 1070 mNotificationManager = new NotificationManager( 1071 new ContextThemeWrapper(outerContext, 1072 outerContext.getApplicationInfo().targetSdkVersion >= 1073 Build.VERSION_CODES.HONEYCOMB 1074 ? com.android.internal.R.style.Theme_Holo_Dialog 1075 : com.android.internal.R.style.Theme_Dialog), 1076 mMainThread.getHandler()); 1077 } 1078 } 1079 return mNotificationManager; 1080 } 1081 1082 private WallpaperManager getWallpaperManager() { 1083 synchronized (mSync) { 1084 if (mWallpaperManager == null) { 1085 mWallpaperManager = new WallpaperManager(getOuterContext(), 1086 mMainThread.getHandler()); 1087 } 1088 } 1089 return mWallpaperManager; 1090 } 1091 1092 private TelephonyManager getTelephonyManager() { 1093 synchronized (mSync) { 1094 if (mTelephonyManager == null) { 1095 mTelephonyManager = new TelephonyManager(getOuterContext()); 1096 } 1097 } 1098 return mTelephonyManager; 1099 } 1100 1101 private ClipboardManager getClipboardManager() { 1102 synchronized (mSync) { 1103 if (mClipboardManager == null) { 1104 mClipboardManager = new ClipboardManager(getOuterContext(), 1105 mMainThread.getHandler()); 1106 } 1107 } 1108 return mClipboardManager; 1109 } 1110 1111 private LocationManager getLocationManager() { 1112 synchronized (sSync) { 1113 if (sLocationManager == null) { 1114 IBinder b = ServiceManager.getService(LOCATION_SERVICE); 1115 ILocationManager service = ILocationManager.Stub.asInterface(b); 1116 sLocationManager = new LocationManager(service); 1117 } 1118 } 1119 return sLocationManager; 1120 } 1121 1122 private CountryDetector getCountryDetector() { 1123 synchronized (sSync) { 1124 if (sCountryDetector == null) { 1125 IBinder b = ServiceManager.getService(COUNTRY_DETECTOR); 1126 ICountryDetector service = ICountryDetector.Stub.asInterface(b); 1127 sCountryDetector = new CountryDetector(service); 1128 } 1129 } 1130 return sCountryDetector; 1131 } 1132 1133 private SearchManager getSearchManager() { 1134 synchronized (mSync) { 1135 if (mSearchManager == null) { 1136 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler()); 1137 } 1138 } 1139 return mSearchManager; 1140 } 1141 1142 private SensorManager getSensorManager() { 1143 synchronized (mSync) { 1144 if (mSensorManager == null) { 1145 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper()); 1146 } 1147 } 1148 return mSensorManager; 1149 } 1150 1151 private StorageManager getStorageManager() { 1152 synchronized (mSync) { 1153 if (mStorageManager == null) { 1154 try { 1155 mStorageManager = new StorageManager(mMainThread.getHandler().getLooper()); 1156 } catch (RemoteException rex) { 1157 Log.e(TAG, "Failed to create StorageManager", rex); 1158 mStorageManager = null; 1159 } 1160 } 1161 } 1162 return mStorageManager; 1163 } 1164 1165 private Vibrator getVibrator() { 1166 synchronized (mSync) { 1167 if (mVibrator == null) { 1168 mVibrator = new Vibrator(); 1169 } 1170 } 1171 return mVibrator; 1172 } 1173 1174 private AudioManager getAudioManager() 1175 { 1176 if (mAudioManager == null) { 1177 mAudioManager = new AudioManager(this); 1178 } 1179 return mAudioManager; 1180 } 1181 1182 /* package */ static DropBoxManager createDropBoxManager() { 1183 IBinder b = ServiceManager.getService(DROPBOX_SERVICE); 1184 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b); 1185 if (service == null) { 1186 // Don't return a DropBoxManager that will NPE upon use. 1187 // This also avoids caching a broken DropBoxManager in 1188 // getDropBoxManager during early boot, before the 1189 // DROPBOX_SERVICE is registered. 1190 return null; 1191 } 1192 return new DropBoxManager(service); 1193 } 1194 1195 private DropBoxManager getDropBoxManager() { 1196 synchronized (mSync) { 1197 if (mDropBoxManager == null) { 1198 mDropBoxManager = createDropBoxManager(); 1199 } 1200 } 1201 return mDropBoxManager; 1202 } 1203 1204 private DevicePolicyManager getDevicePolicyManager() { 1205 synchronized (mSync) { 1206 if (mDevicePolicyManager == null) { 1207 mDevicePolicyManager = DevicePolicyManager.create(this, 1208 mMainThread.getHandler()); 1209 } 1210 } 1211 return mDevicePolicyManager; 1212 } 1213 1214 private UiModeManager getUiModeManager() { 1215 synchronized (mSync) { 1216 if (mUiModeManager == null) { 1217 mUiModeManager = new UiModeManager(); 1218 } 1219 } 1220 return mUiModeManager; 1221 } 1222 1223 private DownloadManager getDownloadManager() { 1224 synchronized (mSync) { 1225 if (mDownloadManager == null) { 1226 mDownloadManager = new DownloadManager(getContentResolver(), getPackageName()); 1227 } 1228 } 1229 return mDownloadManager; 1230 } 1231 1232 @Override 1233 public int checkPermission(String permission, int pid, int uid) { 1234 if (permission == null) { 1235 throw new IllegalArgumentException("permission is null"); 1236 } 1237 1238 if (!Process.supportsProcesses()) { 1239 return PackageManager.PERMISSION_GRANTED; 1240 } 1241 try { 1242 return ActivityManagerNative.getDefault().checkPermission( 1243 permission, pid, uid); 1244 } catch (RemoteException e) { 1245 return PackageManager.PERMISSION_DENIED; 1246 } 1247 } 1248 1249 @Override 1250 public int checkCallingPermission(String permission) { 1251 if (permission == null) { 1252 throw new IllegalArgumentException("permission is null"); 1253 } 1254 1255 if (!Process.supportsProcesses()) { 1256 return PackageManager.PERMISSION_GRANTED; 1257 } 1258 int pid = Binder.getCallingPid(); 1259 if (pid != Process.myPid()) { 1260 return checkPermission(permission, pid, 1261 Binder.getCallingUid()); 1262 } 1263 return PackageManager.PERMISSION_DENIED; 1264 } 1265 1266 @Override 1267 public int checkCallingOrSelfPermission(String permission) { 1268 if (permission == null) { 1269 throw new IllegalArgumentException("permission is null"); 1270 } 1271 1272 return checkPermission(permission, Binder.getCallingPid(), 1273 Binder.getCallingUid()); 1274 } 1275 1276 private void enforce( 1277 String permission, int resultOfCheck, 1278 boolean selfToo, int uid, String message) { 1279 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { 1280 throw new SecurityException( 1281 (message != null ? (message + ": ") : "") + 1282 (selfToo 1283 ? "Neither user " + uid + " nor current process has " 1284 : "User " + uid + " does not have ") + 1285 permission + 1286 "."); 1287 } 1288 } 1289 1290 public void enforcePermission( 1291 String permission, int pid, int uid, String message) { 1292 enforce(permission, 1293 checkPermission(permission, pid, uid), 1294 false, 1295 uid, 1296 message); 1297 } 1298 1299 public void enforceCallingPermission(String permission, String message) { 1300 enforce(permission, 1301 checkCallingPermission(permission), 1302 false, 1303 Binder.getCallingUid(), 1304 message); 1305 } 1306 1307 public void enforceCallingOrSelfPermission( 1308 String permission, String message) { 1309 enforce(permission, 1310 checkCallingOrSelfPermission(permission), 1311 true, 1312 Binder.getCallingUid(), 1313 message); 1314 } 1315 1316 @Override 1317 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) { 1318 try { 1319 ActivityManagerNative.getDefault().grantUriPermission( 1320 mMainThread.getApplicationThread(), toPackage, uri, 1321 modeFlags); 1322 } catch (RemoteException e) { 1323 } 1324 } 1325 1326 @Override 1327 public void revokeUriPermission(Uri uri, int modeFlags) { 1328 try { 1329 ActivityManagerNative.getDefault().revokeUriPermission( 1330 mMainThread.getApplicationThread(), uri, 1331 modeFlags); 1332 } catch (RemoteException e) { 1333 } 1334 } 1335 1336 @Override 1337 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { 1338 if (!Process.supportsProcesses()) { 1339 return PackageManager.PERMISSION_GRANTED; 1340 } 1341 try { 1342 return ActivityManagerNative.getDefault().checkUriPermission( 1343 uri, pid, uid, modeFlags); 1344 } catch (RemoteException e) { 1345 return PackageManager.PERMISSION_DENIED; 1346 } 1347 } 1348 1349 @Override 1350 public int checkCallingUriPermission(Uri uri, int modeFlags) { 1351 if (!Process.supportsProcesses()) { 1352 return PackageManager.PERMISSION_GRANTED; 1353 } 1354 int pid = Binder.getCallingPid(); 1355 if (pid != Process.myPid()) { 1356 return checkUriPermission(uri, pid, 1357 Binder.getCallingUid(), modeFlags); 1358 } 1359 return PackageManager.PERMISSION_DENIED; 1360 } 1361 1362 @Override 1363 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { 1364 return checkUriPermission(uri, Binder.getCallingPid(), 1365 Binder.getCallingUid(), modeFlags); 1366 } 1367 1368 @Override 1369 public int checkUriPermission(Uri uri, String readPermission, 1370 String writePermission, int pid, int uid, int modeFlags) { 1371 if (DEBUG) { 1372 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission=" 1373 + readPermission + " writePermission=" + writePermission 1374 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags); 1375 } 1376 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { 1377 if (readPermission == null 1378 || checkPermission(readPermission, pid, uid) 1379 == PackageManager.PERMISSION_GRANTED) { 1380 return PackageManager.PERMISSION_GRANTED; 1381 } 1382 } 1383 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { 1384 if (writePermission == null 1385 || checkPermission(writePermission, pid, uid) 1386 == PackageManager.PERMISSION_GRANTED) { 1387 return PackageManager.PERMISSION_GRANTED; 1388 } 1389 } 1390 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags) 1391 : PackageManager.PERMISSION_DENIED; 1392 } 1393 1394 private String uriModeFlagToString(int uriModeFlags) { 1395 switch (uriModeFlags) { 1396 case Intent.FLAG_GRANT_READ_URI_PERMISSION | 1397 Intent.FLAG_GRANT_WRITE_URI_PERMISSION: 1398 return "read and write"; 1399 case Intent.FLAG_GRANT_READ_URI_PERMISSION: 1400 return "read"; 1401 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION: 1402 return "write"; 1403 } 1404 throw new IllegalArgumentException( 1405 "Unknown permission mode flags: " + uriModeFlags); 1406 } 1407 1408 private void enforceForUri( 1409 int modeFlags, int resultOfCheck, boolean selfToo, 1410 int uid, Uri uri, String message) { 1411 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { 1412 throw new SecurityException( 1413 (message != null ? (message + ": ") : "") + 1414 (selfToo 1415 ? "Neither user " + uid + " nor current process has " 1416 : "User " + uid + " does not have ") + 1417 uriModeFlagToString(modeFlags) + 1418 " permission on " + 1419 uri + 1420 "."); 1421 } 1422 } 1423 1424 public void enforceUriPermission( 1425 Uri uri, int pid, int uid, int modeFlags, String message) { 1426 enforceForUri( 1427 modeFlags, checkUriPermission(uri, pid, uid, modeFlags), 1428 false, uid, uri, message); 1429 } 1430 1431 public void enforceCallingUriPermission( 1432 Uri uri, int modeFlags, String message) { 1433 enforceForUri( 1434 modeFlags, checkCallingUriPermission(uri, modeFlags), 1435 false, Binder.getCallingUid(), uri, message); 1436 } 1437 1438 public void enforceCallingOrSelfUriPermission( 1439 Uri uri, int modeFlags, String message) { 1440 enforceForUri( 1441 modeFlags, 1442 checkCallingOrSelfUriPermission(uri, modeFlags), true, 1443 Binder.getCallingUid(), uri, message); 1444 } 1445 1446 public void enforceUriPermission( 1447 Uri uri, String readPermission, String writePermission, 1448 int pid, int uid, int modeFlags, String message) { 1449 enforceForUri(modeFlags, 1450 checkUriPermission( 1451 uri, readPermission, writePermission, pid, uid, 1452 modeFlags), 1453 false, 1454 uid, 1455 uri, 1456 message); 1457 } 1458 1459 @Override 1460 public Context createPackageContext(String packageName, int flags) 1461 throws PackageManager.NameNotFoundException { 1462 if (packageName.equals("system") || packageName.equals("android")) { 1463 return new ContextImpl(mMainThread.getSystemContext()); 1464 } 1465 1466 LoadedApk pi = 1467 mMainThread.getPackageInfo(packageName, flags); 1468 if (pi != null) { 1469 ContextImpl c = new ContextImpl(); 1470 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; 1471 c.init(pi, null, mMainThread, mResources); 1472 if (c.mResources != null) { 1473 return c; 1474 } 1475 } 1476 1477 // Should be a better exception. 1478 throw new PackageManager.NameNotFoundException( 1479 "Application package " + packageName + " not found"); 1480 } 1481 1482 @Override 1483 public boolean isRestricted() { 1484 return mRestricted; 1485 } 1486 1487 private File getDataDirFile() { 1488 if (mPackageInfo != null) { 1489 return mPackageInfo.getDataDirFile(); 1490 } 1491 throw new RuntimeException("Not supported in system context"); 1492 } 1493 1494 @Override 1495 public File getDir(String name, int mode) { 1496 name = "app_" + name; 1497 File file = makeFilename(getDataDirFile(), name); 1498 if (!file.exists()) { 1499 file.mkdir(); 1500 setFilePermissionsFromMode(file.getPath(), mode, 1501 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH); 1502 } 1503 return file; 1504 } 1505 1506 static ContextImpl createSystemContext(ActivityThread mainThread) { 1507 ContextImpl context = new ContextImpl(); 1508 context.init(Resources.getSystem(), mainThread); 1509 return context; 1510 } 1511 1512 ContextImpl() { 1513 mOuterContext = this; 1514 } 1515 1516 /** 1517 * Create a new ApplicationContext from an existing one. The new one 1518 * works and operates the same as the one it is copying. 1519 * 1520 * @param context Existing application context. 1521 */ 1522 public ContextImpl(ContextImpl context) { 1523 mPackageInfo = context.mPackageInfo; 1524 mResources = context.mResources; 1525 mMainThread = context.mMainThread; 1526 mContentResolver = context.mContentResolver; 1527 mOuterContext = this; 1528 } 1529 1530 final void init(LoadedApk packageInfo, 1531 IBinder activityToken, ActivityThread mainThread) { 1532 init(packageInfo, activityToken, mainThread, null); 1533 } 1534 1535 final void init(LoadedApk packageInfo, 1536 IBinder activityToken, ActivityThread mainThread, 1537 Resources container) { 1538 mPackageInfo = packageInfo; 1539 mResources = mPackageInfo.getResources(mainThread); 1540 1541 if (mResources != null && container != null 1542 && container.getCompatibilityInfo().applicationScale != 1543 mResources.getCompatibilityInfo().applicationScale) { 1544 if (DEBUG) { 1545 Log.d(TAG, "loaded context has different scaling. Using container's" + 1546 " compatiblity info:" + container.getDisplayMetrics()); 1547 } 1548 mResources = mainThread.getTopLevelResources( 1549 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy()); 1550 } 1551 mMainThread = mainThread; 1552 mContentResolver = new ApplicationContentResolver(this, mainThread); 1553 1554 setActivityToken(activityToken); 1555 } 1556 1557 final void init(Resources resources, ActivityThread mainThread) { 1558 mPackageInfo = null; 1559 mResources = resources; 1560 mMainThread = mainThread; 1561 mContentResolver = new ApplicationContentResolver(this, mainThread); 1562 } 1563 1564 final void scheduleFinalCleanup(String who, String what) { 1565 mMainThread.scheduleContextCleanup(this, who, what); 1566 } 1567 1568 final void performFinalCleanup(String who, String what) { 1569 //Log.i(TAG, "Cleanup up context: " + this); 1570 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what); 1571 } 1572 1573 final Context getReceiverRestrictedContext() { 1574 if (mReceiverRestrictedContext != null) { 1575 return mReceiverRestrictedContext; 1576 } 1577 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext()); 1578 } 1579 1580 final void setActivityToken(IBinder token) { 1581 mActivityToken = token; 1582 } 1583 1584 final void setOuterContext(Context context) { 1585 mOuterContext = context; 1586 } 1587 1588 final Context getOuterContext() { 1589 return mOuterContext; 1590 } 1591 1592 final IBinder getActivityToken() { 1593 return mActivityToken; 1594 } 1595 1596 private static void setFilePermissionsFromMode(String name, int mode, 1597 int extraPermissions) { 1598 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR 1599 |FileUtils.S_IRGRP|FileUtils.S_IWGRP 1600 |extraPermissions; 1601 if ((mode&MODE_WORLD_READABLE) != 0) { 1602 perms |= FileUtils.S_IROTH; 1603 } 1604 if ((mode&MODE_WORLD_WRITEABLE) != 0) { 1605 perms |= FileUtils.S_IWOTH; 1606 } 1607 if (DEBUG) { 1608 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode) 1609 + ", perms=0x" + Integer.toHexString(perms)); 1610 } 1611 FileUtils.setPermissions(name, perms, -1, -1); 1612 } 1613 1614 private File validateFilePath(String name, boolean createDirectory) { 1615 File dir; 1616 File f; 1617 1618 if (name.charAt(0) == File.separatorChar) { 1619 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar)); 1620 dir = new File(dirPath); 1621 name = name.substring(name.lastIndexOf(File.separatorChar)); 1622 f = new File(dir, name); 1623 } else { 1624 dir = getDatabasesDir(); 1625 f = makeFilename(dir, name); 1626 } 1627 1628 if (createDirectory && !dir.isDirectory() && dir.mkdir()) { 1629 FileUtils.setPermissions(dir.getPath(), 1630 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 1631 -1, -1); 1632 } 1633 1634 return f; 1635 } 1636 1637 private File makeFilename(File base, String name) { 1638 if (name.indexOf(File.separatorChar) < 0) { 1639 return new File(base, name); 1640 } 1641 throw new IllegalArgumentException( 1642 "File " + name + " contains a path separator"); 1643 } 1644 1645 // ---------------------------------------------------------------------- 1646 // ---------------------------------------------------------------------- 1647 // ---------------------------------------------------------------------- 1648 1649 private static final class ApplicationContentResolver extends ContentResolver { 1650 public ApplicationContentResolver(Context context, ActivityThread mainThread) { 1651 super(context); 1652 mMainThread = mainThread; 1653 } 1654 1655 @Override 1656 protected IContentProvider acquireProvider(Context context, String name) { 1657 return mMainThread.acquireProvider(context, name); 1658 } 1659 1660 @Override 1661 protected IContentProvider acquireExistingProvider(Context context, String name) { 1662 return mMainThread.acquireExistingProvider(context, name); 1663 } 1664 1665 @Override 1666 public boolean releaseProvider(IContentProvider provider) { 1667 return mMainThread.releaseProvider(provider); 1668 } 1669 1670 private final ActivityThread mMainThread; 1671 } 1672 1673 // ---------------------------------------------------------------------- 1674 // ---------------------------------------------------------------------- 1675 // ---------------------------------------------------------------------- 1676 1677 /*package*/ 1678 static final class ApplicationPackageManager extends PackageManager { 1679 @Override 1680 public PackageInfo getPackageInfo(String packageName, int flags) 1681 throws NameNotFoundException { 1682 try { 1683 PackageInfo pi = mPM.getPackageInfo(packageName, flags); 1684 if (pi != null) { 1685 return pi; 1686 } 1687 } catch (RemoteException e) { 1688 throw new RuntimeException("Package manager has died", e); 1689 } 1690 1691 throw new NameNotFoundException(packageName); 1692 } 1693 1694 @Override 1695 public String[] currentToCanonicalPackageNames(String[] names) { 1696 try { 1697 return mPM.currentToCanonicalPackageNames(names); 1698 } catch (RemoteException e) { 1699 throw new RuntimeException("Package manager has died", e); 1700 } 1701 } 1702 1703 @Override 1704 public String[] canonicalToCurrentPackageNames(String[] names) { 1705 try { 1706 return mPM.canonicalToCurrentPackageNames(names); 1707 } catch (RemoteException e) { 1708 throw new RuntimeException("Package manager has died", e); 1709 } 1710 } 1711 1712 @Override 1713 public Intent getLaunchIntentForPackage(String packageName) { 1714 // First see if the package has an INFO activity; the existence of 1715 // such an activity is implied to be the desired front-door for the 1716 // overall package (such as if it has multiple launcher entries). 1717 Intent intentToResolve = new Intent(Intent.ACTION_MAIN); 1718 intentToResolve.addCategory(Intent.CATEGORY_INFO); 1719 intentToResolve.setPackage(packageName); 1720 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0); 1721 1722 // Otherwise, try to find a main launcher activity. 1723 if (resolveInfo == null) { 1724 // reuse the intent instance 1725 intentToResolve.removeCategory(Intent.CATEGORY_INFO); 1726 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); 1727 intentToResolve.setPackage(packageName); 1728 resolveInfo = resolveActivity(intentToResolve, 0); 1729 } 1730 if (resolveInfo == null) { 1731 return null; 1732 } 1733 Intent intent = new Intent(intentToResolve); 1734 intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName, 1735 resolveInfo.activityInfo.name); 1736 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1737 return intent; 1738 } 1739 1740 @Override 1741 public int[] getPackageGids(String packageName) 1742 throws NameNotFoundException { 1743 try { 1744 int[] gids = mPM.getPackageGids(packageName); 1745 if (gids == null || gids.length > 0) { 1746 return gids; 1747 } 1748 } catch (RemoteException e) { 1749 throw new RuntimeException("Package manager has died", e); 1750 } 1751 1752 throw new NameNotFoundException(packageName); 1753 } 1754 1755 @Override 1756 public PermissionInfo getPermissionInfo(String name, int flags) 1757 throws NameNotFoundException { 1758 try { 1759 PermissionInfo pi = mPM.getPermissionInfo(name, flags); 1760 if (pi != null) { 1761 return pi; 1762 } 1763 } catch (RemoteException e) { 1764 throw new RuntimeException("Package manager has died", e); 1765 } 1766 1767 throw new NameNotFoundException(name); 1768 } 1769 1770 @Override 1771 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags) 1772 throws NameNotFoundException { 1773 try { 1774 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags); 1775 if (pi != null) { 1776 return pi; 1777 } 1778 } catch (RemoteException e) { 1779 throw new RuntimeException("Package manager has died", e); 1780 } 1781 1782 throw new NameNotFoundException(group); 1783 } 1784 1785 @Override 1786 public PermissionGroupInfo getPermissionGroupInfo(String name, 1787 int flags) throws NameNotFoundException { 1788 try { 1789 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags); 1790 if (pgi != null) { 1791 return pgi; 1792 } 1793 } catch (RemoteException e) { 1794 throw new RuntimeException("Package manager has died", e); 1795 } 1796 1797 throw new NameNotFoundException(name); 1798 } 1799 1800 @Override 1801 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { 1802 try { 1803 return mPM.getAllPermissionGroups(flags); 1804 } catch (RemoteException e) { 1805 throw new RuntimeException("Package manager has died", e); 1806 } 1807 } 1808 1809 @Override 1810 public ApplicationInfo getApplicationInfo(String packageName, int flags) 1811 throws NameNotFoundException { 1812 try { 1813 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags); 1814 if (ai != null) { 1815 return ai; 1816 } 1817 } catch (RemoteException e) { 1818 throw new RuntimeException("Package manager has died", e); 1819 } 1820 1821 throw new NameNotFoundException(packageName); 1822 } 1823 1824 @Override 1825 public ActivityInfo getActivityInfo(ComponentName className, int flags) 1826 throws NameNotFoundException { 1827 try { 1828 ActivityInfo ai = mPM.getActivityInfo(className, flags); 1829 if (ai != null) { 1830 return ai; 1831 } 1832 } catch (RemoteException e) { 1833 throw new RuntimeException("Package manager has died", e); 1834 } 1835 1836 throw new NameNotFoundException(className.toString()); 1837 } 1838 1839 @Override 1840 public ActivityInfo getReceiverInfo(ComponentName className, int flags) 1841 throws NameNotFoundException { 1842 try { 1843 ActivityInfo ai = mPM.getReceiverInfo(className, flags); 1844 if (ai != null) { 1845 return ai; 1846 } 1847 } catch (RemoteException e) { 1848 throw new RuntimeException("Package manager has died", e); 1849 } 1850 1851 throw new NameNotFoundException(className.toString()); 1852 } 1853 1854 @Override 1855 public ServiceInfo getServiceInfo(ComponentName className, int flags) 1856 throws NameNotFoundException { 1857 try { 1858 ServiceInfo si = mPM.getServiceInfo(className, flags); 1859 if (si != null) { 1860 return si; 1861 } 1862 } catch (RemoteException e) { 1863 throw new RuntimeException("Package manager has died", e); 1864 } 1865 1866 throw new NameNotFoundException(className.toString()); 1867 } 1868 1869 @Override 1870 public ProviderInfo getProviderInfo(ComponentName className, int flags) 1871 throws NameNotFoundException { 1872 try { 1873 ProviderInfo pi = mPM.getProviderInfo(className, flags); 1874 if (pi != null) { 1875 return pi; 1876 } 1877 } catch (RemoteException e) { 1878 throw new RuntimeException("Package manager has died", e); 1879 } 1880 1881 throw new NameNotFoundException(className.toString()); 1882 } 1883 1884 @Override 1885 public String[] getSystemSharedLibraryNames() { 1886 try { 1887 return mPM.getSystemSharedLibraryNames(); 1888 } catch (RemoteException e) { 1889 throw new RuntimeException("Package manager has died", e); 1890 } 1891 } 1892 1893 @Override 1894 public FeatureInfo[] getSystemAvailableFeatures() { 1895 try { 1896 return mPM.getSystemAvailableFeatures(); 1897 } catch (RemoteException e) { 1898 throw new RuntimeException("Package manager has died", e); 1899 } 1900 } 1901 1902 @Override 1903 public boolean hasSystemFeature(String name) { 1904 try { 1905 return mPM.hasSystemFeature(name); 1906 } catch (RemoteException e) { 1907 throw new RuntimeException("Package manager has died", e); 1908 } 1909 } 1910 1911 @Override 1912 public int checkPermission(String permName, String pkgName) { 1913 try { 1914 return mPM.checkPermission(permName, pkgName); 1915 } catch (RemoteException e) { 1916 throw new RuntimeException("Package manager has died", e); 1917 } 1918 } 1919 1920 @Override 1921 public boolean addPermission(PermissionInfo info) { 1922 try { 1923 return mPM.addPermission(info); 1924 } catch (RemoteException e) { 1925 throw new RuntimeException("Package manager has died", e); 1926 } 1927 } 1928 1929 @Override 1930 public boolean addPermissionAsync(PermissionInfo info) { 1931 try { 1932 return mPM.addPermissionAsync(info); 1933 } catch (RemoteException e) { 1934 throw new RuntimeException("Package manager has died", e); 1935 } 1936 } 1937 1938 @Override 1939 public void removePermission(String name) { 1940 try { 1941 mPM.removePermission(name); 1942 } catch (RemoteException e) { 1943 throw new RuntimeException("Package manager has died", e); 1944 } 1945 } 1946 1947 @Override 1948 public int checkSignatures(String pkg1, String pkg2) { 1949 try { 1950 return mPM.checkSignatures(pkg1, pkg2); 1951 } catch (RemoteException e) { 1952 throw new RuntimeException("Package manager has died", e); 1953 } 1954 } 1955 1956 @Override 1957 public int checkSignatures(int uid1, int uid2) { 1958 try { 1959 return mPM.checkUidSignatures(uid1, uid2); 1960 } catch (RemoteException e) { 1961 throw new RuntimeException("Package manager has died", e); 1962 } 1963 } 1964 1965 @Override 1966 public String[] getPackagesForUid(int uid) { 1967 try { 1968 return mPM.getPackagesForUid(uid); 1969 } catch (RemoteException e) { 1970 throw new RuntimeException("Package manager has died", e); 1971 } 1972 } 1973 1974 @Override 1975 public String getNameForUid(int uid) { 1976 try { 1977 return mPM.getNameForUid(uid); 1978 } catch (RemoteException e) { 1979 throw new RuntimeException("Package manager has died", e); 1980 } 1981 } 1982 1983 @Override 1984 public int getUidForSharedUser(String sharedUserName) 1985 throws NameNotFoundException { 1986 try { 1987 int uid = mPM.getUidForSharedUser(sharedUserName); 1988 if(uid != -1) { 1989 return uid; 1990 } 1991 } catch (RemoteException e) { 1992 throw new RuntimeException("Package manager has died", e); 1993 } 1994 throw new NameNotFoundException("No shared userid for user:"+sharedUserName); 1995 } 1996 1997 @Override 1998 public List<PackageInfo> getInstalledPackages(int flags) { 1999 try { 2000 return mPM.getInstalledPackages(flags); 2001 } catch (RemoteException e) { 2002 throw new RuntimeException("Package manager has died", e); 2003 } 2004 } 2005 2006 @Override 2007 public List<ApplicationInfo> getInstalledApplications(int flags) { 2008 try { 2009 return mPM.getInstalledApplications(flags); 2010 } catch (RemoteException e) { 2011 throw new RuntimeException("Package manager has died", e); 2012 } 2013 } 2014 2015 @Override 2016 public ResolveInfo resolveActivity(Intent intent, int flags) { 2017 try { 2018 return mPM.resolveIntent( 2019 intent, 2020 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2021 flags); 2022 } catch (RemoteException e) { 2023 throw new RuntimeException("Package manager has died", e); 2024 } 2025 } 2026 2027 @Override 2028 public List<ResolveInfo> queryIntentActivities(Intent intent, 2029 int flags) { 2030 try { 2031 return mPM.queryIntentActivities( 2032 intent, 2033 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2034 flags); 2035 } catch (RemoteException e) { 2036 throw new RuntimeException("Package manager has died", e); 2037 } 2038 } 2039 2040 @Override 2041 public List<ResolveInfo> queryIntentActivityOptions( 2042 ComponentName caller, Intent[] specifics, Intent intent, 2043 int flags) { 2044 final ContentResolver resolver = mContext.getContentResolver(); 2045 2046 String[] specificTypes = null; 2047 if (specifics != null) { 2048 final int N = specifics.length; 2049 for (int i=0; i<N; i++) { 2050 Intent sp = specifics[i]; 2051 if (sp != null) { 2052 String t = sp.resolveTypeIfNeeded(resolver); 2053 if (t != null) { 2054 if (specificTypes == null) { 2055 specificTypes = new String[N]; 2056 } 2057 specificTypes[i] = t; 2058 } 2059 } 2060 } 2061 } 2062 2063 try { 2064 return mPM.queryIntentActivityOptions(caller, specifics, 2065 specificTypes, intent, intent.resolveTypeIfNeeded(resolver), 2066 flags); 2067 } catch (RemoteException e) { 2068 throw new RuntimeException("Package manager has died", e); 2069 } 2070 } 2071 2072 @Override 2073 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) { 2074 try { 2075 return mPM.queryIntentReceivers( 2076 intent, 2077 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2078 flags); 2079 } catch (RemoteException e) { 2080 throw new RuntimeException("Package manager has died", e); 2081 } 2082 } 2083 2084 @Override 2085 public ResolveInfo resolveService(Intent intent, int flags) { 2086 try { 2087 return mPM.resolveService( 2088 intent, 2089 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2090 flags); 2091 } catch (RemoteException e) { 2092 throw new RuntimeException("Package manager has died", e); 2093 } 2094 } 2095 2096 @Override 2097 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) { 2098 try { 2099 return mPM.queryIntentServices( 2100 intent, 2101 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 2102 flags); 2103 } catch (RemoteException e) { 2104 throw new RuntimeException("Package manager has died", e); 2105 } 2106 } 2107 2108 @Override 2109 public ProviderInfo resolveContentProvider(String name, 2110 int flags) { 2111 try { 2112 return mPM.resolveContentProvider(name, flags); 2113 } catch (RemoteException e) { 2114 throw new RuntimeException("Package manager has died", e); 2115 } 2116 } 2117 2118 @Override 2119 public List<ProviderInfo> queryContentProviders(String processName, 2120 int uid, int flags) { 2121 try { 2122 return mPM.queryContentProviders(processName, uid, flags); 2123 } catch (RemoteException e) { 2124 throw new RuntimeException("Package manager has died", e); 2125 } 2126 } 2127 2128 @Override 2129 public InstrumentationInfo getInstrumentationInfo( 2130 ComponentName className, int flags) 2131 throws NameNotFoundException { 2132 try { 2133 InstrumentationInfo ii = mPM.getInstrumentationInfo( 2134 className, flags); 2135 if (ii != null) { 2136 return ii; 2137 } 2138 } catch (RemoteException e) { 2139 throw new RuntimeException("Package manager has died", e); 2140 } 2141 2142 throw new NameNotFoundException(className.toString()); 2143 } 2144 2145 @Override 2146 public List<InstrumentationInfo> queryInstrumentation( 2147 String targetPackage, int flags) { 2148 try { 2149 return mPM.queryInstrumentation(targetPackage, flags); 2150 } catch (RemoteException e) { 2151 throw new RuntimeException("Package manager has died", e); 2152 } 2153 } 2154 2155 @Override public Drawable getDrawable(String packageName, int resid, 2156 ApplicationInfo appInfo) { 2157 ResourceName name = new ResourceName(packageName, resid); 2158 Drawable dr = getCachedIcon(name); 2159 if (dr != null) { 2160 return dr; 2161 } 2162 if (appInfo == null) { 2163 try { 2164 appInfo = getApplicationInfo(packageName, 0); 2165 } catch (NameNotFoundException e) { 2166 return null; 2167 } 2168 } 2169 try { 2170 Resources r = getResourcesForApplication(appInfo); 2171 dr = r.getDrawable(resid); 2172 if (false) { 2173 RuntimeException e = new RuntimeException("here"); 2174 e.fillInStackTrace(); 2175 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid) 2176 + " from package " + packageName 2177 + ": app scale=" + r.getCompatibilityInfo().applicationScale 2178 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale, 2179 e); 2180 } 2181 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x" 2182 + Integer.toHexString(resid) + " from " + r 2183 + ": " + dr); 2184 putCachedIcon(name, dr); 2185 return dr; 2186 } catch (NameNotFoundException e) { 2187 Log.w("PackageManager", "Failure retrieving resources for" 2188 + appInfo.packageName); 2189 } catch (RuntimeException e) { 2190 // If an exception was thrown, fall through to return 2191 // default icon. 2192 Log.w("PackageManager", "Failure retrieving icon 0x" 2193 + Integer.toHexString(resid) + " in package " 2194 + packageName, e); 2195 } 2196 return null; 2197 } 2198 2199 @Override public Drawable getActivityIcon(ComponentName activityName) 2200 throws NameNotFoundException { 2201 return getActivityInfo(activityName, 0).loadIcon(this); 2202 } 2203 2204 @Override public Drawable getActivityIcon(Intent intent) 2205 throws NameNotFoundException { 2206 if (intent.getComponent() != null) { 2207 return getActivityIcon(intent.getComponent()); 2208 } 2209 2210 ResolveInfo info = resolveActivity( 2211 intent, PackageManager.MATCH_DEFAULT_ONLY); 2212 if (info != null) { 2213 return info.activityInfo.loadIcon(this); 2214 } 2215 2216 throw new NameNotFoundException(intent.toURI()); 2217 } 2218 2219 @Override public Drawable getDefaultActivityIcon() { 2220 return Resources.getSystem().getDrawable( 2221 com.android.internal.R.drawable.sym_def_app_icon); 2222 } 2223 2224 @Override public Drawable getApplicationIcon(ApplicationInfo info) { 2225 return info.loadIcon(this); 2226 } 2227 2228 @Override public Drawable getApplicationIcon(String packageName) 2229 throws NameNotFoundException { 2230 return getApplicationIcon(getApplicationInfo(packageName, 0)); 2231 } 2232 2233 @Override 2234 public Drawable getActivityLogo(ComponentName activityName) 2235 throws NameNotFoundException { 2236 return getActivityInfo(activityName, 0).loadLogo(this); 2237 } 2238 2239 @Override 2240 public Drawable getActivityLogo(Intent intent) 2241 throws NameNotFoundException { 2242 if (intent.getComponent() != null) { 2243 return getActivityLogo(intent.getComponent()); 2244 } 2245 2246 ResolveInfo info = resolveActivity( 2247 intent, PackageManager.MATCH_DEFAULT_ONLY); 2248 if (info != null) { 2249 return info.activityInfo.loadLogo(this); 2250 } 2251 2252 throw new NameNotFoundException(intent.toUri(0)); 2253 } 2254 2255 @Override 2256 public Drawable getApplicationLogo(ApplicationInfo info) { 2257 return info.loadLogo(this); 2258 } 2259 2260 @Override 2261 public Drawable getApplicationLogo(String packageName) 2262 throws NameNotFoundException { 2263 return getApplicationLogo(getApplicationInfo(packageName, 0)); 2264 } 2265 2266 @Override public Resources getResourcesForActivity( 2267 ComponentName activityName) throws NameNotFoundException { 2268 return getResourcesForApplication( 2269 getActivityInfo(activityName, 0).applicationInfo); 2270 } 2271 2272 @Override public Resources getResourcesForApplication( 2273 ApplicationInfo app) throws NameNotFoundException { 2274 if (app.packageName.equals("system")) { 2275 return mContext.mMainThread.getSystemContext().getResources(); 2276 } 2277 Resources r = mContext.mMainThread.getTopLevelResources( 2278 app.uid == Process.myUid() ? app.sourceDir 2279 : app.publicSourceDir, mContext.mPackageInfo); 2280 if (r != null) { 2281 return r; 2282 } 2283 throw new NameNotFoundException("Unable to open " + app.publicSourceDir); 2284 } 2285 2286 @Override public Resources getResourcesForApplication( 2287 String appPackageName) throws NameNotFoundException { 2288 return getResourcesForApplication( 2289 getApplicationInfo(appPackageName, 0)); 2290 } 2291 2292 int mCachedSafeMode = -1; 2293 @Override public boolean isSafeMode() { 2294 try { 2295 if (mCachedSafeMode < 0) { 2296 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0; 2297 } 2298 return mCachedSafeMode != 0; 2299 } catch (RemoteException e) { 2300 throw new RuntimeException("Package manager has died", e); 2301 } 2302 } 2303 2304 static void configurationChanged() { 2305 synchronized (sSync) { 2306 sIconCache.clear(); 2307 sStringCache.clear(); 2308 } 2309 } 2310 2311 ApplicationPackageManager(ContextImpl context, 2312 IPackageManager pm) { 2313 mContext = context; 2314 mPM = pm; 2315 } 2316 2317 private Drawable getCachedIcon(ResourceName name) { 2318 synchronized (sSync) { 2319 WeakReference<Drawable> wr = sIconCache.get(name); 2320 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for " 2321 + name + ": " + wr); 2322 if (wr != null) { // we have the activity 2323 Drawable dr = wr.get(); 2324 if (dr != null) { 2325 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for " 2326 + name + ": " + dr); 2327 return dr; 2328 } 2329 // our entry has been purged 2330 sIconCache.remove(name); 2331 } 2332 } 2333 return null; 2334 } 2335 2336 private void putCachedIcon(ResourceName name, Drawable dr) { 2337 synchronized (sSync) { 2338 sIconCache.put(name, new WeakReference<Drawable>(dr)); 2339 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for " 2340 + name + ": " + dr); 2341 } 2342 } 2343 2344 static final void handlePackageBroadcast(int cmd, String[] pkgList, 2345 boolean hasPkgInfo) { 2346 boolean immediateGc = false; 2347 if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) { 2348 immediateGc = true; 2349 } 2350 if (pkgList != null && (pkgList.length > 0)) { 2351 boolean needCleanup = false; 2352 for (String ssp : pkgList) { 2353 synchronized (sSync) { 2354 if (sIconCache.size() > 0) { 2355 Iterator<ResourceName> it = sIconCache.keySet().iterator(); 2356 while (it.hasNext()) { 2357 ResourceName nm = it.next(); 2358 if (nm.packageName.equals(ssp)) { 2359 //Log.i(TAG, "Removing cached drawable for " + nm); 2360 it.remove(); 2361 needCleanup = true; 2362 } 2363 } 2364 } 2365 if (sStringCache.size() > 0) { 2366 Iterator<ResourceName> it = sStringCache.keySet().iterator(); 2367 while (it.hasNext()) { 2368 ResourceName nm = it.next(); 2369 if (nm.packageName.equals(ssp)) { 2370 //Log.i(TAG, "Removing cached string for " + nm); 2371 it.remove(); 2372 needCleanup = true; 2373 } 2374 } 2375 } 2376 } 2377 } 2378 if (needCleanup || hasPkgInfo) { 2379 if (immediateGc) { 2380 // Schedule an immediate gc. 2381 Runtime.getRuntime().gc(); 2382 } else { 2383 ActivityThread.currentActivityThread().scheduleGcIdler(); 2384 } 2385 } 2386 } 2387 } 2388 2389 private static final class ResourceName { 2390 final String packageName; 2391 final int iconId; 2392 2393 ResourceName(String _packageName, int _iconId) { 2394 packageName = _packageName; 2395 iconId = _iconId; 2396 } 2397 2398 ResourceName(ApplicationInfo aInfo, int _iconId) { 2399 this(aInfo.packageName, _iconId); 2400 } 2401 2402 ResourceName(ComponentInfo cInfo, int _iconId) { 2403 this(cInfo.applicationInfo.packageName, _iconId); 2404 } 2405 2406 ResourceName(ResolveInfo rInfo, int _iconId) { 2407 this(rInfo.activityInfo.applicationInfo.packageName, _iconId); 2408 } 2409 2410 @Override 2411 public boolean equals(Object o) { 2412 if (this == o) return true; 2413 if (o == null || getClass() != o.getClass()) return false; 2414 2415 ResourceName that = (ResourceName) o; 2416 2417 if (iconId != that.iconId) return false; 2418 return !(packageName != null ? 2419 !packageName.equals(that.packageName) : that.packageName != null); 2420 2421 } 2422 2423 @Override 2424 public int hashCode() { 2425 int result; 2426 result = packageName.hashCode(); 2427 result = 31 * result + iconId; 2428 return result; 2429 } 2430 2431 @Override 2432 public String toString() { 2433 return "{ResourceName " + packageName + " / " + iconId + "}"; 2434 } 2435 } 2436 2437 private CharSequence getCachedString(ResourceName name) { 2438 synchronized (sSync) { 2439 WeakReference<CharSequence> wr = sStringCache.get(name); 2440 if (wr != null) { // we have the activity 2441 CharSequence cs = wr.get(); 2442 if (cs != null) { 2443 return cs; 2444 } 2445 // our entry has been purged 2446 sStringCache.remove(name); 2447 } 2448 } 2449 return null; 2450 } 2451 2452 private void putCachedString(ResourceName name, CharSequence cs) { 2453 synchronized (sSync) { 2454 sStringCache.put(name, new WeakReference<CharSequence>(cs)); 2455 } 2456 } 2457 2458 @Override 2459 public CharSequence getText(String packageName, int resid, 2460 ApplicationInfo appInfo) { 2461 ResourceName name = new ResourceName(packageName, resid); 2462 CharSequence text = getCachedString(name); 2463 if (text != null) { 2464 return text; 2465 } 2466 if (appInfo == null) { 2467 try { 2468 appInfo = getApplicationInfo(packageName, 0); 2469 } catch (NameNotFoundException e) { 2470 return null; 2471 } 2472 } 2473 try { 2474 Resources r = getResourcesForApplication(appInfo); 2475 text = r.getText(resid); 2476 putCachedString(name, text); 2477 return text; 2478 } catch (NameNotFoundException e) { 2479 Log.w("PackageManager", "Failure retrieving resources for" 2480 + appInfo.packageName); 2481 } catch (RuntimeException e) { 2482 // If an exception was thrown, fall through to return 2483 // default icon. 2484 Log.w("PackageManager", "Failure retrieving text 0x" 2485 + Integer.toHexString(resid) + " in package " 2486 + packageName, e); 2487 } 2488 return null; 2489 } 2490 2491 @Override 2492 public XmlResourceParser getXml(String packageName, int resid, 2493 ApplicationInfo appInfo) { 2494 if (appInfo == null) { 2495 try { 2496 appInfo = getApplicationInfo(packageName, 0); 2497 } catch (NameNotFoundException e) { 2498 return null; 2499 } 2500 } 2501 try { 2502 Resources r = getResourcesForApplication(appInfo); 2503 return r.getXml(resid); 2504 } catch (RuntimeException e) { 2505 // If an exception was thrown, fall through to return 2506 // default icon. 2507 Log.w("PackageManager", "Failure retrieving xml 0x" 2508 + Integer.toHexString(resid) + " in package " 2509 + packageName, e); 2510 } catch (NameNotFoundException e) { 2511 Log.w("PackageManager", "Failure retrieving resources for" 2512 + appInfo.packageName); 2513 } 2514 return null; 2515 } 2516 2517 @Override 2518 public CharSequence getApplicationLabel(ApplicationInfo info) { 2519 return info.loadLabel(this); 2520 } 2521 2522 @Override 2523 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags, 2524 String installerPackageName) { 2525 try { 2526 mPM.installPackage(packageURI, observer, flags, installerPackageName); 2527 } catch (RemoteException e) { 2528 // Should never happen! 2529 } 2530 } 2531 2532 @Override 2533 public void movePackage(String packageName, IPackageMoveObserver observer, int flags) { 2534 try { 2535 mPM.movePackage(packageName, observer, flags); 2536 } catch (RemoteException e) { 2537 // Should never happen! 2538 } 2539 } 2540 2541 @Override 2542 public String getInstallerPackageName(String packageName) { 2543 try { 2544 return mPM.getInstallerPackageName(packageName); 2545 } catch (RemoteException e) { 2546 // Should never happen! 2547 } 2548 return null; 2549 } 2550 2551 @Override 2552 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) { 2553 try { 2554 mPM.deletePackage(packageName, observer, flags); 2555 } catch (RemoteException e) { 2556 // Should never happen! 2557 } 2558 } 2559 @Override 2560 public void clearApplicationUserData(String packageName, 2561 IPackageDataObserver observer) { 2562 try { 2563 mPM.clearApplicationUserData(packageName, observer); 2564 } catch (RemoteException e) { 2565 // Should never happen! 2566 } 2567 } 2568 @Override 2569 public void deleteApplicationCacheFiles(String packageName, 2570 IPackageDataObserver observer) { 2571 try { 2572 mPM.deleteApplicationCacheFiles(packageName, observer); 2573 } catch (RemoteException e) { 2574 // Should never happen! 2575 } 2576 } 2577 @Override 2578 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) { 2579 try { 2580 mPM.freeStorageAndNotify(idealStorageSize, observer); 2581 } catch (RemoteException e) { 2582 // Should never happen! 2583 } 2584 } 2585 2586 @Override 2587 public void freeStorage(long freeStorageSize, IntentSender pi) { 2588 try { 2589 mPM.freeStorage(freeStorageSize, pi); 2590 } catch (RemoteException e) { 2591 // Should never happen! 2592 } 2593 } 2594 2595 @Override 2596 public void getPackageSizeInfo(String packageName, 2597 IPackageStatsObserver observer) { 2598 try { 2599 mPM.getPackageSizeInfo(packageName, observer); 2600 } catch (RemoteException e) { 2601 // Should never happen! 2602 } 2603 } 2604 @Override 2605 public void addPackageToPreferred(String packageName) { 2606 try { 2607 mPM.addPackageToPreferred(packageName); 2608 } catch (RemoteException e) { 2609 // Should never happen! 2610 } 2611 } 2612 2613 @Override 2614 public void removePackageFromPreferred(String packageName) { 2615 try { 2616 mPM.removePackageFromPreferred(packageName); 2617 } catch (RemoteException e) { 2618 // Should never happen! 2619 } 2620 } 2621 2622 @Override 2623 public List<PackageInfo> getPreferredPackages(int flags) { 2624 try { 2625 return mPM.getPreferredPackages(flags); 2626 } catch (RemoteException e) { 2627 // Should never happen! 2628 } 2629 return new ArrayList<PackageInfo>(); 2630 } 2631 2632 @Override 2633 public void addPreferredActivity(IntentFilter filter, 2634 int match, ComponentName[] set, ComponentName activity) { 2635 try { 2636 mPM.addPreferredActivity(filter, match, set, activity); 2637 } catch (RemoteException e) { 2638 // Should never happen! 2639 } 2640 } 2641 2642 @Override 2643 public void replacePreferredActivity(IntentFilter filter, 2644 int match, ComponentName[] set, ComponentName activity) { 2645 try { 2646 mPM.replacePreferredActivity(filter, match, set, activity); 2647 } catch (RemoteException e) { 2648 // Should never happen! 2649 } 2650 } 2651 2652 @Override 2653 public void clearPackagePreferredActivities(String packageName) { 2654 try { 2655 mPM.clearPackagePreferredActivities(packageName); 2656 } catch (RemoteException e) { 2657 // Should never happen! 2658 } 2659 } 2660 2661 @Override 2662 public int getPreferredActivities(List<IntentFilter> outFilters, 2663 List<ComponentName> outActivities, String packageName) { 2664 try { 2665 return mPM.getPreferredActivities(outFilters, outActivities, packageName); 2666 } catch (RemoteException e) { 2667 // Should never happen! 2668 } 2669 return 0; 2670 } 2671 2672 @Override 2673 public void setComponentEnabledSetting(ComponentName componentName, 2674 int newState, int flags) { 2675 try { 2676 mPM.setComponentEnabledSetting(componentName, newState, flags); 2677 } catch (RemoteException e) { 2678 // Should never happen! 2679 } 2680 } 2681 2682 @Override 2683 public int getComponentEnabledSetting(ComponentName componentName) { 2684 try { 2685 return mPM.getComponentEnabledSetting(componentName); 2686 } catch (RemoteException e) { 2687 // Should never happen! 2688 } 2689 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2690 } 2691 2692 @Override 2693 public void setApplicationEnabledSetting(String packageName, 2694 int newState, int flags) { 2695 try { 2696 mPM.setApplicationEnabledSetting(packageName, newState, flags); 2697 } catch (RemoteException e) { 2698 // Should never happen! 2699 } 2700 } 2701 2702 @Override 2703 public int getApplicationEnabledSetting(String packageName) { 2704 try { 2705 return mPM.getApplicationEnabledSetting(packageName); 2706 } catch (RemoteException e) { 2707 // Should never happen! 2708 } 2709 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 2710 } 2711 2712 @Override 2713 public void setPackageObbPath(String packageName, String path) { 2714 try { 2715 mPM.setPackageObbPath(packageName, path); 2716 } catch (RemoteException e) { 2717 // Should never happen! 2718 } 2719 } 2720 2721 private final ContextImpl mContext; 2722 private final IPackageManager mPM; 2723 2724 private static final Object sSync = new Object(); 2725 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache 2726 = new HashMap<ResourceName, WeakReference<Drawable> >(); 2727 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache 2728 = new HashMap<ResourceName, WeakReference<CharSequence> >(); 2729 } 2730 2731 // ---------------------------------------------------------------------- 2732 // ---------------------------------------------------------------------- 2733 // ---------------------------------------------------------------------- 2734 2735 private static final class SharedPreferencesImpl implements SharedPreferences { 2736 2737 // Lock ordering rules: 2738 // - acquire SharedPreferencesImpl.this before EditorImpl.this 2739 // - acquire mWritingToDiskLock before EditorImpl.this 2740 2741 private final File mFile; 2742 private final File mBackupFile; 2743 private final int mMode; 2744 2745 private Map<String, Object> mMap; // guarded by 'this' 2746 private int mDiskWritesInFlight = 0; // guarded by 'this' 2747 private boolean mLoaded = false; // guarded by 'this' 2748 private long mStatTimestamp; // guarded by 'this' 2749 private long mStatSize; // guarded by 'this' 2750 2751 private final Object mWritingToDiskLock = new Object(); 2752 private static final Object mContent = new Object(); 2753 private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners; 2754 2755 SharedPreferencesImpl( 2756 File file, int mode, Map initialContents) { 2757 mFile = file; 2758 mBackupFile = makeBackupFile(file); 2759 mMode = mode; 2760 mLoaded = initialContents != null; 2761 mMap = initialContents != null ? initialContents : new HashMap<String, Object>(); 2762 FileStatus stat = new FileStatus(); 2763 if (FileUtils.getFileStatus(file.getPath(), stat)) { 2764 mStatTimestamp = stat.mtime; 2765 } 2766 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); 2767 } 2768 2769 // Has this SharedPreferences ever had values assigned to it? 2770 boolean isLoaded() { 2771 synchronized (this) { 2772 return mLoaded; 2773 } 2774 } 2775 2776 // Has the file changed out from under us? i.e. writes that 2777 // we didn't instigate. 2778 public boolean hasFileChangedUnexpectedly() { 2779 synchronized (this) { 2780 if (mDiskWritesInFlight > 0) { 2781 // If we know we caused it, it's not unexpected. 2782 if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected."); 2783 return false; 2784 } 2785 } 2786 FileStatus stat = new FileStatus(); 2787 if (!FileUtils.getFileStatus(mFile.getPath(), stat)) { 2788 return true; 2789 } 2790 synchronized (this) { 2791 return mStatTimestamp != stat.mtime || mStatSize != stat.size; 2792 } 2793 } 2794 2795 public void replace(Map newContents) { 2796 synchronized (this) { 2797 mLoaded = true; 2798 if (newContents != null) { 2799 mMap = newContents; 2800 } 2801 } 2802 } 2803 2804 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 2805 synchronized(this) { 2806 mListeners.put(listener, mContent); 2807 } 2808 } 2809 2810 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { 2811 synchronized(this) { 2812 mListeners.remove(listener); 2813 } 2814 } 2815 2816 public Map<String, ?> getAll() { 2817 synchronized(this) { 2818 //noinspection unchecked 2819 return new HashMap<String, Object>(mMap); 2820 } 2821 } 2822 2823 public String getString(String key, String defValue) { 2824 synchronized (this) { 2825 String v = (String)mMap.get(key); 2826 return v != null ? v : defValue; 2827 } 2828 } 2829 2830 public Set<String> getStringSet(String key, Set<String> defValues) { 2831 synchronized (this) { 2832 Set<String> v = (Set<String>) mMap.get(key); 2833 return v != null ? v : defValues; 2834 } 2835 } 2836 2837 public int getInt(String key, int defValue) { 2838 synchronized (this) { 2839 Integer v = (Integer)mMap.get(key); 2840 return v != null ? v : defValue; 2841 } 2842 } 2843 public long getLong(String key, long defValue) { 2844 synchronized (this) { 2845 Long v = (Long)mMap.get(key); 2846 return v != null ? v : defValue; 2847 } 2848 } 2849 public float getFloat(String key, float defValue) { 2850 synchronized (this) { 2851 Float v = (Float)mMap.get(key); 2852 return v != null ? v : defValue; 2853 } 2854 } 2855 public boolean getBoolean(String key, boolean defValue) { 2856 synchronized (this) { 2857 Boolean v = (Boolean)mMap.get(key); 2858 return v != null ? v : defValue; 2859 } 2860 } 2861 2862 public boolean contains(String key) { 2863 synchronized (this) { 2864 return mMap.containsKey(key); 2865 } 2866 } 2867 2868 public Editor edit() { 2869 return new EditorImpl(); 2870 } 2871 2872 // Return value from EditorImpl#commitToMemory() 2873 private static class MemoryCommitResult { 2874 public boolean changesMade; // any keys different? 2875 public List<String> keysModified; // may be null 2876 public Set<OnSharedPreferenceChangeListener> listeners; // may be null 2877 public Map<?, ?> mapToWriteToDisk; 2878 public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1); 2879 public volatile boolean writeToDiskResult = false; 2880 2881 public void setDiskWriteResult(boolean result) { 2882 writeToDiskResult = result; 2883 writtenToDiskLatch.countDown(); 2884 } 2885 } 2886 2887 public final class EditorImpl implements Editor { 2888 private final Map<String, Object> mModified = Maps.newHashMap(); 2889 private boolean mClear = false; 2890 2891 public Editor putString(String key, String value) { 2892 synchronized (this) { 2893 mModified.put(key, value); 2894 return this; 2895 } 2896 } 2897 public Editor putStringSet(String key, Set<String> values) { 2898 synchronized (this) { 2899 mModified.put(key, values); 2900 return this; 2901 } 2902 } 2903 public Editor putInt(String key, int value) { 2904 synchronized (this) { 2905 mModified.put(key, value); 2906 return this; 2907 } 2908 } 2909 public Editor putLong(String key, long value) { 2910 synchronized (this) { 2911 mModified.put(key, value); 2912 return this; 2913 } 2914 } 2915 public Editor putFloat(String key, float value) { 2916 synchronized (this) { 2917 mModified.put(key, value); 2918 return this; 2919 } 2920 } 2921 public Editor putBoolean(String key, boolean value) { 2922 synchronized (this) { 2923 mModified.put(key, value); 2924 return this; 2925 } 2926 } 2927 2928 public Editor remove(String key) { 2929 synchronized (this) { 2930 mModified.put(key, this); 2931 return this; 2932 } 2933 } 2934 2935 public Editor clear() { 2936 synchronized (this) { 2937 mClear = true; 2938 return this; 2939 } 2940 } 2941 2942 public void apply() { 2943 final MemoryCommitResult mcr = commitToMemory(); 2944 final Runnable awaitCommit = new Runnable() { 2945 public void run() { 2946 try { 2947 mcr.writtenToDiskLatch.await(); 2948 } catch (InterruptedException ignored) { 2949 } 2950 } 2951 }; 2952 2953 QueuedWork.add(awaitCommit); 2954 2955 Runnable postWriteRunnable = new Runnable() { 2956 public void run() { 2957 awaitCommit.run(); 2958 QueuedWork.remove(awaitCommit); 2959 } 2960 }; 2961 2962 SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable); 2963 2964 // Okay to notify the listeners before it's hit disk 2965 // because the listeners should always get the same 2966 // SharedPreferences instance back, which has the 2967 // changes reflected in memory. 2968 notifyListeners(mcr); 2969 } 2970 2971 // Returns true if any changes were made 2972 private MemoryCommitResult commitToMemory() { 2973 MemoryCommitResult mcr = new MemoryCommitResult(); 2974 synchronized (SharedPreferencesImpl.this) { 2975 // We optimistically don't make a deep copy until 2976 // a memory commit comes in when we're already 2977 // writing to disk. 2978 if (mDiskWritesInFlight > 0) { 2979 // We can't modify our mMap as a currently 2980 // in-flight write owns it. Clone it before 2981 // modifying it. 2982 // noinspection unchecked 2983 mMap = new HashMap<String, Object>(mMap); 2984 } 2985 mcr.mapToWriteToDisk = mMap; 2986 mDiskWritesInFlight++; 2987 2988 boolean hasListeners = mListeners.size() > 0; 2989 if (hasListeners) { 2990 mcr.keysModified = new ArrayList<String>(); 2991 mcr.listeners = 2992 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet()); 2993 } 2994 2995 synchronized (this) { 2996 if (mClear) { 2997 if (!mMap.isEmpty()) { 2998 mcr.changesMade = true; 2999 mMap.clear(); 3000 } 3001 mClear = false; 3002 } 3003 3004 for (Entry<String, Object> e : mModified.entrySet()) { 3005 String k = e.getKey(); 3006 Object v = e.getValue(); 3007 if (v == this) { // magic value for a removal mutation 3008 if (!mMap.containsKey(k)) { 3009 continue; 3010 } 3011 mMap.remove(k); 3012 } else { 3013 boolean isSame = false; 3014 if (mMap.containsKey(k)) { 3015 Object existingValue = mMap.get(k); 3016 if (existingValue != null && existingValue.equals(v)) { 3017 continue; 3018 } 3019 } 3020 mMap.put(k, v); 3021 } 3022 3023 mcr.changesMade = true; 3024 if (hasListeners) { 3025 mcr.keysModified.add(k); 3026 } 3027 } 3028 3029 mModified.clear(); 3030 } 3031 } 3032 return mcr; 3033 } 3034 3035 public boolean commit() { 3036 MemoryCommitResult mcr = commitToMemory(); 3037 SharedPreferencesImpl.this.enqueueDiskWrite( 3038 mcr, null /* sync write on this thread okay */); 3039 try { 3040 mcr.writtenToDiskLatch.await(); 3041 } catch (InterruptedException e) { 3042 return false; 3043 } 3044 notifyListeners(mcr); 3045 return mcr.writeToDiskResult; 3046 } 3047 3048 private void notifyListeners(final MemoryCommitResult mcr) { 3049 if (mcr.listeners == null || mcr.keysModified == null || 3050 mcr.keysModified.size() == 0) { 3051 return; 3052 } 3053 if (Looper.myLooper() == Looper.getMainLooper()) { 3054 for (int i = mcr.keysModified.size() - 1; i >= 0; i--) { 3055 final String key = mcr.keysModified.get(i); 3056 for (OnSharedPreferenceChangeListener listener : mcr.listeners) { 3057 if (listener != null) { 3058 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key); 3059 } 3060 } 3061 } 3062 } else { 3063 // Run this function on the main thread. 3064 ActivityThread.sMainThreadHandler.post(new Runnable() { 3065 public void run() { 3066 notifyListeners(mcr); 3067 } 3068 }); 3069 } 3070 } 3071 } 3072 3073 /** 3074 * Enqueue an already-committed-to-memory result to be written 3075 * to disk. 3076 * 3077 * They will be written to disk one-at-a-time in the order 3078 * that they're enqueued. 3079 * 3080 * @param postWriteRunnable if non-null, we're being called 3081 * from apply() and this is the runnable to run after 3082 * the write proceeds. if null (from a regular commit()), 3083 * then we're allowed to do this disk write on the main 3084 * thread (which in addition to reducing allocations and 3085 * creating a background thread, this has the advantage that 3086 * we catch them in userdebug StrictMode reports to convert 3087 * them where possible to apply() ...) 3088 */ 3089 private void enqueueDiskWrite(final MemoryCommitResult mcr, 3090 final Runnable postWriteRunnable) { 3091 final Runnable writeToDiskRunnable = new Runnable() { 3092 public void run() { 3093 synchronized (mWritingToDiskLock) { 3094 writeToFile(mcr); 3095 } 3096 synchronized (SharedPreferencesImpl.this) { 3097 mDiskWritesInFlight--; 3098 } 3099 if (postWriteRunnable != null) { 3100 postWriteRunnable.run(); 3101 } 3102 } 3103 }; 3104 3105 final boolean isFromSyncCommit = (postWriteRunnable == null); 3106 3107 // Typical #commit() path with fewer allocations, doing a write on 3108 // the current thread. 3109 if (isFromSyncCommit) { 3110 boolean wasEmpty = false; 3111 synchronized (SharedPreferencesImpl.this) { 3112 wasEmpty = mDiskWritesInFlight == 1; 3113 } 3114 if (wasEmpty) { 3115 writeToDiskRunnable.run(); 3116 return; 3117 } 3118 } 3119 3120 QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable); 3121 } 3122 3123 private static FileOutputStream createFileOutputStream(File file) { 3124 FileOutputStream str = null; 3125 try { 3126 str = new FileOutputStream(file); 3127 } catch (FileNotFoundException e) { 3128 File parent = file.getParentFile(); 3129 if (!parent.mkdir()) { 3130 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file); 3131 return null; 3132 } 3133 FileUtils.setPermissions( 3134 parent.getPath(), 3135 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 3136 -1, -1); 3137 try { 3138 str = new FileOutputStream(file); 3139 } catch (FileNotFoundException e2) { 3140 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2); 3141 } 3142 } 3143 return str; 3144 } 3145 3146 // Note: must hold mWritingToDiskLock 3147 private void writeToFile(MemoryCommitResult mcr) { 3148 // Rename the current file so it may be used as a backup during the next read 3149 if (mFile.exists()) { 3150 if (!mcr.changesMade) { 3151 // If the file already exists, but no changes were 3152 // made to the underlying map, it's wasteful to 3153 // re-write the file. Return as if we wrote it 3154 // out. 3155 mcr.setDiskWriteResult(true); 3156 return; 3157 } 3158 if (!mBackupFile.exists()) { 3159 if (!mFile.renameTo(mBackupFile)) { 3160 Log.e(TAG, "Couldn't rename file " + mFile 3161 + " to backup file " + mBackupFile); 3162 mcr.setDiskWriteResult(false); 3163 return; 3164 } 3165 } else { 3166 mFile.delete(); 3167 } 3168 } 3169 3170 // Attempt to write the file, delete the backup and return true as atomically as 3171 // possible. If any exception occurs, delete the new file; next time we will restore 3172 // from the backup. 3173 try { 3174 FileOutputStream str = createFileOutputStream(mFile); 3175 if (str == null) { 3176 mcr.setDiskWriteResult(false); 3177 return; 3178 } 3179 XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str); 3180 FileUtils.sync(str); 3181 str.close(); 3182 setFilePermissionsFromMode(mFile.getPath(), mMode, 0); 3183 FileStatus stat = new FileStatus(); 3184 if (FileUtils.getFileStatus(mFile.getPath(), stat)) { 3185 synchronized (this) { 3186 mStatTimestamp = stat.mtime; 3187 mStatSize = stat.size; 3188 } 3189 } 3190 // Writing was successful, delete the backup file if there is one. 3191 mBackupFile.delete(); 3192 mcr.setDiskWriteResult(true); 3193 return; 3194 } catch (XmlPullParserException e) { 3195 Log.w(TAG, "writeToFile: Got exception:", e); 3196 } catch (IOException e) { 3197 Log.w(TAG, "writeToFile: Got exception:", e); 3198 } 3199 // Clean up an unsuccessfully written file 3200 if (mFile.exists()) { 3201 if (!mFile.delete()) { 3202 Log.e(TAG, "Couldn't clean up partially-written file " + mFile); 3203 } 3204 } 3205 mcr.setDiskWriteResult(false); 3206 } 3207 } 3208} 3209