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