/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app; import com.android.internal.util.XmlUtils; import com.google.android.collect.Maps; import org.xmlpull.v1.XmlPullParserException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; //import android.content.IContentProvider; import android.content.Intent; import android.content.IntentFilter; import android.content.IIntentReceiver; //import android.content.IntentSender; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; //import android.content.pm.FeatureInfo; //import android.content.pm.IPackageDataObserver; //import android.content.pm.IPackageDeleteObserver; //import android.content.pm.IPackageInstallObserver; //import android.content.pm.IPackageMoveObserver; //import android.content.pm.IPackageManager; //import android.content.pm.IPackageStatsObserver; //import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.PackageParser.Package; import android.content.res.AssetManager; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.hardware.SensorManager; //import android.location.ILocationManager; import android.location.LocationManager; import android.media.AudioManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; import android.os.IBinder; import android.os.Looper; import android.os.PowerManager; //import android.os.Process; import android.os.RemoteException; //import android.os.ServiceManager; import android.os.FileUtils.FileStatus; import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.WindowManagerImpl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; /** * Common implementation of Context API, which provides the base * context object for Activity and other application components. */ class ContextImpl extends Context { private final static String TAG = "ApplicationContext"; private final static boolean DEBUG = false; private final static boolean DEBUG_ICONS = false; private static final Object sSync = new Object(); private static AlarmManager sAlarmManager; private static PowerManager sPowerManager; private static LocationManager sLocationManager; private AudioManager mAudioManager; /*package*/ LoadedApk mPackageInfo; private Resources mResources; /*package*/ ActivityThread mMainThread; private Context mOuterContext; private IBinder mActivityToken = null; private ApplicationContentResolver mContentResolver; private int mThemeResource = 0; private Resources.Theme mTheme = null; private PackageManager mPackageManager; private NotificationManager mNotificationManager = null; private ActivityManager mActivityManager = null; private Context mReceiverRestrictedContext = null; private SensorManager mSensorManager = null; private LayoutInflater mLayoutInflater = null; private boolean mRestricted; private final Object mSync = new Object(); private File mDatabasesDir; private File mPreferencesDir; private File mFilesDir; private File mCacheDir; private File mExternalFilesDir; private File mExternalCacheDir; private static long sInstanceCount = 0; private static final String[] EMPTY_FILE_LIST = {}; // For debug only /* @Override protected void finalize() throws Throwable { super.finalize(); --sInstanceCount; } */ public static long getInstanceCount() { return sInstanceCount; } @Override public Resources getResources() { return mResources; } @Override public ContentResolver getContentResolver() { return mContentResolver; } @Override public Context getApplicationContext() { return (mPackageInfo != null) ? mPackageInfo.getApplication() : mMainThread.getApplication(); } @Override public void setTheme(int resid) { mThemeResource = resid; } @Override public Resources.Theme getTheme() { if (mTheme == null) { if (mThemeResource == 0) { mThemeResource = com.android.internal.R.style.Theme; } mTheme = mResources.newTheme(); mTheme.applyStyle(mThemeResource, true); } return mTheme; } private static File makeBackupFile(File prefsFile) { return new File(prefsFile.getPath() + ".bak"); } @Override public FileInputStream openFileInput(String name) throws FileNotFoundException { File f = makeFilename(getFilesDir(), name); return new FileInputStream(f); } @Override public FileOutputStream openFileOutput(String name, int mode) throws FileNotFoundException { final boolean append = (mode&MODE_APPEND) != 0; File f = makeFilename(getFilesDir(), name); try { FileOutputStream fos = new FileOutputStream(f, append); setFilePermissionsFromMode(f.getPath(), mode, 0); return fos; } catch (FileNotFoundException e) { } File parent = f.getParentFile(); parent.mkdir(); FileUtils.setPermissions( parent.getPath(), FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, -1, -1); FileOutputStream fos = new FileOutputStream(f, append); setFilePermissionsFromMode(f.getPath(), mode, 0); return fos; } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } @Override public void unregisterReceiver(BroadcastReceiver receiver) {} private SensorManager getSensorManager() { synchronized (mSync) { if (mSensorManager == null) { mSensorManager = new SensorManager(mMainThread.getHandler().getLooper()); } } return mSensorManager; } private AudioManager getAudioManager() { if (mAudioManager == null) { mAudioManager = new AudioManager(this); } return mAudioManager; } private void enforce( String permission, int resultOfCheck, boolean selfToo, int uid, String message) { if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { throw new SecurityException( (message != null ? (message + ": ") : "") + (selfToo ? "Neither user " + uid + " nor current process has " : "User " + uid + " does not have ") + permission + "."); } } private String uriModeFlagToString(int uriModeFlags) { switch (uriModeFlags) { case Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION: return "read and write"; case Intent.FLAG_GRANT_READ_URI_PERMISSION: return "read"; case Intent.FLAG_GRANT_WRITE_URI_PERMISSION: return "write"; } throw new IllegalArgumentException( "Unknown permission mode flags: " + uriModeFlags); } private void enforceForUri( int modeFlags, int resultOfCheck, boolean selfToo, int uid, Uri uri, String message) { if (resultOfCheck != PackageManager.PERMISSION_GRANTED) { throw new SecurityException( (message != null ? (message + ": ") : "") + (selfToo ? "Neither user " + uid + " nor current process has " : "User " + uid + " does not have ") + uriModeFlagToString(modeFlags) + " permission on " + uri + "."); } } @Override public Context createPackageContext(String packageName, int flags) throws PackageManager.NameNotFoundException { if (packageName.equals("system") || packageName.equals("android")) { return new ContextImpl(mMainThread.getSystemContext()); } LoadedApk pi = mMainThread.getPackageInfo(packageName, flags); if (pi != null) { ContextImpl c = new ContextImpl(); c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; c.init(pi, null, mMainThread, mResources); if (c.mResources != null) { return c; } } // Should be a better exception. throw new PackageManager.NameNotFoundException( "Application package " + packageName + " not found"); } @Override public boolean isRestricted() { return mRestricted; } static ContextImpl createSystemContext(ActivityThread mainThread) { ContextImpl context = new ContextImpl(); context.init(Resources.getSystem(), mainThread); return context; } ContextImpl() { // For debug only //++sInstanceCount; mOuterContext = this; } /** * Create a new ApplicationContext from an existing one. The new one * works and operates the same as the one it is copying. * * @param context Existing application context. */ public ContextImpl(ContextImpl context) { ++sInstanceCount; mPackageInfo = context.mPackageInfo; mResources = context.mResources; mMainThread = context.mMainThread; mContentResolver = context.mContentResolver; mOuterContext = this; } final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) { init(packageInfo, activityToken, mainThread, null); } final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread, Resources container) { mPackageInfo = packageInfo; /** * @Mayloon update * resource are not initialized in package info * so we load related package resource here */ mResources = ((PackageManager) Context.getSystemContext().getSystemService(PACKAGE_SERVICE)).getPackageResources(mPackageInfo.getPackageName()); /* mResources = mPackageInfo.getResources(mainThread); if (mResources != null && container != null && container.getCompatibilityInfo().applicationScale != mResources.getCompatibilityInfo().applicationScale) { if (DEBUG) { Log.d(TAG, "loaded context has different scaling. Using container's" + " compatiblity info:" + container.getDisplayMetrics()); } mResources = mainThread.getTopLevelResources( mPackageInfo.getResDir(), container.getCompatibilityInfo().copy()); } */ mMainThread = mainThread; mContentResolver = new ApplicationContentResolver(this, mainThread); setActivityToken(activityToken); } final void init(Resources resources, ActivityThread mainThread) { mPackageInfo = null; mResources = resources; mMainThread = mainThread; mContentResolver = new ApplicationContentResolver(this, mainThread); } final Context getReceiverRestrictedContext() { if (mReceiverRestrictedContext != null) { return mReceiverRestrictedContext; } return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext()); } final void setActivityToken(IBinder token) { mActivityToken = token; } private static void setFilePermissionsFromMode(String name, int mode, int extraPermissions) { int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR |FileUtils.S_IRGRP|FileUtils.S_IWGRP |extraPermissions; if ((mode&MODE_WORLD_READABLE) != 0) { perms |= FileUtils.S_IROTH; } if ((mode&MODE_WORLD_WRITEABLE) != 0) { perms |= FileUtils.S_IWOTH; } if (DEBUG) { Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode) + ", perms=0x" + Integer.toHexString(perms)); } FileUtils.setPermissions(name, perms, -1, -1); } private File makeFilename(File base, String name) { if (name.indexOf(File.separatorChar) < 0) { return new File(base, name); } throw new IllegalArgumentException( "File " + name + " contains a path separator"); } @Override public String getPackageName() { if (mPackageInfo != null) { return mPackageInfo.getPackageName(); } throw new RuntimeException("Not supported in system context"); } @Override public void startActivity(Intent intent) { if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { throw new AndroidRuntimeException( "Calling startActivity() from outside of an Activity " + " context requires the FLAG_ACTIVITY_NEW_TASK flag." + " Is this really what you want?"); } mMainThread.getInstrumentation().execStartActivity( getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1); } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- /*package*/ static final class ApplicationPackageManager extends PackageManager {} // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- //private static final class SharedPreferencesImpl implements SharedPreferences {} }