ContextImpl.java revision c68c913d357e2955d4bd7ca52829071e531c7825
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                        ctx.mMainThread.getHandler());
369                }});
370
371        // Note: this was previously cached in a static variable, but
372        // constructed using mMainThread.getHandler(), so converting
373        // it to be a regular Context-cached service...
374        registerService(POWER_SERVICE, new ServiceFetcher() {
375                public Object createService(ContextImpl ctx) {
376                    IBinder b = ServiceManager.getService(POWER_SERVICE);
377                    IPowerManager service = IPowerManager.Stub.asInterface(b);
378                    return new PowerManager(service, ctx.mMainThread.getHandler());
379                }});
380
381        registerService(SEARCH_SERVICE, new ServiceFetcher() {
382                public Object createService(ContextImpl ctx) {
383                    return new SearchManager(ctx.getOuterContext(),
384                            ctx.mMainThread.getHandler());
385                }});
386
387        registerService(SENSOR_SERVICE, new ServiceFetcher() {
388                public Object createService(ContextImpl ctx) {
389                    return new SensorManager(ctx.mMainThread.getHandler().getLooper());
390                }});
391
392        registerService(STATUS_BAR_SERVICE, new ServiceFetcher() {
393                public Object createService(ContextImpl ctx) {
394                    return new StatusBarManager(ctx.getOuterContext());
395                }});
396
397        registerService(STORAGE_SERVICE, new ServiceFetcher() {
398                public Object createService(ContextImpl ctx) {
399                    try {
400                        return new StorageManager(ctx.mMainThread.getHandler().getLooper());
401                    } catch (RemoteException rex) {
402                        Log.e(TAG, "Failed to create StorageManager", rex);
403                        return null;
404                    }
405                }});
406
407        registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
408                public Object createService(ContextImpl ctx) {
409                    return new TelephonyManager(ctx.getOuterContext());
410                }});
411
412        registerService(THROTTLE_SERVICE, new StaticServiceFetcher() {
413                public Object createStaticService() {
414                    IBinder b = ServiceManager.getService(THROTTLE_SERVICE);
415                    return new ThrottleManager(IThrottleManager.Stub.asInterface(b));
416                }});
417
418        registerService(UI_MODE_SERVICE, new ServiceFetcher() {
419                public Object createService(ContextImpl ctx) {
420                    return new UiModeManager();
421                }});
422
423        registerService(USB_SERVICE, new ServiceFetcher() {
424                public Object createService(ContextImpl ctx) {
425                    IBinder b = ServiceManager.getService(USB_SERVICE);
426                    return new UsbManager(ctx, IUsbManager.Stub.asInterface(b));
427                }});
428
429        registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
430                public Object createService(ContextImpl ctx) {
431                    return new Vibrator();
432                }});
433
434        registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
435
436        registerService(WIFI_SERVICE, new ServiceFetcher() {
437                public Object createService(ContextImpl ctx) {
438                    IBinder b = ServiceManager.getService(WIFI_SERVICE);
439                    IWifiManager service = IWifiManager.Stub.asInterface(b);
440                    return new WifiManager(service, ctx.mMainThread.getHandler());
441                }});
442
443        registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
444                public Object createService(ContextImpl ctx) {
445                    IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
446                    IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
447                    return new WifiP2pManager(service);
448                }});
449
450        registerService(WINDOW_SERVICE, new ServiceFetcher() {
451                public Object getService(ContextImpl ctx) {
452                    return WindowManagerImpl.getDefault(ctx.mPackageInfo.mCompatibilityInfo);
453                }});
454    }
455
456    static ContextImpl getImpl(Context context) {
457        Context nextContext;
458        while ((context instanceof ContextWrapper) &&
459                (nextContext=((ContextWrapper)context).getBaseContext()) != null) {
460            context = nextContext;
461        }
462        return (ContextImpl)context;
463    }
464
465    // The system service cache for the system services that are
466    // cached per-ContextImpl.  Package-scoped to avoid accessor
467    // methods.
468    final ArrayList<Object> mServiceCache = new ArrayList<Object>();
469
470    @Override
471    public AssetManager getAssets() {
472        return mResources.getAssets();
473    }
474
475    @Override
476    public Resources getResources() {
477        return mResources;
478    }
479
480    @Override
481    public PackageManager getPackageManager() {
482        if (mPackageManager != null) {
483            return mPackageManager;
484        }
485
486        IPackageManager pm = ActivityThread.getPackageManager();
487        if (pm != null) {
488            // Doesn't matter if we make more than one instance.
489            return (mPackageManager = new ApplicationPackageManager(this, pm));
490        }
491
492        return null;
493    }
494
495    @Override
496    public ContentResolver getContentResolver() {
497        return mContentResolver;
498    }
499
500    @Override
501    public Looper getMainLooper() {
502        return mMainThread.getLooper();
503    }
504
505    @Override
506    public Context getApplicationContext() {
507        return (mPackageInfo != null) ?
508                mPackageInfo.getApplication() : mMainThread.getApplication();
509    }
510
511    @Override
512    public void setTheme(int resid) {
513        mThemeResource = resid;
514    }
515
516    @Override
517    public int getThemeResId() {
518        return mThemeResource;
519    }
520
521    @Override
522    public Resources.Theme getTheme() {
523        if (mTheme == null) {
524            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
525                    getOuterContext().getApplicationInfo().targetSdkVersion);
526            mTheme = mResources.newTheme();
527            mTheme.applyStyle(mThemeResource, true);
528        }
529        return mTheme;
530    }
531
532    @Override
533    public ClassLoader getClassLoader() {
534        return mPackageInfo != null ?
535                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
536    }
537
538    @Override
539    public String getPackageName() {
540        if (mPackageInfo != null) {
541            return mPackageInfo.getPackageName();
542        }
543        throw new RuntimeException("Not supported in system context");
544    }
545
546    @Override
547    public ApplicationInfo getApplicationInfo() {
548        if (mPackageInfo != null) {
549            return mPackageInfo.getApplicationInfo();
550        }
551        throw new RuntimeException("Not supported in system context");
552    }
553
554    @Override
555    public String getPackageResourcePath() {
556        if (mPackageInfo != null) {
557            return mPackageInfo.getResDir();
558        }
559        throw new RuntimeException("Not supported in system context");
560    }
561
562    @Override
563    public String getPackageCodePath() {
564        if (mPackageInfo != null) {
565            return mPackageInfo.getAppDir();
566        }
567        throw new RuntimeException("Not supported in system context");
568    }
569
570    public File getSharedPrefsFile(String name) {
571        return makeFilename(getPreferencesDir(), name + ".xml");
572    }
573
574    @Override
575    public SharedPreferences getSharedPreferences(String name, int mode) {
576        SharedPreferencesImpl sp;
577        synchronized (sSharedPrefs) {
578            sp = sSharedPrefs.get(name);
579            if (sp == null) {
580                File prefsFile = getSharedPrefsFile(name);
581                sp = new SharedPreferencesImpl(prefsFile, mode);
582                sSharedPrefs.put(name, sp);
583                return sp;
584            }
585        }
586        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
587            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
588            // If somebody else (some other process) changed the prefs
589            // file behind our back, we reload it.  This has been the
590            // historical (if undocumented) behavior.
591            sp.startReloadIfChangedUnexpectedly();
592        }
593        return sp;
594    }
595
596    private File getPreferencesDir() {
597        synchronized (mSync) {
598            if (mPreferencesDir == null) {
599                mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
600            }
601            return mPreferencesDir;
602        }
603    }
604
605    @Override
606    public FileInputStream openFileInput(String name)
607        throws FileNotFoundException {
608        File f = makeFilename(getFilesDir(), name);
609        return new FileInputStream(f);
610    }
611
612    @Override
613    public FileOutputStream openFileOutput(String name, int mode)
614        throws FileNotFoundException {
615        final boolean append = (mode&MODE_APPEND) != 0;
616        File f = makeFilename(getFilesDir(), name);
617        try {
618            FileOutputStream fos = new FileOutputStream(f, append);
619            setFilePermissionsFromMode(f.getPath(), mode, 0);
620            return fos;
621        } catch (FileNotFoundException e) {
622        }
623
624        File parent = f.getParentFile();
625        parent.mkdir();
626        FileUtils.setPermissions(
627            parent.getPath(),
628            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
629            -1, -1);
630        FileOutputStream fos = new FileOutputStream(f, append);
631        setFilePermissionsFromMode(f.getPath(), mode, 0);
632        return fos;
633    }
634
635    @Override
636    public boolean deleteFile(String name) {
637        File f = makeFilename(getFilesDir(), name);
638        return f.delete();
639    }
640
641    @Override
642    public File getFilesDir() {
643        synchronized (mSync) {
644            if (mFilesDir == null) {
645                mFilesDir = new File(getDataDirFile(), "files");
646            }
647            if (!mFilesDir.exists()) {
648                if(!mFilesDir.mkdirs()) {
649                    Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
650                    return null;
651                }
652                FileUtils.setPermissions(
653                        mFilesDir.getPath(),
654                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
655                        -1, -1);
656            }
657            return mFilesDir;
658        }
659    }
660
661    @Override
662    public File getExternalFilesDir(String type) {
663        synchronized (mSync) {
664            if (mExternalFilesDir == null) {
665                mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
666                        getPackageName());
667            }
668            if (!mExternalFilesDir.exists()) {
669                try {
670                    (new File(Environment.getExternalStorageAndroidDataDir(),
671                            ".nomedia")).createNewFile();
672                } catch (IOException e) {
673                }
674                if (!mExternalFilesDir.mkdirs()) {
675                    Log.w(TAG, "Unable to create external files directory");
676                    return null;
677                }
678            }
679            if (type == null) {
680                return mExternalFilesDir;
681            }
682            File dir = new File(mExternalFilesDir, type);
683            if (!dir.exists()) {
684                if (!dir.mkdirs()) {
685                    Log.w(TAG, "Unable to create external media directory " + dir);
686                    return null;
687                }
688            }
689            return dir;
690        }
691    }
692
693    @Override
694    public File getObbDir() {
695        synchronized (mSync) {
696            if (mObbDir == null) {
697                mObbDir = Environment.getExternalStorageAppObbDirectory(
698                        getPackageName());
699            }
700            return mObbDir;
701        }
702    }
703
704    @Override
705    public File getCacheDir() {
706        synchronized (mSync) {
707            if (mCacheDir == null) {
708                mCacheDir = new File(getDataDirFile(), "cache");
709            }
710            if (!mCacheDir.exists()) {
711                if(!mCacheDir.mkdirs()) {
712                    Log.w(TAG, "Unable to create cache directory");
713                    return null;
714                }
715                FileUtils.setPermissions(
716                        mCacheDir.getPath(),
717                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
718                        -1, -1);
719            }
720        }
721        return mCacheDir;
722    }
723
724    @Override
725    public File getExternalCacheDir() {
726        synchronized (mSync) {
727            if (mExternalCacheDir == null) {
728                mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
729                        getPackageName());
730            }
731            if (!mExternalCacheDir.exists()) {
732                try {
733                    (new File(Environment.getExternalStorageAndroidDataDir(),
734                            ".nomedia")).createNewFile();
735                } catch (IOException e) {
736                }
737                if (!mExternalCacheDir.mkdirs()) {
738                    Log.w(TAG, "Unable to create external cache directory");
739                    return null;
740                }
741            }
742            return mExternalCacheDir;
743        }
744    }
745
746    @Override
747    public File getFileStreamPath(String name) {
748        return makeFilename(getFilesDir(), name);
749    }
750
751    @Override
752    public String[] fileList() {
753        final String[] list = getFilesDir().list();
754        return (list != null) ? list : EMPTY_FILE_LIST;
755    }
756
757    @Override
758    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
759        File f = validateFilePath(name, true);
760        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
761        setFilePermissionsFromMode(f.getPath(), mode, 0);
762        return db;
763    }
764
765    @Override
766    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
767            DatabaseErrorHandler errorHandler) {
768        File f = validateFilePath(name, true);
769        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
770        setFilePermissionsFromMode(f.getPath(), mode, 0);
771        return db;
772    }
773
774    @Override
775    public boolean deleteDatabase(String name) {
776        try {
777            File f = validateFilePath(name, false);
778            return f.delete();
779        } catch (Exception e) {
780        }
781        return false;
782    }
783
784    @Override
785    public File getDatabasePath(String name) {
786        return validateFilePath(name, false);
787    }
788
789    @Override
790    public String[] databaseList() {
791        final String[] list = getDatabasesDir().list();
792        return (list != null) ? list : EMPTY_FILE_LIST;
793    }
794
795
796    private File getDatabasesDir() {
797        synchronized (mSync) {
798            if (mDatabasesDir == null) {
799                mDatabasesDir = new File(getDataDirFile(), "databases");
800            }
801            if (mDatabasesDir.getPath().equals("databases")) {
802                mDatabasesDir = new File("/data/system");
803            }
804            return mDatabasesDir;
805        }
806    }
807
808    @Override
809    public Drawable getWallpaper() {
810        return getWallpaperManager().getDrawable();
811    }
812
813    @Override
814    public Drawable peekWallpaper() {
815        return getWallpaperManager().peekDrawable();
816    }
817
818    @Override
819    public int getWallpaperDesiredMinimumWidth() {
820        return getWallpaperManager().getDesiredMinimumWidth();
821    }
822
823    @Override
824    public int getWallpaperDesiredMinimumHeight() {
825        return getWallpaperManager().getDesiredMinimumHeight();
826    }
827
828    @Override
829    public void setWallpaper(Bitmap bitmap) throws IOException  {
830        getWallpaperManager().setBitmap(bitmap);
831    }
832
833    @Override
834    public void setWallpaper(InputStream data) throws IOException {
835        getWallpaperManager().setStream(data);
836    }
837
838    @Override
839    public void clearWallpaper() throws IOException {
840        getWallpaperManager().clear();
841    }
842
843    @Override
844    public void startActivity(Intent intent) {
845        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
846            throw new AndroidRuntimeException(
847                    "Calling startActivity() from outside of an Activity "
848                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
849                    + " Is this really what you want?");
850        }
851        mMainThread.getInstrumentation().execStartActivity(
852            getOuterContext(), mMainThread.getApplicationThread(), null,
853            (Activity)null, intent, -1);
854    }
855
856    @Override
857    public void startActivities(Intent[] intents) {
858        if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
859            throw new AndroidRuntimeException(
860                    "Calling startActivities() from outside of an Activity "
861                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
862                    + " Is this really what you want?");
863        }
864        mMainThread.getInstrumentation().execStartActivities(
865            getOuterContext(), mMainThread.getApplicationThread(), null,
866            (Activity)null, intents);
867    }
868
869    @Override
870    public void startIntentSender(IntentSender intent,
871            Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
872            throws IntentSender.SendIntentException {
873        try {
874            String resolvedType = null;
875            if (fillInIntent != null) {
876                resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
877            }
878            int result = ActivityManagerNative.getDefault()
879                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
880                        fillInIntent, resolvedType, null, null,
881                        0, flagsMask, flagsValues);
882            if (result == IActivityManager.START_CANCELED) {
883                throw new IntentSender.SendIntentException();
884            }
885            Instrumentation.checkStartActivityResult(result, null);
886        } catch (RemoteException e) {
887        }
888    }
889
890    @Override
891    public void sendBroadcast(Intent intent) {
892        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
893        try {
894            ActivityManagerNative.getDefault().broadcastIntent(
895                mMainThread.getApplicationThread(), intent, resolvedType, null,
896                Activity.RESULT_OK, null, null, null, false, false);
897        } catch (RemoteException e) {
898        }
899    }
900
901    @Override
902    public void sendBroadcast(Intent intent, String receiverPermission) {
903        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
904        try {
905            ActivityManagerNative.getDefault().broadcastIntent(
906                mMainThread.getApplicationThread(), intent, resolvedType, null,
907                Activity.RESULT_OK, null, null, receiverPermission, false, false);
908        } catch (RemoteException e) {
909        }
910    }
911
912    @Override
913    public void sendOrderedBroadcast(Intent intent,
914            String receiverPermission) {
915        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
916        try {
917            ActivityManagerNative.getDefault().broadcastIntent(
918                mMainThread.getApplicationThread(), intent, resolvedType, null,
919                Activity.RESULT_OK, null, null, receiverPermission, true, false);
920        } catch (RemoteException e) {
921        }
922    }
923
924    @Override
925    public void sendOrderedBroadcast(Intent intent,
926            String receiverPermission, BroadcastReceiver resultReceiver,
927            Handler scheduler, int initialCode, String initialData,
928            Bundle initialExtras) {
929        IIntentReceiver rd = null;
930        if (resultReceiver != null) {
931            if (mPackageInfo != null) {
932                if (scheduler == null) {
933                    scheduler = mMainThread.getHandler();
934                }
935                rd = mPackageInfo.getReceiverDispatcher(
936                    resultReceiver, getOuterContext(), scheduler,
937                    mMainThread.getInstrumentation(), false);
938            } else {
939                if (scheduler == null) {
940                    scheduler = mMainThread.getHandler();
941                }
942                rd = new LoadedApk.ReceiverDispatcher(
943                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
944            }
945        }
946        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
947        try {
948            ActivityManagerNative.getDefault().broadcastIntent(
949                mMainThread.getApplicationThread(), intent, resolvedType, rd,
950                initialCode, initialData, initialExtras, receiverPermission,
951                true, false);
952        } catch (RemoteException e) {
953        }
954    }
955
956    @Override
957    public void sendStickyBroadcast(Intent intent) {
958        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
959        try {
960            ActivityManagerNative.getDefault().broadcastIntent(
961                mMainThread.getApplicationThread(), intent, resolvedType, null,
962                Activity.RESULT_OK, null, null, null, false, true);
963        } catch (RemoteException e) {
964        }
965    }
966
967    @Override
968    public void sendStickyOrderedBroadcast(Intent intent,
969            BroadcastReceiver resultReceiver,
970            Handler scheduler, int initialCode, String initialData,
971            Bundle initialExtras) {
972        IIntentReceiver rd = null;
973        if (resultReceiver != null) {
974            if (mPackageInfo != null) {
975                if (scheduler == null) {
976                    scheduler = mMainThread.getHandler();
977                }
978                rd = mPackageInfo.getReceiverDispatcher(
979                    resultReceiver, getOuterContext(), scheduler,
980                    mMainThread.getInstrumentation(), false);
981            } else {
982                if (scheduler == null) {
983                    scheduler = mMainThread.getHandler();
984                }
985                rd = new LoadedApk.ReceiverDispatcher(
986                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
987            }
988        }
989        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
990        try {
991            ActivityManagerNative.getDefault().broadcastIntent(
992                mMainThread.getApplicationThread(), intent, resolvedType, rd,
993                initialCode, initialData, initialExtras, null,
994                true, true);
995        } catch (RemoteException e) {
996        }
997    }
998
999    @Override
1000    public void removeStickyBroadcast(Intent intent) {
1001        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
1002        if (resolvedType != null) {
1003            intent = new Intent(intent);
1004            intent.setDataAndType(intent.getData(), resolvedType);
1005        }
1006        try {
1007            ActivityManagerNative.getDefault().unbroadcastIntent(
1008                mMainThread.getApplicationThread(), intent);
1009        } catch (RemoteException e) {
1010        }
1011    }
1012
1013    @Override
1014    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1015        return registerReceiver(receiver, filter, null, null);
1016    }
1017
1018    @Override
1019    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
1020            String broadcastPermission, Handler scheduler) {
1021        return registerReceiverInternal(receiver, filter, broadcastPermission,
1022                scheduler, getOuterContext());
1023    }
1024
1025    private Intent registerReceiverInternal(BroadcastReceiver receiver,
1026            IntentFilter filter, String broadcastPermission,
1027            Handler scheduler, Context context) {
1028        IIntentReceiver rd = null;
1029        if (receiver != null) {
1030            if (mPackageInfo != null && context != null) {
1031                if (scheduler == null) {
1032                    scheduler = mMainThread.getHandler();
1033                }
1034                rd = mPackageInfo.getReceiverDispatcher(
1035                    receiver, context, scheduler,
1036                    mMainThread.getInstrumentation(), true);
1037            } else {
1038                if (scheduler == null) {
1039                    scheduler = mMainThread.getHandler();
1040                }
1041                rd = new LoadedApk.ReceiverDispatcher(
1042                        receiver, context, scheduler, null, true).getIIntentReceiver();
1043            }
1044        }
1045        try {
1046            return ActivityManagerNative.getDefault().registerReceiver(
1047                    mMainThread.getApplicationThread(), mBasePackageName,
1048                    rd, filter, broadcastPermission);
1049        } catch (RemoteException e) {
1050            return null;
1051        }
1052    }
1053
1054    @Override
1055    public void unregisterReceiver(BroadcastReceiver receiver) {
1056        if (mPackageInfo != null) {
1057            IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
1058                    getOuterContext(), receiver);
1059            try {
1060                ActivityManagerNative.getDefault().unregisterReceiver(rd);
1061            } catch (RemoteException e) {
1062            }
1063        } else {
1064            throw new RuntimeException("Not supported in system context");
1065        }
1066    }
1067
1068    @Override
1069    public ComponentName startService(Intent service) {
1070        try {
1071            ComponentName cn = ActivityManagerNative.getDefault().startService(
1072                mMainThread.getApplicationThread(), service,
1073                service.resolveTypeIfNeeded(getContentResolver()));
1074            if (cn != null && cn.getPackageName().equals("!")) {
1075                throw new SecurityException(
1076                        "Not allowed to start service " + service
1077                        + " without permission " + cn.getClassName());
1078            }
1079            return cn;
1080        } catch (RemoteException e) {
1081            return null;
1082        }
1083    }
1084
1085    @Override
1086    public boolean stopService(Intent service) {
1087        try {
1088            int res = ActivityManagerNative.getDefault().stopService(
1089                mMainThread.getApplicationThread(), service,
1090                service.resolveTypeIfNeeded(getContentResolver()));
1091            if (res < 0) {
1092                throw new SecurityException(
1093                        "Not allowed to stop service " + service);
1094            }
1095            return res != 0;
1096        } catch (RemoteException e) {
1097            return false;
1098        }
1099    }
1100
1101    @Override
1102    public boolean bindService(Intent service, ServiceConnection conn,
1103            int flags) {
1104        IServiceConnection sd;
1105        if (mPackageInfo != null) {
1106            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1107                    mMainThread.getHandler(), flags);
1108        } else {
1109            throw new RuntimeException("Not supported in system context");
1110        }
1111        try {
1112            IBinder token = getActivityToken();
1113            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
1114                    && mPackageInfo.getApplicationInfo().targetSdkVersion
1115                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
1116                flags |= BIND_WAIVE_PRIORITY;
1117            }
1118            int res = ActivityManagerNative.getDefault().bindService(
1119                mMainThread.getApplicationThread(), getActivityToken(),
1120                service, service.resolveTypeIfNeeded(getContentResolver()),
1121                sd, flags);
1122            if (res < 0) {
1123                throw new SecurityException(
1124                        "Not allowed to bind to service " + service);
1125            }
1126            return res != 0;
1127        } catch (RemoteException e) {
1128            return false;
1129        }
1130    }
1131
1132    @Override
1133    public void unbindService(ServiceConnection conn) {
1134        if (mPackageInfo != null) {
1135            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1136                    getOuterContext(), conn);
1137            try {
1138                ActivityManagerNative.getDefault().unbindService(sd);
1139            } catch (RemoteException e) {
1140            }
1141        } else {
1142            throw new RuntimeException("Not supported in system context");
1143        }
1144    }
1145
1146    @Override
1147    public boolean startInstrumentation(ComponentName className,
1148            String profileFile, Bundle arguments) {
1149        try {
1150            return ActivityManagerNative.getDefault().startInstrumentation(
1151                    className, profileFile, 0, arguments, null);
1152        } catch (RemoteException e) {
1153            // System has crashed, nothing we can do.
1154        }
1155        return false;
1156    }
1157
1158    @Override
1159    public Object getSystemService(String name) {
1160        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
1161        return fetcher == null ? null : fetcher.getService(this);
1162    }
1163
1164    private WallpaperManager getWallpaperManager() {
1165        return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
1166    }
1167
1168    /* package */ static DropBoxManager createDropBoxManager() {
1169        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1170        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1171        if (service == null) {
1172            // Don't return a DropBoxManager that will NPE upon use.
1173            // This also avoids caching a broken DropBoxManager in
1174            // getDropBoxManager during early boot, before the
1175            // DROPBOX_SERVICE is registered.
1176            return null;
1177        }
1178        return new DropBoxManager(service);
1179    }
1180
1181    @Override
1182    public int checkPermission(String permission, int pid, int uid) {
1183        if (permission == null) {
1184            throw new IllegalArgumentException("permission is null");
1185        }
1186
1187        try {
1188            return ActivityManagerNative.getDefault().checkPermission(
1189                    permission, pid, uid);
1190        } catch (RemoteException e) {
1191            return PackageManager.PERMISSION_DENIED;
1192        }
1193    }
1194
1195    @Override
1196    public int checkCallingPermission(String permission) {
1197        if (permission == null) {
1198            throw new IllegalArgumentException("permission is null");
1199        }
1200
1201        int pid = Binder.getCallingPid();
1202        if (pid != Process.myPid()) {
1203            return checkPermission(permission, pid,
1204                    Binder.getCallingUid());
1205        }
1206        return PackageManager.PERMISSION_DENIED;
1207    }
1208
1209    @Override
1210    public int checkCallingOrSelfPermission(String permission) {
1211        if (permission == null) {
1212            throw new IllegalArgumentException("permission is null");
1213        }
1214
1215        return checkPermission(permission, Binder.getCallingPid(),
1216                Binder.getCallingUid());
1217    }
1218
1219    private void enforce(
1220            String permission, int resultOfCheck,
1221            boolean selfToo, int uid, String message) {
1222        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1223            throw new SecurityException(
1224                    (message != null ? (message + ": ") : "") +
1225                    (selfToo
1226                     ? "Neither user " + uid + " nor current process has "
1227                     : "User " + uid + " does not have ") +
1228                    permission +
1229                    ".");
1230        }
1231    }
1232
1233    public void enforcePermission(
1234            String permission, int pid, int uid, String message) {
1235        enforce(permission,
1236                checkPermission(permission, pid, uid),
1237                false,
1238                uid,
1239                message);
1240    }
1241
1242    public void enforceCallingPermission(String permission, String message) {
1243        enforce(permission,
1244                checkCallingPermission(permission),
1245                false,
1246                Binder.getCallingUid(),
1247                message);
1248    }
1249
1250    public void enforceCallingOrSelfPermission(
1251            String permission, String message) {
1252        enforce(permission,
1253                checkCallingOrSelfPermission(permission),
1254                true,
1255                Binder.getCallingUid(),
1256                message);
1257    }
1258
1259    @Override
1260    public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1261         try {
1262            ActivityManagerNative.getDefault().grantUriPermission(
1263                    mMainThread.getApplicationThread(), toPackage, uri,
1264                    modeFlags);
1265        } catch (RemoteException e) {
1266        }
1267    }
1268
1269    @Override
1270    public void revokeUriPermission(Uri uri, int modeFlags) {
1271         try {
1272            ActivityManagerNative.getDefault().revokeUriPermission(
1273                    mMainThread.getApplicationThread(), uri,
1274                    modeFlags);
1275        } catch (RemoteException e) {
1276        }
1277    }
1278
1279    @Override
1280    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1281        try {
1282            return ActivityManagerNative.getDefault().checkUriPermission(
1283                    uri, pid, uid, modeFlags);
1284        } catch (RemoteException e) {
1285            return PackageManager.PERMISSION_DENIED;
1286        }
1287    }
1288
1289    @Override
1290    public int checkCallingUriPermission(Uri uri, int modeFlags) {
1291        int pid = Binder.getCallingPid();
1292        if (pid != Process.myPid()) {
1293            return checkUriPermission(uri, pid,
1294                    Binder.getCallingUid(), modeFlags);
1295        }
1296        return PackageManager.PERMISSION_DENIED;
1297    }
1298
1299    @Override
1300    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1301        return checkUriPermission(uri, Binder.getCallingPid(),
1302                Binder.getCallingUid(), modeFlags);
1303    }
1304
1305    @Override
1306    public int checkUriPermission(Uri uri, String readPermission,
1307            String writePermission, int pid, int uid, int modeFlags) {
1308        if (DEBUG) {
1309            Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1310                    + readPermission + " writePermission=" + writePermission
1311                    + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1312        }
1313        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1314            if (readPermission == null
1315                    || checkPermission(readPermission, pid, uid)
1316                    == PackageManager.PERMISSION_GRANTED) {
1317                return PackageManager.PERMISSION_GRANTED;
1318            }
1319        }
1320        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1321            if (writePermission == null
1322                    || checkPermission(writePermission, pid, uid)
1323                    == PackageManager.PERMISSION_GRANTED) {
1324                return PackageManager.PERMISSION_GRANTED;
1325            }
1326        }
1327        return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1328                : PackageManager.PERMISSION_DENIED;
1329    }
1330
1331    private String uriModeFlagToString(int uriModeFlags) {
1332        switch (uriModeFlags) {
1333            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1334                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1335                return "read and write";
1336            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1337                return "read";
1338            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1339                return "write";
1340        }
1341        throw new IllegalArgumentException(
1342                "Unknown permission mode flags: " + uriModeFlags);
1343    }
1344
1345    private void enforceForUri(
1346            int modeFlags, int resultOfCheck, boolean selfToo,
1347            int uid, Uri uri, String message) {
1348        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1349            throw new SecurityException(
1350                    (message != null ? (message + ": ") : "") +
1351                    (selfToo
1352                     ? "Neither user " + uid + " nor current process has "
1353                     : "User " + uid + " does not have ") +
1354                    uriModeFlagToString(modeFlags) +
1355                    " permission on " +
1356                    uri +
1357                    ".");
1358        }
1359    }
1360
1361    public void enforceUriPermission(
1362            Uri uri, int pid, int uid, int modeFlags, String message) {
1363        enforceForUri(
1364                modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1365                false, uid, uri, message);
1366    }
1367
1368    public void enforceCallingUriPermission(
1369            Uri uri, int modeFlags, String message) {
1370        enforceForUri(
1371                modeFlags, checkCallingUriPermission(uri, modeFlags),
1372                false, Binder.getCallingUid(), uri, message);
1373    }
1374
1375    public void enforceCallingOrSelfUriPermission(
1376            Uri uri, int modeFlags, String message) {
1377        enforceForUri(
1378                modeFlags,
1379                checkCallingOrSelfUriPermission(uri, modeFlags), true,
1380                Binder.getCallingUid(), uri, message);
1381    }
1382
1383    public void enforceUriPermission(
1384            Uri uri, String readPermission, String writePermission,
1385            int pid, int uid, int modeFlags, String message) {
1386        enforceForUri(modeFlags,
1387                      checkUriPermission(
1388                              uri, readPermission, writePermission, pid, uid,
1389                              modeFlags),
1390                      false,
1391                      uid,
1392                      uri,
1393                      message);
1394    }
1395
1396    @Override
1397    public Context createPackageContext(String packageName, int flags)
1398        throws PackageManager.NameNotFoundException {
1399        if (packageName.equals("system") || packageName.equals("android")) {
1400            return new ContextImpl(mMainThread.getSystemContext());
1401        }
1402
1403        LoadedApk pi =
1404            mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags);
1405        if (pi != null) {
1406            ContextImpl c = new ContextImpl();
1407            c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
1408            c.init(pi, null, mMainThread, mResources, mBasePackageName);
1409            if (c.mResources != null) {
1410                return c;
1411            }
1412        }
1413
1414        // Should be a better exception.
1415        throw new PackageManager.NameNotFoundException(
1416            "Application package " + packageName + " not found");
1417    }
1418
1419    @Override
1420    public boolean isRestricted() {
1421        return mRestricted;
1422    }
1423
1424    private File getDataDirFile() {
1425        if (mPackageInfo != null) {
1426            return mPackageInfo.getDataDirFile();
1427        }
1428        throw new RuntimeException("Not supported in system context");
1429    }
1430
1431    @Override
1432    public File getDir(String name, int mode) {
1433        name = "app_" + name;
1434        File file = makeFilename(getDataDirFile(), name);
1435        if (!file.exists()) {
1436            file.mkdir();
1437            setFilePermissionsFromMode(file.getPath(), mode,
1438                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1439        }
1440        return file;
1441    }
1442
1443    static ContextImpl createSystemContext(ActivityThread mainThread) {
1444        ContextImpl context = new ContextImpl();
1445        context.init(Resources.getSystem(), mainThread);
1446        return context;
1447    }
1448
1449    ContextImpl() {
1450        mOuterContext = this;
1451    }
1452
1453    /**
1454     * Create a new ApplicationContext from an existing one.  The new one
1455     * works and operates the same as the one it is copying.
1456     *
1457     * @param context Existing application context.
1458     */
1459    public ContextImpl(ContextImpl context) {
1460        mPackageInfo = context.mPackageInfo;
1461        mBasePackageName = context.mBasePackageName;
1462        mResources = context.mResources;
1463        mMainThread = context.mMainThread;
1464        mContentResolver = context.mContentResolver;
1465        mOuterContext = this;
1466    }
1467
1468    final void init(LoadedApk packageInfo,
1469            IBinder activityToken, ActivityThread mainThread) {
1470        init(packageInfo, activityToken, mainThread, null, null);
1471    }
1472
1473    final void init(LoadedApk packageInfo,
1474                IBinder activityToken, ActivityThread mainThread,
1475                Resources container, String basePackageName) {
1476        mPackageInfo = packageInfo;
1477        mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
1478        mResources = mPackageInfo.getResources(mainThread);
1479
1480        if (mResources != null && container != null
1481                && container.getCompatibilityInfo().applicationScale !=
1482                        mResources.getCompatibilityInfo().applicationScale) {
1483            if (DEBUG) {
1484                Log.d(TAG, "loaded context has different scaling. Using container's" +
1485                        " compatiblity info:" + container.getDisplayMetrics());
1486            }
1487            mResources = mainThread.getTopLevelResources(
1488                    mPackageInfo.getResDir(), container.getCompatibilityInfo());
1489        }
1490        mMainThread = mainThread;
1491        mContentResolver = new ApplicationContentResolver(this, mainThread);
1492
1493        setActivityToken(activityToken);
1494    }
1495
1496    final void init(Resources resources, ActivityThread mainThread) {
1497        mPackageInfo = null;
1498        mBasePackageName = null;
1499        mResources = resources;
1500        mMainThread = mainThread;
1501        mContentResolver = new ApplicationContentResolver(this, mainThread);
1502    }
1503
1504    final void scheduleFinalCleanup(String who, String what) {
1505        mMainThread.scheduleContextCleanup(this, who, what);
1506    }
1507
1508    final void performFinalCleanup(String who, String what) {
1509        //Log.i(TAG, "Cleanup up context: " + this);
1510        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1511    }
1512
1513    final Context getReceiverRestrictedContext() {
1514        if (mReceiverRestrictedContext != null) {
1515            return mReceiverRestrictedContext;
1516        }
1517        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1518    }
1519
1520    final void setActivityToken(IBinder token) {
1521        mActivityToken = token;
1522    }
1523
1524    final void setOuterContext(Context context) {
1525        mOuterContext = context;
1526    }
1527
1528    final Context getOuterContext() {
1529        return mOuterContext;
1530    }
1531
1532    final IBinder getActivityToken() {
1533        return mActivityToken;
1534    }
1535
1536    static void setFilePermissionsFromMode(String name, int mode,
1537            int extraPermissions) {
1538        int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1539            |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1540            |extraPermissions;
1541        if ((mode&MODE_WORLD_READABLE) != 0) {
1542            perms |= FileUtils.S_IROTH;
1543        }
1544        if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1545            perms |= FileUtils.S_IWOTH;
1546        }
1547        if (DEBUG) {
1548            Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1549                  + ", perms=0x" + Integer.toHexString(perms));
1550        }
1551        FileUtils.setPermissions(name, perms, -1, -1);
1552    }
1553
1554    private File validateFilePath(String name, boolean createDirectory) {
1555        File dir;
1556        File f;
1557
1558        if (name.charAt(0) == File.separatorChar) {
1559            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1560            dir = new File(dirPath);
1561            name = name.substring(name.lastIndexOf(File.separatorChar));
1562            f = new File(dir, name);
1563        } else {
1564            dir = getDatabasesDir();
1565            f = makeFilename(dir, name);
1566        }
1567
1568        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1569            FileUtils.setPermissions(dir.getPath(),
1570                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1571                -1, -1);
1572        }
1573
1574        return f;
1575    }
1576
1577    private File makeFilename(File base, String name) {
1578        if (name.indexOf(File.separatorChar) < 0) {
1579            return new File(base, name);
1580        }
1581        throw new IllegalArgumentException(
1582                "File " + name + " contains a path separator");
1583    }
1584
1585    // ----------------------------------------------------------------------
1586    // ----------------------------------------------------------------------
1587    // ----------------------------------------------------------------------
1588
1589    private static final class ApplicationContentResolver extends ContentResolver {
1590        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
1591            super(context);
1592            mMainThread = mainThread;
1593        }
1594
1595        @Override
1596        protected IContentProvider acquireProvider(Context context, String name) {
1597            return mMainThread.acquireProvider(context, name);
1598        }
1599
1600        @Override
1601        protected IContentProvider acquireExistingProvider(Context context, String name) {
1602            return mMainThread.acquireExistingProvider(context, name);
1603        }
1604
1605        @Override
1606        public boolean releaseProvider(IContentProvider provider) {
1607            return mMainThread.releaseProvider(provider);
1608        }
1609
1610        private final ActivityThread mMainThread;
1611    }
1612}
1613