ContextImpl.java revision 5be8de3420ba4c9d816b98e29bdec11715f6b626
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                    RuntimeException e = new RuntimeException("foo");
429                    e.fillInStackTrace();
430                    Log.i(TAG, "Getting window manager", e);
431                    CompatibilityInfo ci = ctx.mResources.getCompatibilityInfo();
432                    return WindowManagerImpl.getDefault(ci);
433                }});
434    }
435
436    // The system service cache for the system services that are
437    // cached per-ContextImpl.  Package-scoped to avoid accessor
438    // methods.
439    final ArrayList<Object> mServiceCache = new ArrayList<Object>();
440
441    @Override
442    public AssetManager getAssets() {
443        return mResources.getAssets();
444    }
445
446    @Override
447    public Resources getResources() {
448        return mResources;
449    }
450
451    @Override
452    public PackageManager getPackageManager() {
453        if (mPackageManager != null) {
454            return mPackageManager;
455        }
456
457        IPackageManager pm = ActivityThread.getPackageManager();
458        if (pm != null) {
459            // Doesn't matter if we make more than one instance.
460            return (mPackageManager = new ApplicationPackageManager(this, pm));
461        }
462
463        return null;
464    }
465
466    @Override
467    public ContentResolver getContentResolver() {
468        return mContentResolver;
469    }
470
471    @Override
472    public Looper getMainLooper() {
473        return mMainThread.getLooper();
474    }
475
476    @Override
477    public Context getApplicationContext() {
478        return (mPackageInfo != null) ?
479                mPackageInfo.getApplication() : mMainThread.getApplication();
480    }
481
482    @Override
483    public void setTheme(int resid) {
484        mThemeResource = resid;
485    }
486
487    @Override
488    public int getThemeResId() {
489        return mThemeResource;
490    }
491
492    @Override
493    public Resources.Theme getTheme() {
494        if (mTheme == null) {
495            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
496                    getOuterContext().getApplicationInfo().targetSdkVersion);
497            mTheme = mResources.newTheme();
498            mTheme.applyStyle(mThemeResource, true);
499        }
500        return mTheme;
501    }
502
503    @Override
504    public ClassLoader getClassLoader() {
505        return mPackageInfo != null ?
506                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
507    }
508
509    @Override
510    public String getPackageName() {
511        if (mPackageInfo != null) {
512            return mPackageInfo.getPackageName();
513        }
514        throw new RuntimeException("Not supported in system context");
515    }
516
517    @Override
518    public ApplicationInfo getApplicationInfo() {
519        if (mPackageInfo != null) {
520            return mPackageInfo.getApplicationInfo();
521        }
522        throw new RuntimeException("Not supported in system context");
523    }
524
525    @Override
526    public String getPackageResourcePath() {
527        if (mPackageInfo != null) {
528            return mPackageInfo.getResDir();
529        }
530        throw new RuntimeException("Not supported in system context");
531    }
532
533    @Override
534    public String getPackageCodePath() {
535        if (mPackageInfo != null) {
536            return mPackageInfo.getAppDir();
537        }
538        throw new RuntimeException("Not supported in system context");
539    }
540
541    public File getSharedPrefsFile(String name) {
542        return makeFilename(getPreferencesDir(), name + ".xml");
543    }
544
545    @Override
546    public SharedPreferences getSharedPreferences(String name, int mode) {
547        SharedPreferencesImpl sp;
548        synchronized (sSharedPrefs) {
549            sp = sSharedPrefs.get(name);
550            if (sp == null) {
551                File prefsFile = getSharedPrefsFile(name);
552                sp = new SharedPreferencesImpl(prefsFile, mode);
553                sSharedPrefs.put(name, sp);
554                return sp;
555            }
556        }
557        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
558            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
559            // If somebody else (some other process) changed the prefs
560            // file behind our back, we reload it.  This has been the
561            // historical (if undocumented) behavior.
562            sp.startReloadIfChangedUnexpectedly();
563        }
564        return sp;
565    }
566
567    private File getPreferencesDir() {
568        synchronized (mSync) {
569            if (mPreferencesDir == null) {
570                mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
571            }
572            return mPreferencesDir;
573        }
574    }
575
576    @Override
577    public FileInputStream openFileInput(String name)
578        throws FileNotFoundException {
579        File f = makeFilename(getFilesDir(), name);
580        return new FileInputStream(f);
581    }
582
583    @Override
584    public FileOutputStream openFileOutput(String name, int mode)
585        throws FileNotFoundException {
586        final boolean append = (mode&MODE_APPEND) != 0;
587        File f = makeFilename(getFilesDir(), name);
588        try {
589            FileOutputStream fos = new FileOutputStream(f, append);
590            setFilePermissionsFromMode(f.getPath(), mode, 0);
591            return fos;
592        } catch (FileNotFoundException e) {
593        }
594
595        File parent = f.getParentFile();
596        parent.mkdir();
597        FileUtils.setPermissions(
598            parent.getPath(),
599            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
600            -1, -1);
601        FileOutputStream fos = new FileOutputStream(f, append);
602        setFilePermissionsFromMode(f.getPath(), mode, 0);
603        return fos;
604    }
605
606    @Override
607    public boolean deleteFile(String name) {
608        File f = makeFilename(getFilesDir(), name);
609        return f.delete();
610    }
611
612    @Override
613    public File getFilesDir() {
614        synchronized (mSync) {
615            if (mFilesDir == null) {
616                mFilesDir = new File(getDataDirFile(), "files");
617            }
618            if (!mFilesDir.exists()) {
619                if(!mFilesDir.mkdirs()) {
620                    Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
621                    return null;
622                }
623                FileUtils.setPermissions(
624                        mFilesDir.getPath(),
625                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
626                        -1, -1);
627            }
628            return mFilesDir;
629        }
630    }
631
632    @Override
633    public File getExternalFilesDir(String type) {
634        synchronized (mSync) {
635            if (mExternalFilesDir == null) {
636                mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
637                        getPackageName());
638            }
639            if (!mExternalFilesDir.exists()) {
640                try {
641                    (new File(Environment.getExternalStorageAndroidDataDir(),
642                            ".nomedia")).createNewFile();
643                } catch (IOException e) {
644                }
645                if (!mExternalFilesDir.mkdirs()) {
646                    Log.w(TAG, "Unable to create external files directory");
647                    return null;
648                }
649            }
650            if (type == null) {
651                return mExternalFilesDir;
652            }
653            File dir = new File(mExternalFilesDir, type);
654            if (!dir.exists()) {
655                if (!dir.mkdirs()) {
656                    Log.w(TAG, "Unable to create external media directory " + dir);
657                    return null;
658                }
659            }
660            return dir;
661        }
662    }
663
664    @Override
665    public File getObbDir() {
666        synchronized (mSync) {
667            if (mObbDir == null) {
668                mObbDir = Environment.getExternalStorageAppObbDirectory(
669                        getPackageName());
670            }
671            return mObbDir;
672        }
673    }
674
675    @Override
676    public File getCacheDir() {
677        synchronized (mSync) {
678            if (mCacheDir == null) {
679                mCacheDir = new File(getDataDirFile(), "cache");
680            }
681            if (!mCacheDir.exists()) {
682                if(!mCacheDir.mkdirs()) {
683                    Log.w(TAG, "Unable to create cache directory");
684                    return null;
685                }
686                FileUtils.setPermissions(
687                        mCacheDir.getPath(),
688                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
689                        -1, -1);
690            }
691        }
692        return mCacheDir;
693    }
694
695    @Override
696    public File getExternalCacheDir() {
697        synchronized (mSync) {
698            if (mExternalCacheDir == null) {
699                mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
700                        getPackageName());
701            }
702            if (!mExternalCacheDir.exists()) {
703                try {
704                    (new File(Environment.getExternalStorageAndroidDataDir(),
705                            ".nomedia")).createNewFile();
706                } catch (IOException e) {
707                }
708                if (!mExternalCacheDir.mkdirs()) {
709                    Log.w(TAG, "Unable to create external cache directory");
710                    return null;
711                }
712            }
713            return mExternalCacheDir;
714        }
715    }
716
717    @Override
718    public File getFileStreamPath(String name) {
719        return makeFilename(getFilesDir(), name);
720    }
721
722    @Override
723    public String[] fileList() {
724        final String[] list = getFilesDir().list();
725        return (list != null) ? list : EMPTY_FILE_LIST;
726    }
727
728    @Override
729    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
730        File f = validateFilePath(name, true);
731        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
732        setFilePermissionsFromMode(f.getPath(), mode, 0);
733        return db;
734    }
735
736    @Override
737    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
738            DatabaseErrorHandler errorHandler) {
739        File f = validateFilePath(name, true);
740        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
741        setFilePermissionsFromMode(f.getPath(), mode, 0);
742        return db;
743    }
744
745    @Override
746    public boolean deleteDatabase(String name) {
747        try {
748            File f = validateFilePath(name, false);
749            return f.delete();
750        } catch (Exception e) {
751        }
752        return false;
753    }
754
755    @Override
756    public File getDatabasePath(String name) {
757        return validateFilePath(name, false);
758    }
759
760    @Override
761    public String[] databaseList() {
762        final String[] list = getDatabasesDir().list();
763        return (list != null) ? list : EMPTY_FILE_LIST;
764    }
765
766
767    private File getDatabasesDir() {
768        synchronized (mSync) {
769            if (mDatabasesDir == null) {
770                mDatabasesDir = new File(getDataDirFile(), "databases");
771            }
772            if (mDatabasesDir.getPath().equals("databases")) {
773                mDatabasesDir = new File("/data/system");
774            }
775            return mDatabasesDir;
776        }
777    }
778
779    @Override
780    public Drawable getWallpaper() {
781        return getWallpaperManager().getDrawable();
782    }
783
784    @Override
785    public Drawable peekWallpaper() {
786        return getWallpaperManager().peekDrawable();
787    }
788
789    @Override
790    public int getWallpaperDesiredMinimumWidth() {
791        return getWallpaperManager().getDesiredMinimumWidth();
792    }
793
794    @Override
795    public int getWallpaperDesiredMinimumHeight() {
796        return getWallpaperManager().getDesiredMinimumHeight();
797    }
798
799    @Override
800    public void setWallpaper(Bitmap bitmap) throws IOException  {
801        getWallpaperManager().setBitmap(bitmap);
802    }
803
804    @Override
805    public void setWallpaper(InputStream data) throws IOException {
806        getWallpaperManager().setStream(data);
807    }
808
809    @Override
810    public void clearWallpaper() throws IOException {
811        getWallpaperManager().clear();
812    }
813
814    @Override
815    public void startActivity(Intent intent) {
816        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
817            throw new AndroidRuntimeException(
818                    "Calling startActivity() from outside of an Activity "
819                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
820                    + " Is this really what you want?");
821        }
822        mMainThread.getInstrumentation().execStartActivity(
823            getOuterContext(), mMainThread.getApplicationThread(), null,
824            (Activity)null, intent, -1);
825    }
826
827    @Override
828    public void startActivities(Intent[] intents) {
829        if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
830            throw new AndroidRuntimeException(
831                    "Calling startActivities() from outside of an Activity "
832                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
833                    + " Is this really what you want?");
834        }
835        mMainThread.getInstrumentation().execStartActivities(
836            getOuterContext(), mMainThread.getApplicationThread(), null,
837            (Activity)null, intents);
838    }
839
840    @Override
841    public void startIntentSender(IntentSender intent,
842            Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
843            throws IntentSender.SendIntentException {
844        try {
845            String resolvedType = null;
846            if (fillInIntent != null) {
847                resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
848            }
849            int result = ActivityManagerNative.getDefault()
850                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
851                        fillInIntent, resolvedType, null, null,
852                        0, flagsMask, flagsValues);
853            if (result == IActivityManager.START_CANCELED) {
854                throw new IntentSender.SendIntentException();
855            }
856            Instrumentation.checkStartActivityResult(result, null);
857        } catch (RemoteException e) {
858        }
859    }
860
861    @Override
862    public void sendBroadcast(Intent intent) {
863        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
864        try {
865            ActivityManagerNative.getDefault().broadcastIntent(
866                mMainThread.getApplicationThread(), intent, resolvedType, null,
867                Activity.RESULT_OK, null, null, null, false, false);
868        } catch (RemoteException e) {
869        }
870    }
871
872    @Override
873    public void sendBroadcast(Intent intent, String receiverPermission) {
874        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
875        try {
876            ActivityManagerNative.getDefault().broadcastIntent(
877                mMainThread.getApplicationThread(), intent, resolvedType, null,
878                Activity.RESULT_OK, null, null, receiverPermission, false, false);
879        } catch (RemoteException e) {
880        }
881    }
882
883    @Override
884    public void sendOrderedBroadcast(Intent intent,
885            String receiverPermission) {
886        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
887        try {
888            ActivityManagerNative.getDefault().broadcastIntent(
889                mMainThread.getApplicationThread(), intent, resolvedType, null,
890                Activity.RESULT_OK, null, null, receiverPermission, true, false);
891        } catch (RemoteException e) {
892        }
893    }
894
895    @Override
896    public void sendOrderedBroadcast(Intent intent,
897            String receiverPermission, BroadcastReceiver resultReceiver,
898            Handler scheduler, int initialCode, String initialData,
899            Bundle initialExtras) {
900        IIntentReceiver rd = null;
901        if (resultReceiver != null) {
902            if (mPackageInfo != null) {
903                if (scheduler == null) {
904                    scheduler = mMainThread.getHandler();
905                }
906                rd = mPackageInfo.getReceiverDispatcher(
907                    resultReceiver, getOuterContext(), scheduler,
908                    mMainThread.getInstrumentation(), false);
909            } else {
910                if (scheduler == null) {
911                    scheduler = mMainThread.getHandler();
912                }
913                rd = new LoadedApk.ReceiverDispatcher(
914                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
915            }
916        }
917        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
918        try {
919            ActivityManagerNative.getDefault().broadcastIntent(
920                mMainThread.getApplicationThread(), intent, resolvedType, rd,
921                initialCode, initialData, initialExtras, receiverPermission,
922                true, false);
923        } catch (RemoteException e) {
924        }
925    }
926
927    @Override
928    public void sendStickyBroadcast(Intent intent) {
929        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
930        try {
931            ActivityManagerNative.getDefault().broadcastIntent(
932                mMainThread.getApplicationThread(), intent, resolvedType, null,
933                Activity.RESULT_OK, null, null, null, false, true);
934        } catch (RemoteException e) {
935        }
936    }
937
938    @Override
939    public void sendStickyOrderedBroadcast(Intent intent,
940            BroadcastReceiver resultReceiver,
941            Handler scheduler, int initialCode, String initialData,
942            Bundle initialExtras) {
943        IIntentReceiver rd = null;
944        if (resultReceiver != null) {
945            if (mPackageInfo != null) {
946                if (scheduler == null) {
947                    scheduler = mMainThread.getHandler();
948                }
949                rd = mPackageInfo.getReceiverDispatcher(
950                    resultReceiver, getOuterContext(), scheduler,
951                    mMainThread.getInstrumentation(), false);
952            } else {
953                if (scheduler == null) {
954                    scheduler = mMainThread.getHandler();
955                }
956                rd = new LoadedApk.ReceiverDispatcher(
957                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
958            }
959        }
960        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
961        try {
962            ActivityManagerNative.getDefault().broadcastIntent(
963                mMainThread.getApplicationThread(), intent, resolvedType, rd,
964                initialCode, initialData, initialExtras, null,
965                true, true);
966        } catch (RemoteException e) {
967        }
968    }
969
970    @Override
971    public void removeStickyBroadcast(Intent intent) {
972        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
973        if (resolvedType != null) {
974            intent = new Intent(intent);
975            intent.setDataAndType(intent.getData(), resolvedType);
976        }
977        try {
978            ActivityManagerNative.getDefault().unbroadcastIntent(
979                mMainThread.getApplicationThread(), intent);
980        } catch (RemoteException e) {
981        }
982    }
983
984    @Override
985    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
986        return registerReceiver(receiver, filter, null, null);
987    }
988
989    @Override
990    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
991            String broadcastPermission, Handler scheduler) {
992        return registerReceiverInternal(receiver, filter, broadcastPermission,
993                scheduler, getOuterContext());
994    }
995
996    private Intent registerReceiverInternal(BroadcastReceiver receiver,
997            IntentFilter filter, String broadcastPermission,
998            Handler scheduler, Context context) {
999        IIntentReceiver rd = null;
1000        if (receiver != null) {
1001            if (mPackageInfo != null && context != null) {
1002                if (scheduler == null) {
1003                    scheduler = mMainThread.getHandler();
1004                }
1005                rd = mPackageInfo.getReceiverDispatcher(
1006                    receiver, context, scheduler,
1007                    mMainThread.getInstrumentation(), true);
1008            } else {
1009                if (scheduler == null) {
1010                    scheduler = mMainThread.getHandler();
1011                }
1012                rd = new LoadedApk.ReceiverDispatcher(
1013                        receiver, context, scheduler, null, true).getIIntentReceiver();
1014            }
1015        }
1016        try {
1017            return ActivityManagerNative.getDefault().registerReceiver(
1018                    mMainThread.getApplicationThread(),
1019                    rd, filter, broadcastPermission);
1020        } catch (RemoteException e) {
1021            return null;
1022        }
1023    }
1024
1025    @Override
1026    public void unregisterReceiver(BroadcastReceiver receiver) {
1027        if (mPackageInfo != null) {
1028            IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
1029                    getOuterContext(), receiver);
1030            try {
1031                ActivityManagerNative.getDefault().unregisterReceiver(rd);
1032            } catch (RemoteException e) {
1033            }
1034        } else {
1035            throw new RuntimeException("Not supported in system context");
1036        }
1037    }
1038
1039    @Override
1040    public ComponentName startService(Intent service) {
1041        try {
1042            ComponentName cn = ActivityManagerNative.getDefault().startService(
1043                mMainThread.getApplicationThread(), service,
1044                service.resolveTypeIfNeeded(getContentResolver()));
1045            if (cn != null && cn.getPackageName().equals("!")) {
1046                throw new SecurityException(
1047                        "Not allowed to start service " + service
1048                        + " without permission " + cn.getClassName());
1049            }
1050            return cn;
1051        } catch (RemoteException e) {
1052            return null;
1053        }
1054    }
1055
1056    @Override
1057    public boolean stopService(Intent service) {
1058        try {
1059            int res = ActivityManagerNative.getDefault().stopService(
1060                mMainThread.getApplicationThread(), service,
1061                service.resolveTypeIfNeeded(getContentResolver()));
1062            if (res < 0) {
1063                throw new SecurityException(
1064                        "Not allowed to stop service " + service);
1065            }
1066            return res != 0;
1067        } catch (RemoteException e) {
1068            return false;
1069        }
1070    }
1071
1072    @Override
1073    public boolean bindService(Intent service, ServiceConnection conn,
1074            int flags) {
1075        IServiceConnection sd;
1076        if (mPackageInfo != null) {
1077            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1078                    mMainThread.getHandler(), flags);
1079        } else {
1080            throw new RuntimeException("Not supported in system context");
1081        }
1082        try {
1083            int res = ActivityManagerNative.getDefault().bindService(
1084                mMainThread.getApplicationThread(), getActivityToken(),
1085                service, service.resolveTypeIfNeeded(getContentResolver()),
1086                sd, flags);
1087            if (res < 0) {
1088                throw new SecurityException(
1089                        "Not allowed to bind to service " + service);
1090            }
1091            return res != 0;
1092        } catch (RemoteException e) {
1093            return false;
1094        }
1095    }
1096
1097    @Override
1098    public void unbindService(ServiceConnection conn) {
1099        if (mPackageInfo != null) {
1100            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1101                    getOuterContext(), conn);
1102            try {
1103                ActivityManagerNative.getDefault().unbindService(sd);
1104            } catch (RemoteException e) {
1105            }
1106        } else {
1107            throw new RuntimeException("Not supported in system context");
1108        }
1109    }
1110
1111    @Override
1112    public boolean startInstrumentation(ComponentName className,
1113            String profileFile, Bundle arguments) {
1114        try {
1115            return ActivityManagerNative.getDefault().startInstrumentation(
1116                    className, profileFile, 0, arguments, null);
1117        } catch (RemoteException e) {
1118            // System has crashed, nothing we can do.
1119        }
1120        return false;
1121    }
1122
1123    @Override
1124    public Object getSystemService(String name) {
1125        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
1126        return fetcher == null ? null : fetcher.getService(this);
1127    }
1128
1129    private WallpaperManager getWallpaperManager() {
1130        return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
1131    }
1132
1133    /* package */ static DropBoxManager createDropBoxManager() {
1134        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1135        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1136        if (service == null) {
1137            // Don't return a DropBoxManager that will NPE upon use.
1138            // This also avoids caching a broken DropBoxManager in
1139            // getDropBoxManager during early boot, before the
1140            // DROPBOX_SERVICE is registered.
1141            return null;
1142        }
1143        return new DropBoxManager(service);
1144    }
1145
1146    @Override
1147    public int checkPermission(String permission, int pid, int uid) {
1148        if (permission == null) {
1149            throw new IllegalArgumentException("permission is null");
1150        }
1151
1152        if (!Process.supportsProcesses()) {
1153            return PackageManager.PERMISSION_GRANTED;
1154        }
1155        try {
1156            return ActivityManagerNative.getDefault().checkPermission(
1157                    permission, pid, uid);
1158        } catch (RemoteException e) {
1159            return PackageManager.PERMISSION_DENIED;
1160        }
1161    }
1162
1163    @Override
1164    public int checkCallingPermission(String permission) {
1165        if (permission == null) {
1166            throw new IllegalArgumentException("permission is null");
1167        }
1168
1169        if (!Process.supportsProcesses()) {
1170            return PackageManager.PERMISSION_GRANTED;
1171        }
1172        int pid = Binder.getCallingPid();
1173        if (pid != Process.myPid()) {
1174            return checkPermission(permission, pid,
1175                    Binder.getCallingUid());
1176        }
1177        return PackageManager.PERMISSION_DENIED;
1178    }
1179
1180    @Override
1181    public int checkCallingOrSelfPermission(String permission) {
1182        if (permission == null) {
1183            throw new IllegalArgumentException("permission is null");
1184        }
1185
1186        return checkPermission(permission, Binder.getCallingPid(),
1187                Binder.getCallingUid());
1188    }
1189
1190    private void enforce(
1191            String permission, int resultOfCheck,
1192            boolean selfToo, int uid, String message) {
1193        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1194            throw new SecurityException(
1195                    (message != null ? (message + ": ") : "") +
1196                    (selfToo
1197                     ? "Neither user " + uid + " nor current process has "
1198                     : "User " + uid + " does not have ") +
1199                    permission +
1200                    ".");
1201        }
1202    }
1203
1204    public void enforcePermission(
1205            String permission, int pid, int uid, String message) {
1206        enforce(permission,
1207                checkPermission(permission, pid, uid),
1208                false,
1209                uid,
1210                message);
1211    }
1212
1213    public void enforceCallingPermission(String permission, String message) {
1214        enforce(permission,
1215                checkCallingPermission(permission),
1216                false,
1217                Binder.getCallingUid(),
1218                message);
1219    }
1220
1221    public void enforceCallingOrSelfPermission(
1222            String permission, String message) {
1223        enforce(permission,
1224                checkCallingOrSelfPermission(permission),
1225                true,
1226                Binder.getCallingUid(),
1227                message);
1228    }
1229
1230    @Override
1231    public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1232         try {
1233            ActivityManagerNative.getDefault().grantUriPermission(
1234                    mMainThread.getApplicationThread(), toPackage, uri,
1235                    modeFlags);
1236        } catch (RemoteException e) {
1237        }
1238    }
1239
1240    @Override
1241    public void revokeUriPermission(Uri uri, int modeFlags) {
1242         try {
1243            ActivityManagerNative.getDefault().revokeUriPermission(
1244                    mMainThread.getApplicationThread(), uri,
1245                    modeFlags);
1246        } catch (RemoteException e) {
1247        }
1248    }
1249
1250    @Override
1251    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1252        if (!Process.supportsProcesses()) {
1253            return PackageManager.PERMISSION_GRANTED;
1254        }
1255        try {
1256            return ActivityManagerNative.getDefault().checkUriPermission(
1257                    uri, pid, uid, modeFlags);
1258        } catch (RemoteException e) {
1259            return PackageManager.PERMISSION_DENIED;
1260        }
1261    }
1262
1263    @Override
1264    public int checkCallingUriPermission(Uri uri, int modeFlags) {
1265        if (!Process.supportsProcesses()) {
1266            return PackageManager.PERMISSION_GRANTED;
1267        }
1268        int pid = Binder.getCallingPid();
1269        if (pid != Process.myPid()) {
1270            return checkUriPermission(uri, pid,
1271                    Binder.getCallingUid(), modeFlags);
1272        }
1273        return PackageManager.PERMISSION_DENIED;
1274    }
1275
1276    @Override
1277    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1278        return checkUriPermission(uri, Binder.getCallingPid(),
1279                Binder.getCallingUid(), modeFlags);
1280    }
1281
1282    @Override
1283    public int checkUriPermission(Uri uri, String readPermission,
1284            String writePermission, int pid, int uid, int modeFlags) {
1285        if (DEBUG) {
1286            Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1287                    + readPermission + " writePermission=" + writePermission
1288                    + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1289        }
1290        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1291            if (readPermission == null
1292                    || checkPermission(readPermission, pid, uid)
1293                    == PackageManager.PERMISSION_GRANTED) {
1294                return PackageManager.PERMISSION_GRANTED;
1295            }
1296        }
1297        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1298            if (writePermission == null
1299                    || checkPermission(writePermission, pid, uid)
1300                    == PackageManager.PERMISSION_GRANTED) {
1301                return PackageManager.PERMISSION_GRANTED;
1302            }
1303        }
1304        return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1305                : PackageManager.PERMISSION_DENIED;
1306    }
1307
1308    private String uriModeFlagToString(int uriModeFlags) {
1309        switch (uriModeFlags) {
1310            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1311                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1312                return "read and write";
1313            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1314                return "read";
1315            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1316                return "write";
1317        }
1318        throw new IllegalArgumentException(
1319                "Unknown permission mode flags: " + uriModeFlags);
1320    }
1321
1322    private void enforceForUri(
1323            int modeFlags, int resultOfCheck, boolean selfToo,
1324            int uid, Uri uri, String message) {
1325        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1326            throw new SecurityException(
1327                    (message != null ? (message + ": ") : "") +
1328                    (selfToo
1329                     ? "Neither user " + uid + " nor current process has "
1330                     : "User " + uid + " does not have ") +
1331                    uriModeFlagToString(modeFlags) +
1332                    " permission on " +
1333                    uri +
1334                    ".");
1335        }
1336    }
1337
1338    public void enforceUriPermission(
1339            Uri uri, int pid, int uid, int modeFlags, String message) {
1340        enforceForUri(
1341                modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1342                false, uid, uri, message);
1343    }
1344
1345    public void enforceCallingUriPermission(
1346            Uri uri, int modeFlags, String message) {
1347        enforceForUri(
1348                modeFlags, checkCallingUriPermission(uri, modeFlags),
1349                false, Binder.getCallingUid(), uri, message);
1350    }
1351
1352    public void enforceCallingOrSelfUriPermission(
1353            Uri uri, int modeFlags, String message) {
1354        enforceForUri(
1355                modeFlags,
1356                checkCallingOrSelfUriPermission(uri, modeFlags), true,
1357                Binder.getCallingUid(), uri, message);
1358    }
1359
1360    public void enforceUriPermission(
1361            Uri uri, String readPermission, String writePermission,
1362            int pid, int uid, int modeFlags, String message) {
1363        enforceForUri(modeFlags,
1364                      checkUriPermission(
1365                              uri, readPermission, writePermission, pid, uid,
1366                              modeFlags),
1367                      false,
1368                      uid,
1369                      uri,
1370                      message);
1371    }
1372
1373    @Override
1374    public Context createPackageContext(String packageName, int flags)
1375        throws PackageManager.NameNotFoundException {
1376        if (packageName.equals("system") || packageName.equals("android")) {
1377            return new ContextImpl(mMainThread.getSystemContext());
1378        }
1379
1380        LoadedApk pi =
1381            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
1382        if (pi != null) {
1383            ContextImpl c = new ContextImpl();
1384            c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
1385            c.init(pi, null, mMainThread, mResources);
1386            if (c.mResources != null) {
1387                return c;
1388            }
1389        }
1390
1391        // Should be a better exception.
1392        throw new PackageManager.NameNotFoundException(
1393            "Application package " + packageName + " not found");
1394    }
1395
1396    @Override
1397    public boolean isRestricted() {
1398        return mRestricted;
1399    }
1400
1401    private File getDataDirFile() {
1402        if (mPackageInfo != null) {
1403            return mPackageInfo.getDataDirFile();
1404        }
1405        throw new RuntimeException("Not supported in system context");
1406    }
1407
1408    @Override
1409    public File getDir(String name, int mode) {
1410        name = "app_" + name;
1411        File file = makeFilename(getDataDirFile(), name);
1412        if (!file.exists()) {
1413            file.mkdir();
1414            setFilePermissionsFromMode(file.getPath(), mode,
1415                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1416        }
1417        return file;
1418    }
1419
1420    static ContextImpl createSystemContext(ActivityThread mainThread) {
1421        ContextImpl context = new ContextImpl();
1422        context.init(Resources.getSystem(), mainThread);
1423        return context;
1424    }
1425
1426    ContextImpl() {
1427        mOuterContext = this;
1428    }
1429
1430    /**
1431     * Create a new ApplicationContext from an existing one.  The new one
1432     * works and operates the same as the one it is copying.
1433     *
1434     * @param context Existing application context.
1435     */
1436    public ContextImpl(ContextImpl context) {
1437        mPackageInfo = context.mPackageInfo;
1438        mResources = context.mResources;
1439        mMainThread = context.mMainThread;
1440        mContentResolver = context.mContentResolver;
1441        mOuterContext = this;
1442    }
1443
1444    final void init(LoadedApk packageInfo,
1445            IBinder activityToken, ActivityThread mainThread) {
1446        init(packageInfo, activityToken, mainThread, null);
1447    }
1448
1449    final void init(LoadedApk packageInfo,
1450                IBinder activityToken, ActivityThread mainThread,
1451                Resources container) {
1452        mPackageInfo = packageInfo;
1453        mResources = mPackageInfo.getResources(mainThread);
1454
1455        if (mResources != null && container != null
1456                && container.getCompatibilityInfo().applicationScale !=
1457                        mResources.getCompatibilityInfo().applicationScale) {
1458            if (DEBUG) {
1459                Log.d(TAG, "loaded context has different scaling. Using container's" +
1460                        " compatiblity info:" + container.getDisplayMetrics());
1461            }
1462            mResources = mainThread.getTopLevelResources(
1463                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
1464        }
1465        mMainThread = mainThread;
1466        mContentResolver = new ApplicationContentResolver(this, mainThread);
1467
1468        setActivityToken(activityToken);
1469    }
1470
1471    final void init(Resources resources, ActivityThread mainThread) {
1472        mPackageInfo = null;
1473        mResources = resources;
1474        mMainThread = mainThread;
1475        mContentResolver = new ApplicationContentResolver(this, mainThread);
1476    }
1477
1478    final void scheduleFinalCleanup(String who, String what) {
1479        mMainThread.scheduleContextCleanup(this, who, what);
1480    }
1481
1482    final void performFinalCleanup(String who, String what) {
1483        //Log.i(TAG, "Cleanup up context: " + this);
1484        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1485    }
1486
1487    final Context getReceiverRestrictedContext() {
1488        if (mReceiverRestrictedContext != null) {
1489            return mReceiverRestrictedContext;
1490        }
1491        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1492    }
1493
1494    final void setActivityToken(IBinder token) {
1495        mActivityToken = token;
1496    }
1497
1498    final void setOuterContext(Context context) {
1499        mOuterContext = context;
1500    }
1501
1502    final Context getOuterContext() {
1503        return mOuterContext;
1504    }
1505
1506    final IBinder getActivityToken() {
1507        return mActivityToken;
1508    }
1509
1510    static void setFilePermissionsFromMode(String name, int mode,
1511            int extraPermissions) {
1512        int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1513            |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1514            |extraPermissions;
1515        if ((mode&MODE_WORLD_READABLE) != 0) {
1516            perms |= FileUtils.S_IROTH;
1517        }
1518        if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1519            perms |= FileUtils.S_IWOTH;
1520        }
1521        if (DEBUG) {
1522            Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1523                  + ", perms=0x" + Integer.toHexString(perms));
1524        }
1525        FileUtils.setPermissions(name, perms, -1, -1);
1526    }
1527
1528    private File validateFilePath(String name, boolean createDirectory) {
1529        File dir;
1530        File f;
1531
1532        if (name.charAt(0) == File.separatorChar) {
1533            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1534            dir = new File(dirPath);
1535            name = name.substring(name.lastIndexOf(File.separatorChar));
1536            f = new File(dir, name);
1537        } else {
1538            dir = getDatabasesDir();
1539            f = makeFilename(dir, name);
1540        }
1541
1542        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1543            FileUtils.setPermissions(dir.getPath(),
1544                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1545                -1, -1);
1546        }
1547
1548        return f;
1549    }
1550
1551    private File makeFilename(File base, String name) {
1552        if (name.indexOf(File.separatorChar) < 0) {
1553            return new File(base, name);
1554        }
1555        throw new IllegalArgumentException(
1556                "File " + name + " contains a path separator");
1557    }
1558
1559    // ----------------------------------------------------------------------
1560    // ----------------------------------------------------------------------
1561    // ----------------------------------------------------------------------
1562
1563    private static final class ApplicationContentResolver extends ContentResolver {
1564        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
1565            super(context);
1566            mMainThread = mainThread;
1567        }
1568
1569        @Override
1570        protected IContentProvider acquireProvider(Context context, String name) {
1571            return mMainThread.acquireProvider(context, name);
1572        }
1573
1574        @Override
1575        protected IContentProvider acquireExistingProvider(Context context, String name) {
1576            return mMainThread.acquireExistingProvider(context, name);
1577        }
1578
1579        @Override
1580        public boolean releaseProvider(IContentProvider provider) {
1581            return mMainThread.releaseProvider(provider);
1582        }
1583
1584        private final ActivityThread mMainThread;
1585    }
1586}
1587