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