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