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