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