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