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