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