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