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