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