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