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