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