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