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