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