ContextImpl.java revision 9ecebbfbf768fd63e9a6c9a09c86d81c7737ee2d
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                fillInIntent.setAllowFds(false);
878                resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
879            }
880            int result = ActivityManagerNative.getDefault()
881                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
882                        fillInIntent, resolvedType, null, null,
883                        0, flagsMask, flagsValues);
884            if (result == IActivityManager.START_CANCELED) {
885                throw new IntentSender.SendIntentException();
886            }
887            Instrumentation.checkStartActivityResult(result, null);
888        } catch (RemoteException e) {
889        }
890    }
891
892    @Override
893    public void sendBroadcast(Intent intent) {
894        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
895        try {
896            intent.setAllowFds(false);
897            ActivityManagerNative.getDefault().broadcastIntent(
898                mMainThread.getApplicationThread(), intent, resolvedType, null,
899                Activity.RESULT_OK, null, null, null, false, false);
900        } catch (RemoteException e) {
901        }
902    }
903
904    @Override
905    public void sendBroadcast(Intent intent, String receiverPermission) {
906        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
907        try {
908            intent.setAllowFds(false);
909            ActivityManagerNative.getDefault().broadcastIntent(
910                mMainThread.getApplicationThread(), intent, resolvedType, null,
911                Activity.RESULT_OK, null, null, receiverPermission, false, false);
912        } catch (RemoteException e) {
913        }
914    }
915
916    @Override
917    public void sendOrderedBroadcast(Intent intent,
918            String receiverPermission) {
919        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
920        try {
921            intent.setAllowFds(false);
922            ActivityManagerNative.getDefault().broadcastIntent(
923                mMainThread.getApplicationThread(), intent, resolvedType, null,
924                Activity.RESULT_OK, null, null, receiverPermission, true, false);
925        } catch (RemoteException e) {
926        }
927    }
928
929    @Override
930    public void sendOrderedBroadcast(Intent intent,
931            String receiverPermission, BroadcastReceiver resultReceiver,
932            Handler scheduler, int initialCode, String initialData,
933            Bundle initialExtras) {
934        IIntentReceiver rd = null;
935        if (resultReceiver != null) {
936            if (mPackageInfo != null) {
937                if (scheduler == null) {
938                    scheduler = mMainThread.getHandler();
939                }
940                rd = mPackageInfo.getReceiverDispatcher(
941                    resultReceiver, getOuterContext(), scheduler,
942                    mMainThread.getInstrumentation(), false);
943            } else {
944                if (scheduler == null) {
945                    scheduler = mMainThread.getHandler();
946                }
947                rd = new LoadedApk.ReceiverDispatcher(
948                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
949            }
950        }
951        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
952        try {
953            intent.setAllowFds(false);
954            ActivityManagerNative.getDefault().broadcastIntent(
955                mMainThread.getApplicationThread(), intent, resolvedType, rd,
956                initialCode, initialData, initialExtras, receiverPermission,
957                true, false);
958        } catch (RemoteException e) {
959        }
960    }
961
962    @Override
963    public void sendStickyBroadcast(Intent intent) {
964        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
965        try {
966            intent.setAllowFds(false);
967            ActivityManagerNative.getDefault().broadcastIntent(
968                mMainThread.getApplicationThread(), intent, resolvedType, null,
969                Activity.RESULT_OK, null, null, null, false, true);
970        } catch (RemoteException e) {
971        }
972    }
973
974    @Override
975    public void sendStickyOrderedBroadcast(Intent intent,
976            BroadcastReceiver resultReceiver,
977            Handler scheduler, int initialCode, String initialData,
978            Bundle initialExtras) {
979        IIntentReceiver rd = null;
980        if (resultReceiver != null) {
981            if (mPackageInfo != null) {
982                if (scheduler == null) {
983                    scheduler = mMainThread.getHandler();
984                }
985                rd = mPackageInfo.getReceiverDispatcher(
986                    resultReceiver, getOuterContext(), scheduler,
987                    mMainThread.getInstrumentation(), false);
988            } else {
989                if (scheduler == null) {
990                    scheduler = mMainThread.getHandler();
991                }
992                rd = new LoadedApk.ReceiverDispatcher(
993                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
994            }
995        }
996        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
997        try {
998            intent.setAllowFds(false);
999            ActivityManagerNative.getDefault().broadcastIntent(
1000                mMainThread.getApplicationThread(), intent, resolvedType, rd,
1001                initialCode, initialData, initialExtras, null,
1002                true, true);
1003        } catch (RemoteException e) {
1004        }
1005    }
1006
1007    @Override
1008    public void removeStickyBroadcast(Intent intent) {
1009        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
1010        if (resolvedType != null) {
1011            intent = new Intent(intent);
1012            intent.setDataAndType(intent.getData(), resolvedType);
1013        }
1014        try {
1015            intent.setAllowFds(false);
1016            ActivityManagerNative.getDefault().unbroadcastIntent(
1017                mMainThread.getApplicationThread(), intent);
1018        } catch (RemoteException e) {
1019        }
1020    }
1021
1022    @Override
1023    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1024        return registerReceiver(receiver, filter, null, null);
1025    }
1026
1027    @Override
1028    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
1029            String broadcastPermission, Handler scheduler) {
1030        return registerReceiverInternal(receiver, filter, broadcastPermission,
1031                scheduler, getOuterContext());
1032    }
1033
1034    private Intent registerReceiverInternal(BroadcastReceiver receiver,
1035            IntentFilter filter, String broadcastPermission,
1036            Handler scheduler, Context context) {
1037        IIntentReceiver rd = null;
1038        if (receiver != null) {
1039            if (mPackageInfo != null && context != null) {
1040                if (scheduler == null) {
1041                    scheduler = mMainThread.getHandler();
1042                }
1043                rd = mPackageInfo.getReceiverDispatcher(
1044                    receiver, context, scheduler,
1045                    mMainThread.getInstrumentation(), true);
1046            } else {
1047                if (scheduler == null) {
1048                    scheduler = mMainThread.getHandler();
1049                }
1050                rd = new LoadedApk.ReceiverDispatcher(
1051                        receiver, context, scheduler, null, true).getIIntentReceiver();
1052            }
1053        }
1054        try {
1055            return ActivityManagerNative.getDefault().registerReceiver(
1056                    mMainThread.getApplicationThread(), mBasePackageName,
1057                    rd, filter, broadcastPermission);
1058        } catch (RemoteException e) {
1059            return null;
1060        }
1061    }
1062
1063    @Override
1064    public void unregisterReceiver(BroadcastReceiver receiver) {
1065        if (mPackageInfo != null) {
1066            IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
1067                    getOuterContext(), receiver);
1068            try {
1069                ActivityManagerNative.getDefault().unregisterReceiver(rd);
1070            } catch (RemoteException e) {
1071            }
1072        } else {
1073            throw new RuntimeException("Not supported in system context");
1074        }
1075    }
1076
1077    @Override
1078    public ComponentName startService(Intent service) {
1079        try {
1080            service.setAllowFds(false);
1081            ComponentName cn = ActivityManagerNative.getDefault().startService(
1082                mMainThread.getApplicationThread(), service,
1083                service.resolveTypeIfNeeded(getContentResolver()));
1084            if (cn != null && cn.getPackageName().equals("!")) {
1085                throw new SecurityException(
1086                        "Not allowed to start service " + service
1087                        + " without permission " + cn.getClassName());
1088            }
1089            return cn;
1090        } catch (RemoteException e) {
1091            return null;
1092        }
1093    }
1094
1095    @Override
1096    public boolean stopService(Intent service) {
1097        try {
1098            service.setAllowFds(false);
1099            int res = ActivityManagerNative.getDefault().stopService(
1100                mMainThread.getApplicationThread(), service,
1101                service.resolveTypeIfNeeded(getContentResolver()));
1102            if (res < 0) {
1103                throw new SecurityException(
1104                        "Not allowed to stop service " + service);
1105            }
1106            return res != 0;
1107        } catch (RemoteException e) {
1108            return false;
1109        }
1110    }
1111
1112    @Override
1113    public boolean bindService(Intent service, ServiceConnection conn,
1114            int flags) {
1115        IServiceConnection sd;
1116        if (mPackageInfo != null) {
1117            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1118                    mMainThread.getHandler(), flags);
1119        } else {
1120            throw new RuntimeException("Not supported in system context");
1121        }
1122        try {
1123            IBinder token = getActivityToken();
1124            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
1125                    && mPackageInfo.getApplicationInfo().targetSdkVersion
1126                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1127                flags |= BIND_WAIVE_PRIORITY;
1128            }
1129            service.setAllowFds(false);
1130            int res = ActivityManagerNative.getDefault().bindService(
1131                mMainThread.getApplicationThread(), getActivityToken(),
1132                service, service.resolveTypeIfNeeded(getContentResolver()),
1133                sd, flags);
1134            if (res < 0) {
1135                throw new SecurityException(
1136                        "Not allowed to bind to service " + service);
1137            }
1138            return res != 0;
1139        } catch (RemoteException e) {
1140            return false;
1141        }
1142    }
1143
1144    @Override
1145    public void unbindService(ServiceConnection conn) {
1146        if (mPackageInfo != null) {
1147            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1148                    getOuterContext(), conn);
1149            try {
1150                ActivityManagerNative.getDefault().unbindService(sd);
1151            } catch (RemoteException e) {
1152            }
1153        } else {
1154            throw new RuntimeException("Not supported in system context");
1155        }
1156    }
1157
1158    @Override
1159    public boolean startInstrumentation(ComponentName className,
1160            String profileFile, Bundle arguments) {
1161        try {
1162            if (arguments != null) {
1163                arguments.setAllowFds(false);
1164            }
1165            return ActivityManagerNative.getDefault().startInstrumentation(
1166                    className, profileFile, 0, arguments, null);
1167        } catch (RemoteException e) {
1168            // System has crashed, nothing we can do.
1169        }
1170        return false;
1171    }
1172
1173    @Override
1174    public Object getSystemService(String name) {
1175        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
1176        return fetcher == null ? null : fetcher.getService(this);
1177    }
1178
1179    private WallpaperManager getWallpaperManager() {
1180        return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
1181    }
1182
1183    /* package */ static DropBoxManager createDropBoxManager() {
1184        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1185        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1186        if (service == null) {
1187            // Don't return a DropBoxManager that will NPE upon use.
1188            // This also avoids caching a broken DropBoxManager in
1189            // getDropBoxManager during early boot, before the
1190            // DROPBOX_SERVICE is registered.
1191            return null;
1192        }
1193        return new DropBoxManager(service);
1194    }
1195
1196    @Override
1197    public int checkPermission(String permission, int pid, int uid) {
1198        if (permission == null) {
1199            throw new IllegalArgumentException("permission is null");
1200        }
1201
1202        try {
1203            return ActivityManagerNative.getDefault().checkPermission(
1204                    permission, pid, uid);
1205        } catch (RemoteException e) {
1206            return PackageManager.PERMISSION_DENIED;
1207        }
1208    }
1209
1210    @Override
1211    public int checkCallingPermission(String permission) {
1212        if (permission == null) {
1213            throw new IllegalArgumentException("permission is null");
1214        }
1215
1216        int pid = Binder.getCallingPid();
1217        if (pid != Process.myPid()) {
1218            return checkPermission(permission, pid,
1219                    Binder.getCallingUid());
1220        }
1221        return PackageManager.PERMISSION_DENIED;
1222    }
1223
1224    @Override
1225    public int checkCallingOrSelfPermission(String permission) {
1226        if (permission == null) {
1227            throw new IllegalArgumentException("permission is null");
1228        }
1229
1230        return checkPermission(permission, Binder.getCallingPid(),
1231                Binder.getCallingUid());
1232    }
1233
1234    private void enforce(
1235            String permission, int resultOfCheck,
1236            boolean selfToo, int uid, String message) {
1237        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1238            throw new SecurityException(
1239                    (message != null ? (message + ": ") : "") +
1240                    (selfToo
1241                     ? "Neither user " + uid + " nor current process has "
1242                     : "User " + uid + " does not have ") +
1243                    permission +
1244                    ".");
1245        }
1246    }
1247
1248    public void enforcePermission(
1249            String permission, int pid, int uid, String message) {
1250        enforce(permission,
1251                checkPermission(permission, pid, uid),
1252                false,
1253                uid,
1254                message);
1255    }
1256
1257    public void enforceCallingPermission(String permission, String message) {
1258        enforce(permission,
1259                checkCallingPermission(permission),
1260                false,
1261                Binder.getCallingUid(),
1262                message);
1263    }
1264
1265    public void enforceCallingOrSelfPermission(
1266            String permission, String message) {
1267        enforce(permission,
1268                checkCallingOrSelfPermission(permission),
1269                true,
1270                Binder.getCallingUid(),
1271                message);
1272    }
1273
1274    @Override
1275    public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1276         try {
1277            ActivityManagerNative.getDefault().grantUriPermission(
1278                    mMainThread.getApplicationThread(), toPackage, uri,
1279                    modeFlags);
1280        } catch (RemoteException e) {
1281        }
1282    }
1283
1284    @Override
1285    public void revokeUriPermission(Uri uri, int modeFlags) {
1286         try {
1287            ActivityManagerNative.getDefault().revokeUriPermission(
1288                    mMainThread.getApplicationThread(), uri,
1289                    modeFlags);
1290        } catch (RemoteException e) {
1291        }
1292    }
1293
1294    @Override
1295    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1296        try {
1297            return ActivityManagerNative.getDefault().checkUriPermission(
1298                    uri, pid, uid, modeFlags);
1299        } catch (RemoteException e) {
1300            return PackageManager.PERMISSION_DENIED;
1301        }
1302    }
1303
1304    @Override
1305    public int checkCallingUriPermission(Uri uri, int modeFlags) {
1306        int pid = Binder.getCallingPid();
1307        if (pid != Process.myPid()) {
1308            return checkUriPermission(uri, pid,
1309                    Binder.getCallingUid(), modeFlags);
1310        }
1311        return PackageManager.PERMISSION_DENIED;
1312    }
1313
1314    @Override
1315    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1316        return checkUriPermission(uri, Binder.getCallingPid(),
1317                Binder.getCallingUid(), modeFlags);
1318    }
1319
1320    @Override
1321    public int checkUriPermission(Uri uri, String readPermission,
1322            String writePermission, int pid, int uid, int modeFlags) {
1323        if (DEBUG) {
1324            Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1325                    + readPermission + " writePermission=" + writePermission
1326                    + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1327        }
1328        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1329            if (readPermission == null
1330                    || checkPermission(readPermission, pid, uid)
1331                    == PackageManager.PERMISSION_GRANTED) {
1332                return PackageManager.PERMISSION_GRANTED;
1333            }
1334        }
1335        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1336            if (writePermission == null
1337                    || checkPermission(writePermission, pid, uid)
1338                    == PackageManager.PERMISSION_GRANTED) {
1339                return PackageManager.PERMISSION_GRANTED;
1340            }
1341        }
1342        return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1343                : PackageManager.PERMISSION_DENIED;
1344    }
1345
1346    private String uriModeFlagToString(int uriModeFlags) {
1347        switch (uriModeFlags) {
1348            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1349                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1350                return "read and write";
1351            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1352                return "read";
1353            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1354                return "write";
1355        }
1356        throw new IllegalArgumentException(
1357                "Unknown permission mode flags: " + uriModeFlags);
1358    }
1359
1360    private void enforceForUri(
1361            int modeFlags, int resultOfCheck, boolean selfToo,
1362            int uid, Uri uri, String message) {
1363        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1364            throw new SecurityException(
1365                    (message != null ? (message + ": ") : "") +
1366                    (selfToo
1367                     ? "Neither user " + uid + " nor current process has "
1368                     : "User " + uid + " does not have ") +
1369                    uriModeFlagToString(modeFlags) +
1370                    " permission on " +
1371                    uri +
1372                    ".");
1373        }
1374    }
1375
1376    public void enforceUriPermission(
1377            Uri uri, int pid, int uid, int modeFlags, String message) {
1378        enforceForUri(
1379                modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1380                false, uid, uri, message);
1381    }
1382
1383    public void enforceCallingUriPermission(
1384            Uri uri, int modeFlags, String message) {
1385        enforceForUri(
1386                modeFlags, checkCallingUriPermission(uri, modeFlags),
1387                false, Binder.getCallingUid(), uri, message);
1388    }
1389
1390    public void enforceCallingOrSelfUriPermission(
1391            Uri uri, int modeFlags, String message) {
1392        enforceForUri(
1393                modeFlags,
1394                checkCallingOrSelfUriPermission(uri, modeFlags), true,
1395                Binder.getCallingUid(), uri, message);
1396    }
1397
1398    public void enforceUriPermission(
1399            Uri uri, String readPermission, String writePermission,
1400            int pid, int uid, int modeFlags, String message) {
1401        enforceForUri(modeFlags,
1402                      checkUriPermission(
1403                              uri, readPermission, writePermission, pid, uid,
1404                              modeFlags),
1405                      false,
1406                      uid,
1407                      uri,
1408                      message);
1409    }
1410
1411    @Override
1412    public Context createPackageContext(String packageName, int flags)
1413        throws PackageManager.NameNotFoundException {
1414        if (packageName.equals("system") || packageName.equals("android")) {
1415            return new ContextImpl(mMainThread.getSystemContext());
1416        }
1417
1418        LoadedApk pi =
1419            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
1420        if (pi != null) {
1421            ContextImpl c = new ContextImpl();
1422            c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
1423            c.init(pi, null, mMainThread, mResources, mBasePackageName);
1424            if (c.mResources != null) {
1425                return c;
1426            }
1427        }
1428
1429        // Should be a better exception.
1430        throw new PackageManager.NameNotFoundException(
1431            "Application package " + packageName + " not found");
1432    }
1433
1434    @Override
1435    public boolean isRestricted() {
1436        return mRestricted;
1437    }
1438
1439    private File getDataDirFile() {
1440        if (mPackageInfo != null) {
1441            return mPackageInfo.getDataDirFile();
1442        }
1443        throw new RuntimeException("Not supported in system context");
1444    }
1445
1446    @Override
1447    public File getDir(String name, int mode) {
1448        name = "app_" + name;
1449        File file = makeFilename(getDataDirFile(), name);
1450        if (!file.exists()) {
1451            file.mkdir();
1452            setFilePermissionsFromMode(file.getPath(), mode,
1453                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1454        }
1455        return file;
1456    }
1457
1458    static ContextImpl createSystemContext(ActivityThread mainThread) {
1459        ContextImpl context = new ContextImpl();
1460        context.init(Resources.getSystem(), mainThread);
1461        return context;
1462    }
1463
1464    ContextImpl() {
1465        mOuterContext = this;
1466    }
1467
1468    /**
1469     * Create a new ApplicationContext from an existing one.  The new one
1470     * works and operates the same as the one it is copying.
1471     *
1472     * @param context Existing application context.
1473     */
1474    public ContextImpl(ContextImpl context) {
1475        mPackageInfo = context.mPackageInfo;
1476        mBasePackageName = context.mBasePackageName;
1477        mResources = context.mResources;
1478        mMainThread = context.mMainThread;
1479        mContentResolver = context.mContentResolver;
1480        mOuterContext = this;
1481    }
1482
1483    final void init(LoadedApk packageInfo,
1484            IBinder activityToken, ActivityThread mainThread) {
1485        init(packageInfo, activityToken, mainThread, null, null);
1486    }
1487
1488    final void init(LoadedApk packageInfo,
1489                IBinder activityToken, ActivityThread mainThread,
1490                Resources container, String basePackageName) {
1491        mPackageInfo = packageInfo;
1492        mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
1493        mResources = mPackageInfo.getResources(mainThread);
1494
1495        if (mResources != null && container != null
1496                && container.getCompatibilityInfo().applicationScale !=
1497                        mResources.getCompatibilityInfo().applicationScale) {
1498            if (DEBUG) {
1499                Log.d(TAG, "loaded context has different scaling. Using container's" +
1500                        " compatiblity info:" + container.getDisplayMetrics());
1501            }
1502            mResources = mainThread.getTopLevelResources(
1503                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
1504        }
1505        mMainThread = mainThread;
1506        mContentResolver = new ApplicationContentResolver(this, mainThread);
1507
1508        setActivityToken(activityToken);
1509    }
1510
1511    final void init(Resources resources, ActivityThread mainThread) {
1512        mPackageInfo = null;
1513        mBasePackageName = null;
1514        mResources = resources;
1515        mMainThread = mainThread;
1516        mContentResolver = new ApplicationContentResolver(this, mainThread);
1517    }
1518
1519    final void scheduleFinalCleanup(String who, String what) {
1520        mMainThread.scheduleContextCleanup(this, who, what);
1521    }
1522
1523    final void performFinalCleanup(String who, String what) {
1524        //Log.i(TAG, "Cleanup up context: " + this);
1525        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1526    }
1527
1528    final Context getReceiverRestrictedContext() {
1529        if (mReceiverRestrictedContext != null) {
1530            return mReceiverRestrictedContext;
1531        }
1532        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1533    }
1534
1535    final void setActivityToken(IBinder token) {
1536        mActivityToken = token;
1537    }
1538
1539    final void setOuterContext(Context context) {
1540        mOuterContext = context;
1541    }
1542
1543    final Context getOuterContext() {
1544        return mOuterContext;
1545    }
1546
1547    final IBinder getActivityToken() {
1548        return mActivityToken;
1549    }
1550
1551    static void setFilePermissionsFromMode(String name, int mode,
1552            int extraPermissions) {
1553        int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1554            |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1555            |extraPermissions;
1556        if ((mode&MODE_WORLD_READABLE) != 0) {
1557            perms |= FileUtils.S_IROTH;
1558        }
1559        if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1560            perms |= FileUtils.S_IWOTH;
1561        }
1562        if (DEBUG) {
1563            Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1564                  + ", perms=0x" + Integer.toHexString(perms));
1565        }
1566        FileUtils.setPermissions(name, perms, -1, -1);
1567    }
1568
1569    private File validateFilePath(String name, boolean createDirectory) {
1570        File dir;
1571        File f;
1572
1573        if (name.charAt(0) == File.separatorChar) {
1574            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1575            dir = new File(dirPath);
1576            name = name.substring(name.lastIndexOf(File.separatorChar));
1577            f = new File(dir, name);
1578        } else {
1579            dir = getDatabasesDir();
1580            f = makeFilename(dir, name);
1581        }
1582
1583        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1584            FileUtils.setPermissions(dir.getPath(),
1585                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1586                -1, -1);
1587        }
1588
1589        return f;
1590    }
1591
1592    private File makeFilename(File base, String name) {
1593        if (name.indexOf(File.separatorChar) < 0) {
1594            return new File(base, name);
1595        }
1596        throw new IllegalArgumentException(
1597                "File " + name + " contains a path separator");
1598    }
1599
1600    // ----------------------------------------------------------------------
1601    // ----------------------------------------------------------------------
1602    // ----------------------------------------------------------------------
1603
1604    private static final class ApplicationContentResolver extends ContentResolver {
1605        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
1606            super(context);
1607            mMainThread = mainThread;
1608        }
1609
1610        @Override
1611        protected IContentProvider acquireProvider(Context context, String name) {
1612            return mMainThread.acquireProvider(context, name);
1613        }
1614
1615        @Override
1616        protected IContentProvider acquireExistingProvider(Context context, String name) {
1617            return mMainThread.acquireExistingProvider(context, name);
1618        }
1619
1620        @Override
1621        public boolean releaseProvider(IContentProvider provider) {
1622            return mMainThread.releaseProvider(provider);
1623        }
1624
1625        private final ActivityThread mMainThread;
1626    }
1627}
1628