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