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