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