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