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