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