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