ContextImpl.java revision 5fd2169eabd77e6bfafaf456e58051a3bafb2bca
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;
20
21import android.content.BroadcastReceiver;
22import android.content.ComponentName;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.ContextWrapper;
26import android.content.IContentProvider;
27import android.content.Intent;
28import android.content.IntentFilter;
29import android.content.IIntentReceiver;
30import android.content.IntentSender;
31import android.content.ReceiverCallNotAllowedException;
32import android.content.ServiceConnection;
33import android.content.SharedPreferences;
34import android.content.pm.ApplicationInfo;
35import android.content.pm.IPackageManager;
36import android.content.pm.PackageManager;
37import android.content.res.AssetManager;
38import android.content.res.CompatibilityInfo;
39import android.content.res.Resources;
40import android.database.DatabaseErrorHandler;
41import android.database.sqlite.SQLiteDatabase;
42import android.database.sqlite.SQLiteDatabase.CursorFactory;
43import android.graphics.Bitmap;
44import android.graphics.drawable.Drawable;
45import android.hardware.SensorManager;
46import android.hardware.usb.IUsbManager;
47import android.hardware.usb.UsbManager;
48import android.location.CountryDetector;
49import android.location.ICountryDetector;
50import android.location.ILocationManager;
51import android.location.LocationManager;
52import android.media.AudioManager;
53import android.net.ConnectivityManager;
54import android.net.IConnectivityManager;
55import android.net.ThrottleManager;
56import android.net.IThrottleManager;
57import android.net.Uri;
58import android.net.wifi.IWifiManager;
59import android.net.wifi.WifiManager;
60import android.nfc.NfcManager;
61import android.os.Binder;
62import android.os.Build;
63import android.os.Bundle;
64import android.os.DropBoxManager;
65import android.os.Environment;
66import android.os.FileUtils;
67import android.os.Handler;
68import android.os.IBinder;
69import android.os.IPowerManager;
70import android.os.Looper;
71import android.os.PowerManager;
72import android.os.Process;
73import android.os.RemoteException;
74import android.os.ServiceManager;
75import android.os.Vibrator;
76import android.os.storage.StorageManager;
77import android.telephony.TelephonyManager;
78import android.content.ClipboardManager;
79import android.util.AndroidRuntimeException;
80import android.util.Log;
81import android.view.ContextThemeWrapper;
82import android.view.Display;
83import android.view.WindowManagerImpl;
84import android.view.accessibility.AccessibilityManager;
85import android.view.inputmethod.InputMethodManager;
86import android.accounts.AccountManager;
87import android.accounts.IAccountManager;
88import android.app.admin.DevicePolicyManager;
89import com.android.internal.os.IDropBoxManagerService;
90
91import java.io.File;
92import java.io.FileInputStream;
93import java.io.FileNotFoundException;
94import java.io.FileOutputStream;
95import java.io.IOException;
96import java.io.InputStream;
97import java.util.ArrayList;
98import java.util.HashMap;
99
100class ReceiverRestrictedContext extends ContextWrapper {
101    ReceiverRestrictedContext(Context base) {
102        super(base);
103    }
104
105    @Override
106    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
107        return registerReceiver(receiver, filter, null, null);
108    }
109
110    @Override
111    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
112            String broadcastPermission, Handler scheduler) {
113        throw new ReceiverCallNotAllowedException(
114                "IntentReceiver components are not allowed to register to receive intents");
115        //ex.fillInStackTrace();
116        //Log.e("IntentReceiver", ex.getMessage(), ex);
117        //return mContext.registerReceiver(receiver, filter, broadcastPermission,
118        //        scheduler);
119    }
120
121    @Override
122    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
123        throw new ReceiverCallNotAllowedException(
124                "IntentReceiver components are not allowed to bind to services");
125        //ex.fillInStackTrace();
126        //Log.e("IntentReceiver", ex.getMessage(), ex);
127        //return mContext.bindService(service, interfaceName, conn, flags);
128    }
129}
130
131/**
132 * Common implementation of Context API, which provides the base
133 * context object for Activity and other application components.
134 */
135class ContextImpl extends Context {
136    private final static String TAG = "ApplicationContext";
137    private final static boolean DEBUG = false;
138
139    private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
140            new HashMap<String, SharedPreferencesImpl>();
141
142    /*package*/ LoadedApk mPackageInfo;
143    private Resources mResources;
144    /*package*/ ActivityThread mMainThread;
145    private Context mOuterContext;
146    private IBinder mActivityToken = null;
147    private ApplicationContentResolver mContentResolver;
148    private int mThemeResource = 0;
149    private Resources.Theme mTheme = null;
150    private PackageManager mPackageManager;
151    private Context mReceiverRestrictedContext = null;
152    private boolean mRestricted;
153
154    private final Object mSync = new Object();
155
156    private File mDatabasesDir;
157    private File mPreferencesDir;
158    private File mFilesDir;
159    private File mCacheDir;
160    private File mObbDir;
161    private File mExternalFilesDir;
162    private File mExternalCacheDir;
163
164    private static final String[] EMPTY_FILE_LIST = {};
165
166    /**
167     * Override this class when the system service constructor needs a
168     * ContextImpl.  Else, use StaticServiceFetcher below.
169     */
170    /*package*/ static class ServiceFetcher {
171        int mContextCacheIndex = -1;
172
173        /**
174         * Main entrypoint; only override if you don't need caching.
175         */
176        public Object getService(ContextImpl ctx) {
177            ArrayList<Object> cache = ctx.mServiceCache;
178            Object service;
179            synchronized (cache) {
180                if (cache.size() == 0) {
181                    // Initialize the cache vector on first access.
182                    // At this point sNextPerContextServiceCacheIndex
183                    // is the number of potential services that are
184                    // cached per-Context.
185                    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
186                        cache.add(null);
187                    }
188                } else {
189                    service = cache.get(mContextCacheIndex);
190                    if (service != null) {
191                        return service;
192                    }
193                }
194                service = createService(ctx);
195                cache.set(mContextCacheIndex, service);
196                return service;
197            }
198        }
199
200        /**
201         * Override this to create a new per-Context instance of the
202         * service.  getService() will handle locking and caching.
203         */
204        public Object createService(ContextImpl ctx) {
205            throw new RuntimeException("Not implemented");
206        }
207    }
208
209    /**
210     * Override this class for services to be cached process-wide.
211     */
212    abstract static class StaticServiceFetcher extends ServiceFetcher {
213        private Object mCachedInstance;
214
215        @Override
216        public final Object getService(ContextImpl unused) {
217            synchronized (StaticServiceFetcher.this) {
218                Object service = mCachedInstance;
219                if (service != null) {
220                    return service;
221                }
222                return mCachedInstance = createStaticService();
223            }
224        }
225
226        public abstract Object createStaticService();
227    }
228
229    private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
230            new HashMap<String, ServiceFetcher>();
231
232    private static int sNextPerContextServiceCacheIndex = 0;
233    private static void registerService(String serviceName, ServiceFetcher fetcher) {
234        if (!(fetcher instanceof StaticServiceFetcher)) {
235            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
236        }
237        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
238    }
239
240    // This one's defined separately and given a variable name so it
241    // can be re-used by getWallpaperManager(), avoiding a HashMap
242    // lookup.
243    private static ServiceFetcher WALLPAPER_FETCHER = new ServiceFetcher() {
244            public Object createService(ContextImpl ctx) {
245                return new WallpaperManager(ctx.getOuterContext(),
246                        ctx.mMainThread.getHandler());
247            }};
248
249    static {
250        registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
251                public Object getService(ContextImpl ctx) {
252                    return AccessibilityManager.getInstance(ctx);
253                }});
254
255        registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
256                public Object createService(ContextImpl ctx) {
257                    IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
258                    IAccountManager service = IAccountManager.Stub.asInterface(b);
259                    return new AccountManager(ctx, service);
260                }});
261
262        registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
263                public Object createService(ContextImpl ctx) {
264                    return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
265                }});
266
267        registerService(ALARM_SERVICE, new StaticServiceFetcher() {
268                public Object createStaticService() {
269                    IBinder b = ServiceManager.getService(ALARM_SERVICE);
270                    IAlarmManager service = IAlarmManager.Stub.asInterface(b);
271                    return new AlarmManager(service);
272                }});
273
274        registerService(AUDIO_SERVICE, new ServiceFetcher() {
275                public Object createService(ContextImpl ctx) {
276                    return new AudioManager(ctx);
277                }});
278
279        registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
280                public Object createService(ContextImpl ctx) {
281                    return new ClipboardManager(ctx.getOuterContext(),
282                            ctx.mMainThread.getHandler());
283                }});
284
285        registerService(CONNECTIVITY_SERVICE, new StaticServiceFetcher() {
286                public Object createStaticService() {
287                    IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
288                    return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));
289                }});
290
291        registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() {
292                public Object createStaticService() {
293                    IBinder b = ServiceManager.getService(COUNTRY_DETECTOR);
294                    return new CountryDetector(ICountryDetector.Stub.asInterface(b));
295                }});
296
297        registerService(DEVICE_POLICY_SERVICE, new ServiceFetcher() {
298                public Object createService(ContextImpl ctx) {
299                    return DevicePolicyManager.create(ctx, ctx.mMainThread.getHandler());
300                }});
301
302        registerService(DOWNLOAD_SERVICE, new ServiceFetcher() {
303                public Object createService(ContextImpl ctx) {
304                    return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
305                }});
306
307        registerService(NFC_SERVICE, new ServiceFetcher() {
308                public Object createService(ContextImpl ctx) {
309                    return new NfcManager(ctx);
310                }});
311
312        registerService(DROPBOX_SERVICE, new StaticServiceFetcher() {
313                public Object createStaticService() {
314                    return createDropBoxManager();
315                }});
316
317        registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
318                public Object createService(ContextImpl ctx) {
319                    return InputMethodManager.getInstance(ctx);
320                }});
321
322        registerService(KEYGUARD_SERVICE, new ServiceFetcher() {
323                public Object getService(ContextImpl ctx) {
324                    // TODO: why isn't this caching it?  It wasn't
325                    // before, so I'm preserving the old behavior and
326                    // using getService(), instead of createService()
327                    // which would do the caching.
328                    return new KeyguardManager();
329                }});
330
331        registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
332                public Object createService(ContextImpl ctx) {
333                    return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
334                }});
335
336        registerService(LOCATION_SERVICE, new StaticServiceFetcher() {
337                public Object createStaticService() {
338                    IBinder b = ServiceManager.getService(LOCATION_SERVICE);
339                    return new LocationManager(ILocationManager.Stub.asInterface(b));
340                }});
341
342        registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {
343                public Object createService(ContextImpl ctx) {
344                    final Context outerContext = ctx.getOuterContext();
345                    return new NotificationManager(
346                        new ContextThemeWrapper(outerContext,
347                                Resources.selectSystemTheme(0,
348                                        outerContext.getApplicationInfo().targetSdkVersion,
349                                        com.android.internal.R.style.Theme_Dialog,
350                                        com.android.internal.R.style.Theme_Holo_Dialog)),
351                        ctx.mMainThread.getHandler());
352                }});
353
354        // Note: this was previously cached in a static variable, but
355        // constructed using mMainThread.getHandler(), so converting
356        // it to be a regular Context-cached service...
357        registerService(POWER_SERVICE, new ServiceFetcher() {
358                public Object createService(ContextImpl ctx) {
359                    IBinder b = ServiceManager.getService(POWER_SERVICE);
360                    IPowerManager service = IPowerManager.Stub.asInterface(b);
361                    return new PowerManager(service, ctx.mMainThread.getHandler());
362                }});
363
364        registerService(SEARCH_SERVICE, new ServiceFetcher() {
365                public Object createService(ContextImpl ctx) {
366                    return new SearchManager(ctx.getOuterContext(),
367                            ctx.mMainThread.getHandler());
368                }});
369
370        registerService(SENSOR_SERVICE, new ServiceFetcher() {
371                public Object createService(ContextImpl ctx) {
372                    return new SensorManager(ctx.mMainThread.getHandler().getLooper());
373                }});
374
375        registerService(STATUS_BAR_SERVICE, new ServiceFetcher() {
376                public Object createService(ContextImpl ctx) {
377                    return new StatusBarManager(ctx.getOuterContext());
378                }});
379
380        registerService(STORAGE_SERVICE, new ServiceFetcher() {
381                public Object createService(ContextImpl ctx) {
382                    try {
383                        return new StorageManager(ctx.mMainThread.getHandler().getLooper());
384                    } catch (RemoteException rex) {
385                        Log.e(TAG, "Failed to create StorageManager", rex);
386                        return null;
387                    }
388                }});
389
390        registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
391                public Object createService(ContextImpl ctx) {
392                    return new TelephonyManager(ctx.getOuterContext());
393                }});
394
395        registerService(THROTTLE_SERVICE, new StaticServiceFetcher() {
396                public Object createStaticService() {
397                    IBinder b = ServiceManager.getService(THROTTLE_SERVICE);
398                    return new ThrottleManager(IThrottleManager.Stub.asInterface(b));
399                }});
400
401        registerService(UI_MODE_SERVICE, new ServiceFetcher() {
402                public Object createService(ContextImpl ctx) {
403                    return new UiModeManager();
404                }});
405
406        registerService(USB_SERVICE, new ServiceFetcher() {
407                public Object createService(ContextImpl ctx) {
408                    IBinder b = ServiceManager.getService(USB_SERVICE);
409                    return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
410                }});
411
412        registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
413                public Object createService(ContextImpl ctx) {
414                    return new Vibrator();
415                }});
416
417        registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
418
419        registerService(WIFI_SERVICE, new ServiceFetcher() {
420                public Object createService(ContextImpl ctx) {
421                    IBinder b = ServiceManager.getService(WIFI_SERVICE);
422                    IWifiManager service = IWifiManager.Stub.asInterface(b);
423                    return new WifiManager(service, ctx.mMainThread.getHandler());
424                }});
425
426        registerService(WINDOW_SERVICE, new ServiceFetcher() {
427                public Object getService(ContextImpl ctx) {
428                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
429                }});
430    }
431
432    static ContextImpl getImpl(Context context) {
433        Context nextContext;
434        while ((context instanceof ContextWrapper) &&
435                (nextContext=((ContextWrapper)context).getBaseContext()) != null) {
436            context = nextContext;
437        }
438        return (ContextImpl)context;
439    }
440
441    // The system service cache for the system services that are
442    // cached per-ContextImpl.  Package-scoped to avoid accessor
443    // methods.
444    final ArrayList<Object> mServiceCache = new ArrayList<Object>();
445
446    @Override
447    public AssetManager getAssets() {
448        return mResources.getAssets();
449    }
450
451    @Override
452    public Resources getResources() {
453        return mResources;
454    }
455
456    @Override
457    public PackageManager getPackageManager() {
458        if (mPackageManager != null) {
459            return mPackageManager;
460        }
461
462        IPackageManager pm = ActivityThread.getPackageManager();
463        if (pm != null) {
464            // Doesn't matter if we make more than one instance.
465            return (mPackageManager = new ApplicationPackageManager(this, pm));
466        }
467
468        return null;
469    }
470
471    @Override
472    public ContentResolver getContentResolver() {
473        return mContentResolver;
474    }
475
476    @Override
477    public Looper getMainLooper() {
478        return mMainThread.getLooper();
479    }
480
481    @Override
482    public Context getApplicationContext() {
483        return (mPackageInfo != null) ?
484                mPackageInfo.getApplication() : mMainThread.getApplication();
485    }
486
487    @Override
488    public void setTheme(int resid) {
489        mThemeResource = resid;
490    }
491
492    @Override
493    public int getThemeResId() {
494        return mThemeResource;
495    }
496
497    @Override
498    public Resources.Theme getTheme() {
499        if (mTheme == null) {
500            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
501                    getOuterContext().getApplicationInfo().targetSdkVersion);
502            mTheme = mResources.newTheme();
503            mTheme.applyStyle(mThemeResource, true);
504        }
505        return mTheme;
506    }
507
508    @Override
509    public ClassLoader getClassLoader() {
510        return mPackageInfo != null ?
511                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
512    }
513
514    @Override
515    public String getPackageName() {
516        if (mPackageInfo != null) {
517            return mPackageInfo.getPackageName();
518        }
519        throw new RuntimeException("Not supported in system context");
520    }
521
522    @Override
523    public ApplicationInfo getApplicationInfo() {
524        if (mPackageInfo != null) {
525            return mPackageInfo.getApplicationInfo();
526        }
527        throw new RuntimeException("Not supported in system context");
528    }
529
530    @Override
531    public String getPackageResourcePath() {
532        if (mPackageInfo != null) {
533            return mPackageInfo.getResDir();
534        }
535        throw new RuntimeException("Not supported in system context");
536    }
537
538    @Override
539    public String getPackageCodePath() {
540        if (mPackageInfo != null) {
541            return mPackageInfo.getAppDir();
542        }
543        throw new RuntimeException("Not supported in system context");
544    }
545
546    public File getSharedPrefsFile(String name) {
547        return makeFilename(getPreferencesDir(), name + ".xml");
548    }
549
550    @Override
551    public SharedPreferences getSharedPreferences(String name, int mode) {
552        SharedPreferencesImpl sp;
553        synchronized (sSharedPrefs) {
554            sp = sSharedPrefs.get(name);
555            if (sp == null) {
556                File prefsFile = getSharedPrefsFile(name);
557                sp = new SharedPreferencesImpl(prefsFile, mode);
558                sSharedPrefs.put(name, sp);
559                return sp;
560            }
561        }
562        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
563            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
564            // If somebody else (some other process) changed the prefs
565            // file behind our back, we reload it.  This has been the
566            // historical (if undocumented) behavior.
567            sp.startReloadIfChangedUnexpectedly();
568        }
569        return sp;
570    }
571
572    private File getPreferencesDir() {
573        synchronized (mSync) {
574            if (mPreferencesDir == null) {
575                mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
576            }
577            return mPreferencesDir;
578        }
579    }
580
581    @Override
582    public FileInputStream openFileInput(String name)
583        throws FileNotFoundException {
584        File f = makeFilename(getFilesDir(), name);
585        return new FileInputStream(f);
586    }
587
588    @Override
589    public FileOutputStream openFileOutput(String name, int mode)
590        throws FileNotFoundException {
591        final boolean append = (mode&MODE_APPEND) != 0;
592        File f = makeFilename(getFilesDir(), name);
593        try {
594            FileOutputStream fos = new FileOutputStream(f, append);
595            setFilePermissionsFromMode(f.getPath(), mode, 0);
596            return fos;
597        } catch (FileNotFoundException e) {
598        }
599
600        File parent = f.getParentFile();
601        parent.mkdir();
602        FileUtils.setPermissions(
603            parent.getPath(),
604            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
605            -1, -1);
606        FileOutputStream fos = new FileOutputStream(f, append);
607        setFilePermissionsFromMode(f.getPath(), mode, 0);
608        return fos;
609    }
610
611    @Override
612    public boolean deleteFile(String name) {
613        File f = makeFilename(getFilesDir(), name);
614        return f.delete();
615    }
616
617    @Override
618    public File getFilesDir() {
619        synchronized (mSync) {
620            if (mFilesDir == null) {
621                mFilesDir = new File(getDataDirFile(), "files");
622            }
623            if (!mFilesDir.exists()) {
624                if(!mFilesDir.mkdirs()) {
625                    Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
626                    return null;
627                }
628                FileUtils.setPermissions(
629                        mFilesDir.getPath(),
630                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
631                        -1, -1);
632            }
633            return mFilesDir;
634        }
635    }
636
637    @Override
638    public File getExternalFilesDir(String type) {
639        synchronized (mSync) {
640            if (mExternalFilesDir == null) {
641                mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
642                        getPackageName());
643            }
644            if (!mExternalFilesDir.exists()) {
645                try {
646                    (new File(Environment.getExternalStorageAndroidDataDir(),
647                            ".nomedia")).createNewFile();
648                } catch (IOException e) {
649                }
650                if (!mExternalFilesDir.mkdirs()) {
651                    Log.w(TAG, "Unable to create external files directory");
652                    return null;
653                }
654            }
655            if (type == null) {
656                return mExternalFilesDir;
657            }
658            File dir = new File(mExternalFilesDir, type);
659            if (!dir.exists()) {
660                if (!dir.mkdirs()) {
661                    Log.w(TAG, "Unable to create external media directory " + dir);
662                    return null;
663                }
664            }
665            return dir;
666        }
667    }
668
669    @Override
670    public File getObbDir() {
671        synchronized (mSync) {
672            if (mObbDir == null) {
673                mObbDir = Environment.getExternalStorageAppObbDirectory(
674                        getPackageName());
675            }
676            return mObbDir;
677        }
678    }
679
680    @Override
681    public File getCacheDir() {
682        synchronized (mSync) {
683            if (mCacheDir == null) {
684                mCacheDir = new File(getDataDirFile(), "cache");
685            }
686            if (!mCacheDir.exists()) {
687                if(!mCacheDir.mkdirs()) {
688                    Log.w(TAG, "Unable to create cache directory");
689                    return null;
690                }
691                FileUtils.setPermissions(
692                        mCacheDir.getPath(),
693                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
694                        -1, -1);
695            }
696        }
697        return mCacheDir;
698    }
699
700    @Override
701    public File getExternalCacheDir() {
702        synchronized (mSync) {
703            if (mExternalCacheDir == null) {
704                mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
705                        getPackageName());
706            }
707            if (!mExternalCacheDir.exists()) {
708                try {
709                    (new File(Environment.getExternalStorageAndroidDataDir(),
710                            ".nomedia")).createNewFile();
711                } catch (IOException e) {
712                }
713                if (!mExternalCacheDir.mkdirs()) {
714                    Log.w(TAG, "Unable to create external cache directory");
715                    return null;
716                }
717            }
718            return mExternalCacheDir;
719        }
720    }
721
722    @Override
723    public File getFileStreamPath(String name) {
724        return makeFilename(getFilesDir(), name);
725    }
726
727    @Override
728    public String[] fileList() {
729        final String[] list = getFilesDir().list();
730        return (list != null) ? list : EMPTY_FILE_LIST;
731    }
732
733    @Override
734    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
735        File f = validateFilePath(name, true);
736        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
737        setFilePermissionsFromMode(f.getPath(), mode, 0);
738        return db;
739    }
740
741    @Override
742    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
743            DatabaseErrorHandler errorHandler) {
744        File f = validateFilePath(name, true);
745        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
746        setFilePermissionsFromMode(f.getPath(), mode, 0);
747        return db;
748    }
749
750    @Override
751    public boolean deleteDatabase(String name) {
752        try {
753            File f = validateFilePath(name, false);
754            return f.delete();
755        } catch (Exception e) {
756        }
757        return false;
758    }
759
760    @Override
761    public File getDatabasePath(String name) {
762        return validateFilePath(name, false);
763    }
764
765    @Override
766    public String[] databaseList() {
767        final String[] list = getDatabasesDir().list();
768        return (list != null) ? list : EMPTY_FILE_LIST;
769    }
770
771
772    private File getDatabasesDir() {
773        synchronized (mSync) {
774            if (mDatabasesDir == null) {
775                mDatabasesDir = new File(getDataDirFile(), "databases");
776            }
777            if (mDatabasesDir.getPath().equals("databases")) {
778                mDatabasesDir = new File("/data/system");
779            }
780            return mDatabasesDir;
781        }
782    }
783
784    @Override
785    public Drawable getWallpaper() {
786        return getWallpaperManager().getDrawable();
787    }
788
789    @Override
790    public Drawable peekWallpaper() {
791        return getWallpaperManager().peekDrawable();
792    }
793
794    @Override
795    public int getWallpaperDesiredMinimumWidth() {
796        return getWallpaperManager().getDesiredMinimumWidth();
797    }
798
799    @Override
800    public int getWallpaperDesiredMinimumHeight() {
801        return getWallpaperManager().getDesiredMinimumHeight();
802    }
803
804    @Override
805    public void setWallpaper(Bitmap bitmap) throws IOException  {
806        getWallpaperManager().setBitmap(bitmap);
807    }
808
809    @Override
810    public void setWallpaper(InputStream data) throws IOException {
811        getWallpaperManager().setStream(data);
812    }
813
814    @Override
815    public void clearWallpaper() throws IOException {
816        getWallpaperManager().clear();
817    }
818
819    @Override
820    public void startActivity(Intent intent) {
821        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
822            throw new AndroidRuntimeException(
823                    "Calling startActivity() from outside of an Activity "
824                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
825                    + " Is this really what you want?");
826        }
827        mMainThread.getInstrumentation().execStartActivity(
828            getOuterContext(), mMainThread.getApplicationThread(), null,
829            (Activity)null, intent, -1);
830    }
831
832    @Override
833    public void startActivities(Intent[] intents) {
834        if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
835            throw new AndroidRuntimeException(
836                    "Calling startActivities() from outside of an Activity "
837                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
838                    + " Is this really what you want?");
839        }
840        mMainThread.getInstrumentation().execStartActivities(
841            getOuterContext(), mMainThread.getApplicationThread(), null,
842            (Activity)null, intents);
843    }
844
845    @Override
846    public void startIntentSender(IntentSender intent,
847            Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
848            throws IntentSender.SendIntentException {
849        try {
850            String resolvedType = null;
851            if (fillInIntent != null) {
852                resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
853            }
854            int result = ActivityManagerNative.getDefault()
855                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
856                        fillInIntent, resolvedType, null, null,
857                        0, flagsMask, flagsValues);
858            if (result == IActivityManager.START_CANCELED) {
859                throw new IntentSender.SendIntentException();
860            }
861            Instrumentation.checkStartActivityResult(result, null);
862        } catch (RemoteException e) {
863        }
864    }
865
866    @Override
867    public void sendBroadcast(Intent intent) {
868        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
869        try {
870            ActivityManagerNative.getDefault().broadcastIntent(
871                mMainThread.getApplicationThread(), intent, resolvedType, null,
872                Activity.RESULT_OK, null, null, null, false, false);
873        } catch (RemoteException e) {
874        }
875    }
876
877    @Override
878    public void sendBroadcast(Intent intent, String receiverPermission) {
879        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
880        try {
881            ActivityManagerNative.getDefault().broadcastIntent(
882                mMainThread.getApplicationThread(), intent, resolvedType, null,
883                Activity.RESULT_OK, null, null, receiverPermission, false, false);
884        } catch (RemoteException e) {
885        }
886    }
887
888    @Override
889    public void sendOrderedBroadcast(Intent intent,
890            String receiverPermission) {
891        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
892        try {
893            ActivityManagerNative.getDefault().broadcastIntent(
894                mMainThread.getApplicationThread(), intent, resolvedType, null,
895                Activity.RESULT_OK, null, null, receiverPermission, true, false);
896        } catch (RemoteException e) {
897        }
898    }
899
900    @Override
901    public void sendOrderedBroadcast(Intent intent,
902            String receiverPermission, BroadcastReceiver resultReceiver,
903            Handler scheduler, int initialCode, String initialData,
904            Bundle initialExtras) {
905        IIntentReceiver rd = null;
906        if (resultReceiver != null) {
907            if (mPackageInfo != null) {
908                if (scheduler == null) {
909                    scheduler = mMainThread.getHandler();
910                }
911                rd = mPackageInfo.getReceiverDispatcher(
912                    resultReceiver, getOuterContext(), scheduler,
913                    mMainThread.getInstrumentation(), false);
914            } else {
915                if (scheduler == null) {
916                    scheduler = mMainThread.getHandler();
917                }
918                rd = new LoadedApk.ReceiverDispatcher(
919                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
920            }
921        }
922        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
923        try {
924            ActivityManagerNative.getDefault().broadcastIntent(
925                mMainThread.getApplicationThread(), intent, resolvedType, rd,
926                initialCode, initialData, initialExtras, receiverPermission,
927                true, false);
928        } catch (RemoteException e) {
929        }
930    }
931
932    @Override
933    public void sendStickyBroadcast(Intent intent) {
934        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
935        try {
936            ActivityManagerNative.getDefault().broadcastIntent(
937                mMainThread.getApplicationThread(), intent, resolvedType, null,
938                Activity.RESULT_OK, null, null, null, false, true);
939        } catch (RemoteException e) {
940        }
941    }
942
943    @Override
944    public void sendStickyOrderedBroadcast(Intent intent,
945            BroadcastReceiver resultReceiver,
946            Handler scheduler, int initialCode, String initialData,
947            Bundle initialExtras) {
948        IIntentReceiver rd = null;
949        if (resultReceiver != null) {
950            if (mPackageInfo != null) {
951                if (scheduler == null) {
952                    scheduler = mMainThread.getHandler();
953                }
954                rd = mPackageInfo.getReceiverDispatcher(
955                    resultReceiver, getOuterContext(), scheduler,
956                    mMainThread.getInstrumentation(), false);
957            } else {
958                if (scheduler == null) {
959                    scheduler = mMainThread.getHandler();
960                }
961                rd = new LoadedApk.ReceiverDispatcher(
962                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
963            }
964        }
965        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
966        try {
967            ActivityManagerNative.getDefault().broadcastIntent(
968                mMainThread.getApplicationThread(), intent, resolvedType, rd,
969                initialCode, initialData, initialExtras, null,
970                true, true);
971        } catch (RemoteException e) {
972        }
973    }
974
975    @Override
976    public void removeStickyBroadcast(Intent intent) {
977        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
978        if (resolvedType != null) {
979            intent = new Intent(intent);
980            intent.setDataAndType(intent.getData(), resolvedType);
981        }
982        try {
983            ActivityManagerNative.getDefault().unbroadcastIntent(
984                mMainThread.getApplicationThread(), intent);
985        } catch (RemoteException e) {
986        }
987    }
988
989    @Override
990    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
991        return registerReceiver(receiver, filter, null, null);
992    }
993
994    @Override
995    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
996            String broadcastPermission, Handler scheduler) {
997        return registerReceiverInternal(receiver, filter, broadcastPermission,
998                scheduler, getOuterContext());
999    }
1000
1001    private Intent registerReceiverInternal(BroadcastReceiver receiver,
1002            IntentFilter filter, String broadcastPermission,
1003            Handler scheduler, Context context) {
1004        IIntentReceiver rd = null;
1005        if (receiver != null) {
1006            if (mPackageInfo != null && context != null) {
1007                if (scheduler == null) {
1008                    scheduler = mMainThread.getHandler();
1009                }
1010                rd = mPackageInfo.getReceiverDispatcher(
1011                    receiver, context, scheduler,
1012                    mMainThread.getInstrumentation(), true);
1013            } else {
1014                if (scheduler == null) {
1015                    scheduler = mMainThread.getHandler();
1016                }
1017                rd = new LoadedApk.ReceiverDispatcher(
1018                        receiver, context, scheduler, null, true).getIIntentReceiver();
1019            }
1020        }
1021        try {
1022            return ActivityManagerNative.getDefault().registerReceiver(
1023                    mMainThread.getApplicationThread(),
1024                    rd, filter, broadcastPermission);
1025        } catch (RemoteException e) {
1026            return null;
1027        }
1028    }
1029
1030    @Override
1031    public void unregisterReceiver(BroadcastReceiver receiver) {
1032        if (mPackageInfo != null) {
1033            IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
1034                    getOuterContext(), receiver);
1035            try {
1036                ActivityManagerNative.getDefault().unregisterReceiver(rd);
1037            } catch (RemoteException e) {
1038            }
1039        } else {
1040            throw new RuntimeException("Not supported in system context");
1041        }
1042    }
1043
1044    @Override
1045    public ComponentName startService(Intent service) {
1046        try {
1047            ComponentName cn = ActivityManagerNative.getDefault().startService(
1048                mMainThread.getApplicationThread(), service,
1049                service.resolveTypeIfNeeded(getContentResolver()));
1050            if (cn != null && cn.getPackageName().equals("!")) {
1051                throw new SecurityException(
1052                        "Not allowed to start service " + service
1053                        + " without permission " + cn.getClassName());
1054            }
1055            return cn;
1056        } catch (RemoteException e) {
1057            return null;
1058        }
1059    }
1060
1061    @Override
1062    public boolean stopService(Intent service) {
1063        try {
1064            int res = ActivityManagerNative.getDefault().stopService(
1065                mMainThread.getApplicationThread(), service,
1066                service.resolveTypeIfNeeded(getContentResolver()));
1067            if (res < 0) {
1068                throw new SecurityException(
1069                        "Not allowed to stop service " + service);
1070            }
1071            return res != 0;
1072        } catch (RemoteException e) {
1073            return false;
1074        }
1075    }
1076
1077    @Override
1078    public boolean bindService(Intent service, ServiceConnection conn,
1079            int flags) {
1080        IServiceConnection sd;
1081        if (mPackageInfo != null) {
1082            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1083                    mMainThread.getHandler(), flags);
1084        } else {
1085            throw new RuntimeException("Not supported in system context");
1086        }
1087        try {
1088            int res = ActivityManagerNative.getDefault().bindService(
1089                mMainThread.getApplicationThread(), getActivityToken(),
1090                service, service.resolveTypeIfNeeded(getContentResolver()),
1091                sd, flags);
1092            if (res < 0) {
1093                throw new SecurityException(
1094                        "Not allowed to bind to service " + service);
1095            }
1096            return res != 0;
1097        } catch (RemoteException e) {
1098            return false;
1099        }
1100    }
1101
1102    @Override
1103    public void unbindService(ServiceConnection conn) {
1104        if (mPackageInfo != null) {
1105            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1106                    getOuterContext(), conn);
1107            try {
1108                ActivityManagerNative.getDefault().unbindService(sd);
1109            } catch (RemoteException e) {
1110            }
1111        } else {
1112            throw new RuntimeException("Not supported in system context");
1113        }
1114    }
1115
1116    @Override
1117    public boolean startInstrumentation(ComponentName className,
1118            String profileFile, Bundle arguments) {
1119        try {
1120            return ActivityManagerNative.getDefault().startInstrumentation(
1121                    className, profileFile, 0, arguments, null);
1122        } catch (RemoteException e) {
1123            // System has crashed, nothing we can do.
1124        }
1125        return false;
1126    }
1127
1128    @Override
1129    public Object getSystemService(String name) {
1130        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
1131        return fetcher == null ? null : fetcher.getService(this);
1132    }
1133
1134    private WallpaperManager getWallpaperManager() {
1135        return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
1136    }
1137
1138    /* package */ static DropBoxManager createDropBoxManager() {
1139        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1140        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1141        if (service == null) {
1142            // Don't return a DropBoxManager that will NPE upon use.
1143            // This also avoids caching a broken DropBoxManager in
1144            // getDropBoxManager during early boot, before the
1145            // DROPBOX_SERVICE is registered.
1146            return null;
1147        }
1148        return new DropBoxManager(service);
1149    }
1150
1151    @Override
1152    public int checkPermission(String permission, int pid, int uid) {
1153        if (permission == null) {
1154            throw new IllegalArgumentException("permission is null");
1155        }
1156
1157        if (!Process.supportsProcesses()) {
1158            return PackageManager.PERMISSION_GRANTED;
1159        }
1160        try {
1161            return ActivityManagerNative.getDefault().checkPermission(
1162                    permission, pid, uid);
1163        } catch (RemoteException e) {
1164            return PackageManager.PERMISSION_DENIED;
1165        }
1166    }
1167
1168    @Override
1169    public int checkCallingPermission(String permission) {
1170        if (permission == null) {
1171            throw new IllegalArgumentException("permission is null");
1172        }
1173
1174        if (!Process.supportsProcesses()) {
1175            return PackageManager.PERMISSION_GRANTED;
1176        }
1177        int pid = Binder.getCallingPid();
1178        if (pid != Process.myPid()) {
1179            return checkPermission(permission, pid,
1180                    Binder.getCallingUid());
1181        }
1182        return PackageManager.PERMISSION_DENIED;
1183    }
1184
1185    @Override
1186    public int checkCallingOrSelfPermission(String permission) {
1187        if (permission == null) {
1188            throw new IllegalArgumentException("permission is null");
1189        }
1190
1191        return checkPermission(permission, Binder.getCallingPid(),
1192                Binder.getCallingUid());
1193    }
1194
1195    private void enforce(
1196            String permission, int resultOfCheck,
1197            boolean selfToo, int uid, String message) {
1198        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1199            throw new SecurityException(
1200                    (message != null ? (message + ": ") : "") +
1201                    (selfToo
1202                     ? "Neither user " + uid + " nor current process has "
1203                     : "User " + uid + " does not have ") +
1204                    permission +
1205                    ".");
1206        }
1207    }
1208
1209    public void enforcePermission(
1210            String permission, int pid, int uid, String message) {
1211        enforce(permission,
1212                checkPermission(permission, pid, uid),
1213                false,
1214                uid,
1215                message);
1216    }
1217
1218    public void enforceCallingPermission(String permission, String message) {
1219        enforce(permission,
1220                checkCallingPermission(permission),
1221                false,
1222                Binder.getCallingUid(),
1223                message);
1224    }
1225
1226    public void enforceCallingOrSelfPermission(
1227            String permission, String message) {
1228        enforce(permission,
1229                checkCallingOrSelfPermission(permission),
1230                true,
1231                Binder.getCallingUid(),
1232                message);
1233    }
1234
1235    @Override
1236    public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1237         try {
1238            ActivityManagerNative.getDefault().grantUriPermission(
1239                    mMainThread.getApplicationThread(), toPackage, uri,
1240                    modeFlags);
1241        } catch (RemoteException e) {
1242        }
1243    }
1244
1245    @Override
1246    public void revokeUriPermission(Uri uri, int modeFlags) {
1247         try {
1248            ActivityManagerNative.getDefault().revokeUriPermission(
1249                    mMainThread.getApplicationThread(), uri,
1250                    modeFlags);
1251        } catch (RemoteException e) {
1252        }
1253    }
1254
1255    @Override
1256    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1257        if (!Process.supportsProcesses()) {
1258            return PackageManager.PERMISSION_GRANTED;
1259        }
1260        try {
1261            return ActivityManagerNative.getDefault().checkUriPermission(
1262                    uri, pid, uid, modeFlags);
1263        } catch (RemoteException e) {
1264            return PackageManager.PERMISSION_DENIED;
1265        }
1266    }
1267
1268    @Override
1269    public int checkCallingUriPermission(Uri uri, int modeFlags) {
1270        if (!Process.supportsProcesses()) {
1271            return PackageManager.PERMISSION_GRANTED;
1272        }
1273        int pid = Binder.getCallingPid();
1274        if (pid != Process.myPid()) {
1275            return checkUriPermission(uri, pid,
1276                    Binder.getCallingUid(), modeFlags);
1277        }
1278        return PackageManager.PERMISSION_DENIED;
1279    }
1280
1281    @Override
1282    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1283        return checkUriPermission(uri, Binder.getCallingPid(),
1284                Binder.getCallingUid(), modeFlags);
1285    }
1286
1287    @Override
1288    public int checkUriPermission(Uri uri, String readPermission,
1289            String writePermission, int pid, int uid, int modeFlags) {
1290        if (DEBUG) {
1291            Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1292                    + readPermission + " writePermission=" + writePermission
1293                    + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1294        }
1295        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1296            if (readPermission == null
1297                    || checkPermission(readPermission, pid, uid)
1298                    == PackageManager.PERMISSION_GRANTED) {
1299                return PackageManager.PERMISSION_GRANTED;
1300            }
1301        }
1302        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1303            if (writePermission == null
1304                    || checkPermission(writePermission, pid, uid)
1305                    == PackageManager.PERMISSION_GRANTED) {
1306                return PackageManager.PERMISSION_GRANTED;
1307            }
1308        }
1309        return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1310                : PackageManager.PERMISSION_DENIED;
1311    }
1312
1313    private String uriModeFlagToString(int uriModeFlags) {
1314        switch (uriModeFlags) {
1315            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1316                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1317                return "read and write";
1318            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1319                return "read";
1320            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1321                return "write";
1322        }
1323        throw new IllegalArgumentException(
1324                "Unknown permission mode flags: " + uriModeFlags);
1325    }
1326
1327    private void enforceForUri(
1328            int modeFlags, int resultOfCheck, boolean selfToo,
1329            int uid, Uri uri, String message) {
1330        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1331            throw new SecurityException(
1332                    (message != null ? (message + ": ") : "") +
1333                    (selfToo
1334                     ? "Neither user " + uid + " nor current process has "
1335                     : "User " + uid + " does not have ") +
1336                    uriModeFlagToString(modeFlags) +
1337                    " permission on " +
1338                    uri +
1339                    ".");
1340        }
1341    }
1342
1343    public void enforceUriPermission(
1344            Uri uri, int pid, int uid, int modeFlags, String message) {
1345        enforceForUri(
1346                modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1347                false, uid, uri, message);
1348    }
1349
1350    public void enforceCallingUriPermission(
1351            Uri uri, int modeFlags, String message) {
1352        enforceForUri(
1353                modeFlags, checkCallingUriPermission(uri, modeFlags),
1354                false, Binder.getCallingUid(), uri, message);
1355    }
1356
1357    public void enforceCallingOrSelfUriPermission(
1358            Uri uri, int modeFlags, String message) {
1359        enforceForUri(
1360                modeFlags,
1361                checkCallingOrSelfUriPermission(uri, modeFlags), true,
1362                Binder.getCallingUid(), uri, message);
1363    }
1364
1365    public void enforceUriPermission(
1366            Uri uri, String readPermission, String writePermission,
1367            int pid, int uid, int modeFlags, String message) {
1368        enforceForUri(modeFlags,
1369                      checkUriPermission(
1370                              uri, readPermission, writePermission, pid, uid,
1371                              modeFlags),
1372                      false,
1373                      uid,
1374                      uri,
1375                      message);
1376    }
1377
1378    @Override
1379    public Context createPackageContext(String packageName, int flags)
1380        throws PackageManager.NameNotFoundException {
1381        if (packageName.equals("system") || packageName.equals("android")) {
1382            return new ContextImpl(mMainThread.getSystemContext());
1383        }
1384
1385        LoadedApk pi =
1386            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
1387        if (pi != null) {
1388            ContextImpl c = new ContextImpl();
1389            c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
1390            c.init(pi, null, mMainThread, mResources);
1391            if (c.mResources != null) {
1392                return c;
1393            }
1394        }
1395
1396        // Should be a better exception.
1397        throw new PackageManager.NameNotFoundException(
1398            "Application package " + packageName + " not found");
1399    }
1400
1401    @Override
1402    public boolean isRestricted() {
1403        return mRestricted;
1404    }
1405
1406    private File getDataDirFile() {
1407        if (mPackageInfo != null) {
1408            return mPackageInfo.getDataDirFile();
1409        }
1410        throw new RuntimeException("Not supported in system context");
1411    }
1412
1413    @Override
1414    public File getDir(String name, int mode) {
1415        name = "app_" + name;
1416        File file = makeFilename(getDataDirFile(), name);
1417        if (!file.exists()) {
1418            file.mkdir();
1419            setFilePermissionsFromMode(file.getPath(), mode,
1420                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1421        }
1422        return file;
1423    }
1424
1425    static ContextImpl createSystemContext(ActivityThread mainThread) {
1426        ContextImpl context = new ContextImpl();
1427        context.init(Resources.getSystem(), mainThread);
1428        return context;
1429    }
1430
1431    ContextImpl() {
1432        mOuterContext = this;
1433    }
1434
1435    /**
1436     * Create a new ApplicationContext from an existing one.  The new one
1437     * works and operates the same as the one it is copying.
1438     *
1439     * @param context Existing application context.
1440     */
1441    public ContextImpl(ContextImpl context) {
1442        mPackageInfo = context.mPackageInfo;
1443        mResources = context.mResources;
1444        mMainThread = context.mMainThread;
1445        mContentResolver = context.mContentResolver;
1446        mOuterContext = this;
1447    }
1448
1449    final void init(LoadedApk packageInfo,
1450            IBinder activityToken, ActivityThread mainThread) {
1451        init(packageInfo, activityToken, mainThread, null);
1452    }
1453
1454    final void init(LoadedApk packageInfo,
1455                IBinder activityToken, ActivityThread mainThread,
1456                Resources container) {
1457        mPackageInfo = packageInfo;
1458        mResources = mPackageInfo.getResources(mainThread);
1459
1460        if (mResources != null && container != null
1461                && container.getCompatibilityInfo().applicationScale !=
1462                        mResources.getCompatibilityInfo().applicationScale) {
1463            if (DEBUG) {
1464                Log.d(TAG, "loaded context has different scaling. Using container's" +
1465                        " compatiblity info:" + container.getDisplayMetrics());
1466            }
1467            mResources = mainThread.getTopLevelResources(
1468                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
1469        }
1470        mMainThread = mainThread;
1471        mContentResolver = new ApplicationContentResolver(this, mainThread);
1472
1473        setActivityToken(activityToken);
1474    }
1475
1476    final void init(Resources resources, ActivityThread mainThread) {
1477        mPackageInfo = null;
1478        mResources = resources;
1479        mMainThread = mainThread;
1480        mContentResolver = new ApplicationContentResolver(this, mainThread);
1481    }
1482
1483    final void scheduleFinalCleanup(String who, String what) {
1484        mMainThread.scheduleContextCleanup(this, who, what);
1485    }
1486
1487    final void performFinalCleanup(String who, String what) {
1488        //Log.i(TAG, "Cleanup up context: " + this);
1489        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1490    }
1491
1492    final Context getReceiverRestrictedContext() {
1493        if (mReceiverRestrictedContext != null) {
1494            return mReceiverRestrictedContext;
1495        }
1496        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1497    }
1498
1499    final void setActivityToken(IBinder token) {
1500        mActivityToken = token;
1501    }
1502
1503    final void setOuterContext(Context context) {
1504        mOuterContext = context;
1505    }
1506
1507    final Context getOuterContext() {
1508        return mOuterContext;
1509    }
1510
1511    final IBinder getActivityToken() {
1512        return mActivityToken;
1513    }
1514
1515    static void setFilePermissionsFromMode(String name, int mode,
1516            int extraPermissions) {
1517        int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1518            |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1519            |extraPermissions;
1520        if ((mode&MODE_WORLD_READABLE) != 0) {
1521            perms |= FileUtils.S_IROTH;
1522        }
1523        if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1524            perms |= FileUtils.S_IWOTH;
1525        }
1526        if (DEBUG) {
1527            Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1528                  + ", perms=0x" + Integer.toHexString(perms));
1529        }
1530        FileUtils.setPermissions(name, perms, -1, -1);
1531    }
1532
1533    private File validateFilePath(String name, boolean createDirectory) {
1534        File dir;
1535        File f;
1536
1537        if (name.charAt(0) == File.separatorChar) {
1538            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1539            dir = new File(dirPath);
1540            name = name.substring(name.lastIndexOf(File.separatorChar));
1541            f = new File(dir, name);
1542        } else {
1543            dir = getDatabasesDir();
1544            f = makeFilename(dir, name);
1545        }
1546
1547        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1548            FileUtils.setPermissions(dir.getPath(),
1549                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1550                -1, -1);
1551        }
1552
1553        return f;
1554    }
1555
1556    private File makeFilename(File base, String name) {
1557        if (name.indexOf(File.separatorChar) < 0) {
1558            return new File(base, name);
1559        }
1560        throw new IllegalArgumentException(
1561                "File " + name + " contains a path separator");
1562    }
1563
1564    // ----------------------------------------------------------------------
1565    // ----------------------------------------------------------------------
1566    // ----------------------------------------------------------------------
1567
1568    private static final class ApplicationContentResolver extends ContentResolver {
1569        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
1570            super(context);
1571            mMainThread = mainThread;
1572        }
1573
1574        @Override
1575        protected IContentProvider acquireProvider(Context context, String name) {
1576            return mMainThread.acquireProvider(context, name);
1577        }
1578
1579        @Override
1580        protected IContentProvider acquireExistingProvider(Context context, String name) {
1581            return mMainThread.acquireExistingProvider(context, name);
1582        }
1583
1584        @Override
1585        public boolean releaseProvider(IContentProvider provider) {
1586            return mMainThread.releaseProvider(provider);
1587        }
1588
1589        private final ActivityThread mMainThread;
1590    }
1591}
1592