/*
 * 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 android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.IContentProvider;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.ReceiverCallNotAllowedException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.CompatResources;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.system.StructStat;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.autofill.AutofillManager.AutofillClient;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import libcore.io.Memory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor;

class ReceiverRestrictedContext extends ContextWrapper {
    ReceiverRestrictedContext(Context base) {
        super(base);
    }

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        return registerReceiver(receiver, filter, null, null);
    }

    @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler) {
        if (receiver == null) {
            // Allow retrieving current sticky broadcast; this is safe since we
            // aren't actually registering a receiver.
            return super.registerReceiver(null, filter, broadcastPermission, scheduler);
        } else {
            throw new ReceiverCallNotAllowedException(
                    "BroadcastReceiver components are not allowed to register to receive intents");
        }
    }

    @Override
    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
            IntentFilter filter, String broadcastPermission, Handler scheduler) {
        if (receiver == null) {
            // Allow retrieving current sticky broadcast; this is safe since we
            // aren't actually registering a receiver.
            return super.registerReceiverAsUser(null, user, filter, broadcastPermission, scheduler);
        } else {
            throw new ReceiverCallNotAllowedException(
                    "BroadcastReceiver components are not allowed to register to receive intents");
        }
    }

    @Override
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        throw new ReceiverCallNotAllowedException(
                "BroadcastReceiver components are not allowed to bind to services");
    }
}

Common implementation of Context API, which provides the base context object for Activity and other application components.
/** * 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 = "ContextImpl"; private final static boolean DEBUG = false; private static final String XATTR_INODE_CACHE = "user.inode_cache"; private static final String XATTR_INODE_CODE_CACHE = "user.inode_code_cache";
Map from package name, to preference name, to cached preferences.
/** * Map from package name, to preference name, to cached preferences. */
@GuardedBy("ContextImpl.class") private static ArrayMap<String, ArrayMap<File, SharedPreferencesImpl>> sSharedPrefsCache;
Map from preference name to generated path.
/** * Map from preference name to generated path. */
@GuardedBy("ContextImpl.class") private ArrayMap<String, File> mSharedPrefsPaths; final @NonNull ActivityThread mMainThread; final @NonNull LoadedApk mPackageInfo; private @Nullable ClassLoader mClassLoader; private final @Nullable IBinder mActivityToken; private final @NonNull UserHandle mUser; private final ApplicationContentResolver mContentResolver; private final String mBasePackageName; private final String mOpPackageName; private final @NonNull ResourcesManager mResourcesManager; private @NonNull Resources mResources; private @Nullable Display mDisplay; // may be null if default display private final int mFlags; private Context mOuterContext; private int mThemeResource = 0; private Resources.Theme mTheme = null; private PackageManager mPackageManager; private Context mReceiverRestrictedContext = null; // The name of the split this Context is representing. May be null. private @Nullable String mSplitName = null; private AutofillClient mAutofillClient = null; private boolean mIsAutofillCompatEnabled; private final Object mSync = new Object(); @GuardedBy("mSync") private File mDatabasesDir; @GuardedBy("mSync") private File mPreferencesDir; @GuardedBy("mSync") private File mFilesDir; @GuardedBy("mSync") private File mNoBackupFilesDir; @GuardedBy("mSync") private File mCacheDir; @GuardedBy("mSync") private File mCodeCacheDir; // The system service cache for the system services that are cached per-ContextImpl. final Object[] mServiceCache = SystemServiceRegistry.createServiceCache(); static final int STATE_UNINITIALIZED = 0; static final int STATE_INITIALIZING = 1; static final int STATE_READY = 2; static final int STATE_NOT_FOUND = 3;
@hide
/** @hide */
@IntDef(prefix = { "STATE_" }, value = { STATE_UNINITIALIZED, STATE_INITIALIZING, STATE_READY, STATE_NOT_FOUND, }) @Retention(RetentionPolicy.SOURCE) @interface ServiceInitializationState {}
Initialization state for each service. Any of STATE_UNINITIALIZED, STATE_INITIALIZING or STATE_READY,
/** * Initialization state for each service. Any of {@link #STATE_UNINITIALIZED}, * {@link #STATE_INITIALIZING} or {@link #STATE_READY}, */
@ServiceInitializationState final int[] mServiceInitializationStateArray = new int[mServiceCache.length]; static ContextImpl getImpl(Context context) { Context nextContext; while ((context instanceof ContextWrapper) && (nextContext=((ContextWrapper)context).getBaseContext()) != null) { context = nextContext; } return (ContextImpl)context; } @Override public AssetManager getAssets() { return getResources().getAssets(); } @Override public Resources getResources() { return mResources; } @Override public PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; } @Override public ContentResolver getContentResolver() { return mContentResolver; } @Override public Looper getMainLooper() { return mMainThread.getLooper(); } @Override public Executor getMainExecutor() { return mMainThread.getExecutor(); } @Override public Context getApplicationContext() { return (mPackageInfo != null) ? mPackageInfo.getApplication() : mMainThread.getApplication(); } @Override public void setTheme(int resId) { synchronized (mSync) { if (mThemeResource != resId) { mThemeResource = resId; initializeTheme(); } } } @Override public int getThemeResId() { synchronized (mSync) { return mThemeResource; } } @Override public Resources.Theme getTheme() { synchronized (mSync) { if (mTheme != null) { return mTheme; } mThemeResource = Resources.selectDefaultTheme(mThemeResource, getOuterContext().getApplicationInfo().targetSdkVersion); initializeTheme(); return mTheme; } } private void initializeTheme() { if (mTheme == null) { mTheme = mResources.newTheme(); } mTheme.applyStyle(mThemeResource, true); } @Override public ClassLoader getClassLoader() { return mClassLoader != null ? mClassLoader : (mPackageInfo != null ? mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader()); } @Override public String getPackageName() { if (mPackageInfo != null) { return mPackageInfo.getPackageName(); } // No mPackageInfo means this is a Context for the system itself, // and this here is its name. return "android"; }
@hide
/** @hide */
@Override public String getBasePackageName() { return mBasePackageName != null ? mBasePackageName : getPackageName(); }
@hide
/** @hide */
@Override public String getOpPackageName() { return mOpPackageName != null ? mOpPackageName : getBasePackageName(); } @Override public ApplicationInfo getApplicationInfo() { if (mPackageInfo != null) { return mPackageInfo.getApplicationInfo(); } throw new RuntimeException("Not supported in system context"); } @Override public String getPackageResourcePath() { if (mPackageInfo != null) { return mPackageInfo.getResDir(); } throw new RuntimeException("Not supported in system context"); } @Override public String getPackageCodePath() { if (mPackageInfo != null) { return mPackageInfo.getAppDir(); } throw new RuntimeException("Not supported in system context"); } @Override public SharedPreferences getSharedPreferences(String name, int mode) { // At least one application in the world actually passes in a null // name. This happened to work because when we generated the file name // we would stringify it to "null.xml". Nice. if (mPackageInfo.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.KITKAT) { if (name == null) { name = "null"; } } File file; synchronized (ContextImpl.class) { if (mSharedPrefsPaths == null) { mSharedPrefsPaths = new ArrayMap<>(); } file = mSharedPrefsPaths.get(name); if (file == null) { file = getSharedPreferencesPath(name); mSharedPrefsPaths.put(name, file); } } return getSharedPreferences(file, mode); } @Override public SharedPreferences getSharedPreferences(File file, int mode) { SharedPreferencesImpl sp; synchronized (ContextImpl.class) { final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked(); sp = cache.get(file); if (sp == null) { checkMode(mode); if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) { if (isCredentialProtectedStorage() && !getSystemService(UserManager.class) .isUserUnlockingOrUnlocked(UserHandle.myUserId())) { throw new IllegalStateException("SharedPreferences in credential encrypted " + "storage are not available until after user is unlocked"); } } sp = new SharedPreferencesImpl(file, mode); cache.put(file, sp); return sp; } } if ((mode & Context.MODE_MULTI_PROCESS) != 0 || getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) { // If somebody else (some other process) changed the prefs // file behind our back, we reload it. This has been the // historical (if undocumented) behavior. sp.startReloadIfChangedUnexpectedly(); } return sp; } @GuardedBy("ContextImpl.class") private ArrayMap<File, SharedPreferencesImpl> getSharedPreferencesCacheLocked() { if (sSharedPrefsCache == null) { sSharedPrefsCache = new ArrayMap<>(); } final String packageName = getPackageName(); ArrayMap<File, SharedPreferencesImpl> packagePrefs = sSharedPrefsCache.get(packageName); if (packagePrefs == null) { packagePrefs = new ArrayMap<>(); sSharedPrefsCache.put(packageName, packagePrefs); } return packagePrefs; } @Override public void reloadSharedPreferences() { // Build the list of all per-context impls (i.e. caches) we know about ArrayList<SharedPreferencesImpl> spImpls = new ArrayList<>(); synchronized (ContextImpl.class) { final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked(); for (int i = 0; i < cache.size(); i++) { final SharedPreferencesImpl sp = cache.valueAt(i); if (sp != null) { spImpls.add(sp); } } } // Issue the reload outside the cache lock for (int i = 0; i < spImpls.size(); i++) { spImpls.get(i).startReloadIfChangedUnexpectedly(); } }
Try our best to migrate all files from source to target that match requested prefix.
Returns:the number of files moved, or -1 if there was trouble.
/** * Try our best to migrate all files from source to target that match * requested prefix. * * @return the number of files moved, or -1 if there was trouble. */
private static int moveFiles(File sourceDir, File targetDir, final String prefix) { final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith(prefix); } }); int res = 0; for (File sourceFile : sourceFiles) { final File targetFile = new File(targetDir, sourceFile.getName()); Log.d(TAG, "Migrating " + sourceFile + " to " + targetFile); try { FileUtils.copyFileOrThrow(sourceFile, targetFile); FileUtils.copyPermissions(sourceFile, targetFile); if (!sourceFile.delete()) { throw new IOException("Failed to clean up " + sourceFile); } if (res != -1) { res++; } } catch (IOException e) { Log.w(TAG, "Failed to migrate " + sourceFile + ": " + e); res = -1; } } return res; } @Override public boolean moveSharedPreferencesFrom(Context sourceContext, String name) { synchronized (ContextImpl.class) { final File source = sourceContext.getSharedPreferencesPath(name); final File target = getSharedPreferencesPath(name); final int res = moveFiles(source.getParentFile(), target.getParentFile(), source.getName()); if (res > 0) { // We moved at least one file, so evict any in-memory caches for // either location final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked(); cache.remove(source); cache.remove(target); } return res != -1; } } @Override public boolean deleteSharedPreferences(String name) { synchronized (ContextImpl.class) { final File prefs = getSharedPreferencesPath(name); final File prefsBackup = SharedPreferencesImpl.makeBackupFile(prefs); // Evict any in-memory caches final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked(); cache.remove(prefs); prefs.delete(); prefsBackup.delete(); // We failed if files are still lingering return !(prefs.exists() || prefsBackup.exists()); } } private File getPreferencesDir() { synchronized (mSync) { if (mPreferencesDir == null) { mPreferencesDir = new File(getDataDir(), "shared_prefs"); } return ensurePrivateDirExists(mPreferencesDir); } } @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 { checkMode(mode); 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 boolean deleteFile(String name) { File f = makeFilename(getFilesDir(), name); return f.delete(); }
Common-path handling of app data dir creation
/** * Common-path handling of app data dir creation */
private static File ensurePrivateDirExists(File file) { return ensurePrivateDirExists(file, 0771, -1, null); } private static File ensurePrivateCacheDirExists(File file, String xattr) { final int gid = UserHandle.getCacheAppGid(Process.myUid()); return ensurePrivateDirExists(file, 02771, gid, xattr); } private static File ensurePrivateDirExists(File file, int mode, int gid, String xattr) { if (!file.exists()) { final String path = file.getAbsolutePath(); try { Os.mkdir(path, mode); Os.chmod(path, mode); if (gid != -1) { Os.chown(path, -1, gid); } } catch (ErrnoException e) { if (e.errno == OsConstants.EEXIST) { // We must have raced with someone; that's okay } else { Log.w(TAG, "Failed to ensure " + file + ": " + e.getMessage()); } } if (xattr != null) { try { final StructStat stat = Os.stat(file.getAbsolutePath()); final byte[] value = new byte[8]; Memory.pokeLong(value, 0, stat.st_ino, ByteOrder.nativeOrder()); Os.setxattr(file.getParentFile().getAbsolutePath(), xattr, value, 0); } catch (ErrnoException e) { Log.w(TAG, "Failed to update " + xattr + ": " + e.getMessage()); } } } return file; } @Override public File getFilesDir() { synchronized (mSync) { if (mFilesDir == null) { mFilesDir = new File(getDataDir(), "files"); } return ensurePrivateDirExists(mFilesDir); } } @Override public File getNoBackupFilesDir() { synchronized (mSync) { if (mNoBackupFilesDir == null) { mNoBackupFilesDir = new File(getDataDir(), "no_backup"); } return ensurePrivateDirExists(mNoBackupFilesDir); } } @Override public File getExternalFilesDir(String type) { // Operates on primary external storage final File[] dirs = getExternalFilesDirs(type); return (dirs != null && dirs.length > 0) ? dirs[0] : null; } @Override public File[] getExternalFilesDirs(String type) { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppFilesDirs(getPackageName()); if (type != null) { dirs = Environment.buildPaths(dirs, type); } return ensureExternalDirsExistOrFilter(dirs); } } @Override public File getObbDir() { // Operates on primary external storage final File[] dirs = getObbDirs(); return (dirs != null && dirs.length > 0) ? dirs[0] : null; } @Override public File[] getObbDirs() { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppObbDirs(getPackageName()); return ensureExternalDirsExistOrFilter(dirs); } } @Override public File getCacheDir() { synchronized (mSync) { if (mCacheDir == null) { mCacheDir = new File(getDataDir(), "cache"); } return ensurePrivateCacheDirExists(mCacheDir, XATTR_INODE_CACHE); } } @Override public File getCodeCacheDir() { synchronized (mSync) { if (mCodeCacheDir == null) { mCodeCacheDir = new File(getDataDir(), "code_cache"); } return ensurePrivateCacheDirExists(mCodeCacheDir, XATTR_INODE_CODE_CACHE); } } @Override public File getExternalCacheDir() { // Operates on primary external storage final File[] dirs = getExternalCacheDirs(); return (dirs != null && dirs.length > 0) ? dirs[0] : null; } @Override public File[] getExternalCacheDirs() { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppCacheDirs(getPackageName()); return ensureExternalDirsExistOrFilter(dirs); } } @Override public File[] getExternalMediaDirs() { synchronized (mSync) { File[] dirs = Environment.buildExternalStorageAppMediaDirs(getPackageName()); return ensureExternalDirsExistOrFilter(dirs); } }
@hide
/** * @hide */
@Nullable @Override public File getPreloadsFileCache() { return Environment.getDataPreloadsFileCacheDirectory(getPackageName()); } @Override public File getFileStreamPath(String name) { return makeFilename(getFilesDir(), name); } @Override public File getSharedPreferencesPath(String name) { return makeFilename(getPreferencesDir(), name + ".xml"); } @Override public String[] fileList() { return FileUtils.listOrEmpty(getFilesDir()); } @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) { return openOrCreateDatabase(name, mode, factory, null); } @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler) { checkMode(mode); File f = getDatabasePath(name); int flags = SQLiteDatabase.CREATE_IF_NECESSARY; if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) { flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING; } if ((mode & MODE_NO_LOCALIZED_COLLATORS) != 0) { flags |= SQLiteDatabase.NO_LOCALIZED_COLLATORS; } SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler); setFilePermissionsFromMode(f.getPath(), mode, 0); return db; } @Override public boolean moveDatabaseFrom(Context sourceContext, String name) { synchronized (ContextImpl.class) { final File source = sourceContext.getDatabasePath(name); final File target = getDatabasePath(name); return moveFiles(source.getParentFile(), target.getParentFile(), source.getName()) != -1; } } @Override public boolean deleteDatabase(String name) { try { File f = getDatabasePath(name); return SQLiteDatabase.deleteDatabase(f); } catch (Exception e) { } return false; } @Override public File getDatabasePath(String name) { File dir; File f; if (name.charAt(0) == File.separatorChar) { String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar)); dir = new File(dirPath); name = name.substring(name.lastIndexOf(File.separatorChar)); f = new File(dir, name); if (!dir.isDirectory() && dir.mkdir()) { FileUtils.setPermissions(dir.getPath(), FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, -1, -1); } } else { dir = getDatabasesDir(); f = makeFilename(dir, name); } return f; } @Override public String[] databaseList() { return FileUtils.listOrEmpty(getDatabasesDir()); } private File getDatabasesDir() { synchronized (mSync) { if (mDatabasesDir == null) { if ("android".equals(getPackageName())) { mDatabasesDir = new File("/data/system"); } else { mDatabasesDir = new File(getDataDir(), "databases"); } } return ensurePrivateDirExists(mDatabasesDir); } } @Override @Deprecated public Drawable getWallpaper() { return getWallpaperManager().getDrawable(); } @Override @Deprecated public Drawable peekWallpaper() { return getWallpaperManager().peekDrawable(); } @Override @Deprecated public int getWallpaperDesiredMinimumWidth() { return getWallpaperManager().getDesiredMinimumWidth(); } @Override @Deprecated public int getWallpaperDesiredMinimumHeight() { return getWallpaperManager().getDesiredMinimumHeight(); } @Override @Deprecated public void setWallpaper(Bitmap bitmap) throws IOException { getWallpaperManager().setBitmap(bitmap); } @Override @Deprecated public void setWallpaper(InputStream data) throws IOException { getWallpaperManager().setStream(data); } @Override @Deprecated public void clearWallpaper() throws IOException { getWallpaperManager().clear(); } private WallpaperManager getWallpaperManager() { return getSystemService(WallpaperManager.class); } @Override public void startActivity(Intent intent) { warnIfCallingFromSystemProcess(); startActivity(intent, null); }
@hide
/** @hide */
@Override public void startActivityAsUser(Intent intent, UserHandle user) { startActivityAsUser(intent, null, user); } @Override public void startActivity(Intent intent, Bundle options) { warnIfCallingFromSystemProcess(); // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is // generally not allowed, except if the caller specifies the task id the activity should // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We // maintain this for backwards compatibility. final int targetSdkVersion = getApplicationInfo().targetSdkVersion; if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && (targetSdkVersion < Build.VERSION_CODES.N || targetSdkVersion >= Build.VERSION_CODES.P) && (options == null || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) { 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, (Activity) null, intent, -1, options); }
@hide
/** @hide */
@Override public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) { try { ActivityManager.getService().startActivityAsUser( mMainThread.getApplicationThread(), getBasePackageName(), intent, intent.resolveTypeIfNeeded(getContentResolver()), null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void startActivities(Intent[] intents) { warnIfCallingFromSystemProcess(); startActivities(intents, null); }
@hide
/** @hide */
@Override public int startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) { if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { throw new AndroidRuntimeException( "Calling startActivities() from outside of an Activity " + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent." + " Is this really what you want?"); } return mMainThread.getInstrumentation().execStartActivitiesAsUser( getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intents, options, userHandle.getIdentifier()); } @Override public void startActivities(Intent[] intents, Bundle options) { warnIfCallingFromSystemProcess(); if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { throw new AndroidRuntimeException( "Calling startActivities() from outside of an Activity " + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent." + " Is this really what you want?"); } mMainThread.getInstrumentation().execStartActivities( getOuterContext(), mMainThread.getApplicationThread(), null, (Activity) null, intents, options); } @Override public void startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) throws IntentSender.SendIntentException { startIntentSender(intent, fillInIntent, flagsMask, flagsValues, extraFlags, null); } @Override public void startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) throws IntentSender.SendIntentException { try { String resolvedType = null; if (fillInIntent != null) { fillInIntent.migrateExtraStreamToClipData(); fillInIntent.prepareToLeaveProcess(this); resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver()); } int result = ActivityManager.getService() .startActivityIntentSender(mMainThread.getApplicationThread(), intent != null ? intent.getTarget() : null, intent != null ? intent.getWhitelistToken() : null, fillInIntent, resolvedType, null, null, 0, flagsMask, flagsValues, options); if (result == ActivityManager.START_CANCELED) { throw new IntentSender.SendIntentException(); } Instrumentation.checkStartActivityResult(result, null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user, String[] receiverPermissions) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, options, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcast(Intent intent, String receiverPermission, int appOp) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendOrderedBroadcast(Intent intent, String receiverPermission) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, null, true, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcast(intent, receiverPermission, AppOpsManager.OP_NONE, resultReceiver, scheduler, initialCode, initialData, initialExtras, null); } @Override public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcast(intent, receiverPermission, AppOpsManager.OP_NONE, resultReceiver, scheduler, initialCode, initialData, initialExtras, options); } @Override public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver, scheduler, initialCode, initialData, initialExtras, null); } void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras, Bundle options) { warnIfCallingFromSystemProcess(); IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, appOp, options, true, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent(mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) { sendBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE); } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, Bundle options) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE, options, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE, null, resultReceiver, scheduler, initialCode, initialData, initialExtras); } @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, null, resultReceiver, scheduler, initialCode, initialData, initialExtras); } @Override public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher(resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); String[] receiverPermissions = receiverPermission == null ? null : new String[] {receiverPermission}; try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, receiverPermissions, appOp, options, true, false, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void sendStickyBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { warnIfCallingFromSystemProcess(); IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, AppOpsManager.OP_NONE, null, true, true, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void removeStickyBroadcast(Intent intent) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); if (resolvedType != null) { intent = new Intent(intent); intent.setDataAndType(intent.getData(), resolvedType); } try { intent.prepareToLeaveProcess(this); ActivityManager.getService().unbroadcastIntent( mMainThread.getApplicationThread(), intent, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options, false, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { IIntentReceiver rd = null; if (resultReceiver != null) { if (mPackageInfo != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, mMainThread.getInstrumentation(), false); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver(); } } String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); ActivityManager.getService().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, rd, initialCode, initialData, initialExtras, null, AppOpsManager.OP_NONE, null, true, true, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override @Deprecated public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) { String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); if (resolvedType != null) { intent = new Intent(intent); intent.setDataAndType(intent.getData(), resolvedType); } try { intent.prepareToLeaveProcess(this); ActivityManager.getService().unbroadcastIntent( mMainThread.getApplicationThread(), intent, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { return registerReceiver(receiver, filter, null, null); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) { return registerReceiver(receiver, filter, null, null, flags); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext(), 0); } @Override public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) { return registerReceiverInternal(receiver, getUserId(), filter, broadcastPermission, scheduler, getOuterContext(), flags); } @Override public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, IntentFilter filter, String broadcastPermission, Handler scheduler) { return registerReceiverInternal(receiver, user.getIdentifier(), filter, broadcastPermission, scheduler, getOuterContext(), 0); } private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context, int flags) { IIntentReceiver rd = null; if (receiver != null) { if (mPackageInfo != null && context != null) { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } else { if (scheduler == null) { scheduler = mMainThread.getHandler(); } rd = new LoadedApk.ReceiverDispatcher( receiver, context, scheduler, null, true).getIIntentReceiver(); } } try { final Intent intent = ActivityManager.getService().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId, flags); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void unregisterReceiver(BroadcastReceiver receiver) { if (mPackageInfo != null) { IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher( getOuterContext(), receiver); try { ActivityManager.getService().unregisterReceiver(rd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } } private void validateServiceIntent(Intent service) { if (service.getComponent() == null && service.getPackage() == null) { if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { IllegalArgumentException ex = new IllegalArgumentException( "Service Intent must be explicit: " + service); throw ex; } else { Log.w(TAG, "Implicit intents with startService are not safe: " + service + " " + Debug.getCallers(2, 3)); } } } @Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } @Override public ComponentName startForegroundService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, true, mUser); } @Override public boolean stopService(Intent service) { warnIfCallingFromSystemProcess(); return stopServiceCommon(service, mUser); } @Override public ComponentName startServiceAsUser(Intent service, UserHandle user) { return startServiceCommon(service, false, user); } @Override public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) { return startServiceCommon(service, true, user); } private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public boolean stopServiceAsUser(Intent service, UserHandle user) { return stopServiceCommon(service, user); } private boolean stopServiceCommon(Intent service, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); int res = ActivityManager.getService().stopService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to stop service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser()); }
@hide
/** @hide */
@Override public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags, UserHandle user) { return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user); }
@hide
/** @hide */
@Override public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { if (handler == null) { throw new IllegalArgumentException("handler must not be null."); } return bindServiceCommon(service, conn, flags, handler, user); }
@hide
/** @hide */
@Override public IServiceConnection getServiceDispatcher(ServiceConnection conn, Handler handler, int flags) { return mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); }
@hide
/** @hide */
@Override public IApplicationThread getIApplicationThread() { return mMainThread.getApplicationThread(); }
@hide
/** @hide */
@Override public Handler getMainThreadHandler() { return mMainThread.getHandler(); } private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser. IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } else { throw new RuntimeException("Not supported in system context"); } validateServiceIntent(service); try { IBinder token = getActivityToken(); if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null && mPackageInfo.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } service.prepareToLeaveProcess(this); int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void unbindService(ServiceConnection conn) { if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( getOuterContext(), conn); try { ActivityManager.getService().unbindService(sd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } } @Override public boolean startInstrumentation(ComponentName className, String profileFile, Bundle arguments) { try { if (arguments != null) { arguments.setAllowFds(false); } return ActivityManager.getService().startInstrumentation( className, profileFile, 0, arguments, null, null, getUserId(), null /* ABI override */); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); } @Override public String getSystemServiceName(Class<?> serviceClass) { return SystemServiceRegistry.getSystemServiceName(serviceClass); } @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } final IActivityManager am = ActivityManager.getService(); if (am == null) { // Well this is super awkward; we somehow don't have an active // ActivityManager instance. If we're testing a root or system // UID, then they totally have whatever permission this is. final int appId = UserHandle.getAppId(uid); if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission); return PackageManager.PERMISSION_GRANTED; } Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold " + permission); return PackageManager.PERMISSION_DENIED; } try { return am.checkPermission(permission, pid, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
@hide
/** @hide */
@Override public int checkPermission(String permission, int pid, int uid, IBinder callerToken) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } try { return ActivityManager.getService().checkPermissionWithToken( permission, pid, uid, callerToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public int checkCallingPermission(String permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } int pid = Binder.getCallingPid(); if (pid != Process.myPid()) { return checkPermission(permission, pid, Binder.getCallingUid()); } return PackageManager.PERMISSION_DENIED; } @Override public int checkCallingOrSelfPermission(String permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } return checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid()); } @Override public int checkSelfPermission(String permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } return checkPermission(permission, Process.myPid(), Process.myUid()); } 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 " : "uid " + uid + " does not have ") + permission + "."); } } @Override public void enforcePermission( String permission, int pid, int uid, String message) { enforce(permission, checkPermission(permission, pid, uid), false, uid, message); } @Override public void enforceCallingPermission(String permission, String message) { enforce(permission, checkCallingPermission(permission), false, Binder.getCallingUid(), message); } @Override public void enforceCallingOrSelfPermission( String permission, String message) { enforce(permission, checkCallingOrSelfPermission(permission), true, Binder.getCallingUid(), message); } @Override public void grantUriPermission(String toPackage, Uri uri, int modeFlags) { try { ActivityManager.getService().grantUriPermission( mMainThread.getApplicationThread(), toPackage, ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void revokeUriPermission(Uri uri, int modeFlags) { try { ActivityManager.getService().revokeUriPermission( mMainThread.getApplicationThread(), null, ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public void revokeUriPermission(String targetPackage, Uri uri, int modeFlags) { try { ActivityManager.getService().revokeUriPermission( mMainThread.getApplicationThread(), targetPackage, ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { try { return ActivityManager.getService().checkUriPermission( ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags, resolveUserId(uri), null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
@hide
/** @hide */
@Override public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) { try { return ActivityManager.getService().checkUriPermission( ContentProvider.getUriWithoutUserId(uri), pid, uid, modeFlags, resolveUserId(uri), callerToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private int resolveUserId(Uri uri) { return ContentProvider.getUserIdFromUri(uri, getUserId()); } @Override public int checkCallingUriPermission(Uri uri, int modeFlags) { int pid = Binder.getCallingPid(); if (pid != Process.myPid()) { return checkUriPermission(uri, pid, Binder.getCallingUid(), modeFlags); } return PackageManager.PERMISSION_DENIED; } @Override public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { return checkUriPermission(uri, Binder.getCallingPid(), Binder.getCallingUid(), modeFlags); } @Override public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags) { if (DEBUG) { Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission=" + readPermission + " writePermission=" + writePermission + " pid=" + pid + " uid=" + uid + " mode" + modeFlags); } if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { if (readPermission == null || checkPermission(readPermission, pid, uid) == PackageManager.PERMISSION_GRANTED) { return PackageManager.PERMISSION_GRANTED; } } if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { if (writePermission == null || checkPermission(writePermission, pid, uid) == PackageManager.PERMISSION_GRANTED) { return PackageManager.PERMISSION_GRANTED; } } return uri != null ? checkUriPermission(uri, pid, uid, modeFlags) : PackageManager.PERMISSION_DENIED; } private String uriModeFlagToString(int uriModeFlags) { StringBuilder builder = new StringBuilder(); if ((uriModeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) { builder.append("read and "); } if ((uriModeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) { builder.append("write and "); } if ((uriModeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) { builder.append("persistable and "); } if ((uriModeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) { builder.append("prefix and "); } if (builder.length() > 5) { builder.setLength(builder.length() - 5); return builder.toString(); } else { 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 void enforceUriPermission( Uri uri, int pid, int uid, int modeFlags, String message) { enforceForUri( modeFlags, checkUriPermission(uri, pid, uid, modeFlags), false, uid, uri, message); } @Override public void enforceCallingUriPermission( Uri uri, int modeFlags, String message) { enforceForUri( modeFlags, checkCallingUriPermission(uri, modeFlags), false, Binder.getCallingUid(), uri, message); } @Override public void enforceCallingOrSelfUriPermission( Uri uri, int modeFlags, String message) { enforceForUri( modeFlags, checkCallingOrSelfUriPermission(uri, modeFlags), true, Binder.getCallingUid(), uri, message); } @Override public void enforceUriPermission( Uri uri, String readPermission, String writePermission, int pid, int uid, int modeFlags, String message) { enforceForUri(modeFlags, checkUriPermission( uri, readPermission, writePermission, pid, uid, modeFlags), false, uid, uri, message); }
Logs a warning if the system process directly called a method such as startService(Intent) instead of startServiceAsUser(Intent, UserHandle). The "AsUser" variants allow us to properly enforce the user's restrictions.
/** * Logs a warning if the system process directly called a method such as * {@link #startService(Intent)} instead of {@link #startServiceAsUser(Intent, UserHandle)}. * The "AsUser" variants allow us to properly enforce the user's restrictions. */
private void warnIfCallingFromSystemProcess() { if (Process.myUid() == Process.SYSTEM_UID) { Slog.w(TAG, "Calling a method in the system process without a qualified user: " + Debug.getCallers(5)); } } private static Resources createResources(IBinder activityToken, LoadedApk pi, String splitName, int displayId, Configuration overrideConfig, CompatibilityInfo compatInfo) { final String[] splitResDirs; final ClassLoader classLoader; try { splitResDirs = pi.getSplitPaths(splitName); classLoader = pi.getSplitClassLoader(splitName); } catch (NameNotFoundException e) { throw new RuntimeException(e); } return ResourcesManager.getInstance().getResources(activityToken, pi.getResDir(), splitResDirs, pi.getOverlayDirs(), pi.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfig, compatInfo, classLoader); } @Override public Context createApplicationContext(ApplicationInfo application, int flags) throws NameNotFoundException { LoadedApk pi = mMainThread.getPackageInfo(application, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, new UserHandle(UserHandle.getUserId(application.uid)), flags, null); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; c.setResources(createResources(mActivityToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; } } throw new PackageManager.NameNotFoundException( "Application package " + application.packageName + " not found"); } @Override public Context createPackageContext(String packageName, int flags) throws NameNotFoundException { return createPackageContextAsUser(packageName, flags, mUser); } @Override public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) throws NameNotFoundException { if (packageName.equals("system") || packageName.equals("android")) { // The system resources are loaded in every application, so we can safely copy // the context without reloading Resources. return new ContextImpl(this, mMainThread, mPackageInfo, null, mActivityToken, user, flags, null); } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, null, mActivityToken, user, flags, null); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; c.setResources(createResources(mActivityToken, pi, null, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); if (c.mResources != null) { return c; } } // Should be a better exception. throw new PackageManager.NameNotFoundException( "Application package " + packageName + " not found"); } @Override public Context createContextForSplit(String splitName) throws NameNotFoundException { if (!mPackageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { // All Splits are always loaded. return this; } final ClassLoader classLoader = mPackageInfo.getSplitClassLoader(splitName); final String[] paths = mPackageInfo.getSplitPaths(splitName); final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, splitName, mActivityToken, mUser, mFlags, classLoader); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; context.setResources(ResourcesManager.getInstance().getResources( mActivityToken, mPackageInfo.getResDir(), paths, mPackageInfo.getOverlayDirs(), mPackageInfo.getApplicationInfo().sharedLibraryFiles, displayId, null, mPackageInfo.getCompatibilityInfo(), classLoader)); return context; } @Override public Context createConfigurationContext(Configuration overrideConfiguration) { if (overrideConfiguration == null) { throw new IllegalArgumentException("overrideConfiguration must not be null"); } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, mFlags, mClassLoader); final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY; context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo())); return context; } @Override public Context createDisplayContext(Display display) { if (display == null) { throw new IllegalArgumentException("display must not be null"); } ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, mFlags, mClassLoader); final int displayId = display.getDisplayId(); context.setResources(createResources(mActivityToken, mPackageInfo, mSplitName, displayId, null, getDisplayAdjustments(displayId).getCompatibilityInfo())); context.mDisplay = display; return context; } @Override public Context createDeviceProtectedStorageContext() { final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) | Context.CONTEXT_DEVICE_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, flags, mClassLoader); } @Override public Context createCredentialProtectedStorageContext() { final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE) | Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; return new ContextImpl(this, mMainThread, mPackageInfo, mSplitName, mActivityToken, mUser, flags, mClassLoader); } @Override public boolean isRestricted() { return (mFlags & Context.CONTEXT_RESTRICTED) != 0; } @Override public boolean isDeviceProtectedStorage() { return (mFlags & Context.CONTEXT_DEVICE_PROTECTED_STORAGE) != 0; } @Override public boolean isCredentialProtectedStorage() { return (mFlags & Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE) != 0; } @Override public boolean canLoadUnsafeResources() { if (getPackageName().equals(getOpPackageName())) { return true; } return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0; } @Override public Display getDisplay() { if (mDisplay == null) { return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY, mResources); } return mDisplay; } @Override public void updateDisplay(int displayId) { mDisplay = mResourcesManager.getAdjustedDisplay(displayId, mResources); } @Override public DisplayAdjustments getDisplayAdjustments(int displayId) { return mResources.getDisplayAdjustments(); } @Override public File getDataDir() { if (mPackageInfo != null) { File res = null; if (isCredentialProtectedStorage()) { res = mPackageInfo.getCredentialProtectedDataDirFile(); } else if (isDeviceProtectedStorage()) { res = mPackageInfo.getDeviceProtectedDataDirFile(); } else { res = mPackageInfo.getDataDirFile(); } if (res != null) { if (!res.exists() && android.os.Process.myUid() == android.os.Process.SYSTEM_UID) { Log.wtf(TAG, "Data directory doesn't exist for package " + getPackageName(), new Throwable()); } return res; } else { throw new RuntimeException( "No data directory found for package " + getPackageName()); } } else { throw new RuntimeException( "No package details found for package " + getPackageName()); } } @Override public File getDir(String name, int mode) { checkMode(mode); name = "app_" + name; File file = makeFilename(getDataDir(), name); if (!file.exists()) { file.mkdir(); setFilePermissionsFromMode(file.getPath(), mode, FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH); } return file; }
{@hide}
/** {@hide} */
@Override public UserHandle getUser() { return mUser; }
{@hide}
/** {@hide} */
@Override public int getUserId() { return mUser.getIdentifier(); }
@hide
/** @hide */
@Override public AutofillClient getAutofillClient() { return mAutofillClient; }
@hide
/** @hide */
@Override public void setAutofillClient(AutofillClient client) { mAutofillClient = client; }
@hide
/** @hide */
@Override public boolean isAutofillCompatibilityEnabled() { return mIsAutofillCompatEnabled; }
@hide
/** @hide */
@TestApi @Override public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) { mIsAutofillCompatEnabled = autofillCompatEnabled; } static ContextImpl createSystemContext(ActivityThread mainThread) { LoadedApk packageInfo = new LoadedApk(mainThread); ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, null); context.setResources(packageInfo.getResources()); context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(), context.mResourcesManager.getDisplayMetrics()); return context; }
System Context to be used for UI. This Context has resources that can be themed. Make sure that the created system UI context shares the same LoadedApk as the system context.
/** * System Context to be used for UI. This Context has resources that can be themed. * Make sure that the created system UI context shares the same LoadedApk as the system context. */
static ContextImpl createSystemUiContext(ContextImpl systemContext) { final LoadedApk packageInfo = systemContext.mPackageInfo; ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo, null, null, null, 0, null); context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null, packageInfo.getCompatibilityInfo())); return context; } static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0, null); context.setResources(packageInfo.getResources()); return context; } static ContextImpl createActivityContext(ActivityThread mainThread, LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId, Configuration overrideConfiguration) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); String[] splitDirs = packageInfo.getSplitResDirs(); ClassLoader classLoader = packageInfo.getClassLoader(); if (packageInfo.getApplicationInfo().requestsIsolatedSplitLoading()) { Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "SplitDependencies"); try { classLoader = packageInfo.getSplitClassLoader(activityInfo.splitName); splitDirs = packageInfo.getSplitPaths(activityInfo.splitName); } catch (NameNotFoundException e) { // Nothing above us can handle a NameNotFoundException, better crash. throw new RuntimeException(e); } finally { Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } } ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName, activityToken, null, 0, classLoader); // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY. displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY; final CompatibilityInfo compatInfo = (displayId == Display.DEFAULT_DISPLAY) ? packageInfo.getCompatibilityInfo() : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; final ResourcesManager resourcesManager = ResourcesManager.getInstance(); // Create the base resources for which all configuration contexts for this Activity // will be rebased upon. context.setResources(resourcesManager.createBaseActivityResources(activityToken, packageInfo.getResDir(), splitDirs, packageInfo.getOverlayDirs(), packageInfo.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfiguration, compatInfo, classLoader)); context.mDisplay = resourcesManager.getAdjustedDisplay(displayId, context.getResources()); return context; } private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread, @NonNull LoadedApk packageInfo, @Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user, int flags, @Nullable ClassLoader classLoader) { mOuterContext = this; // If creator didn't specify which storage to use, use the default // location for application. if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) { final File dataDir = packageInfo.getDataDirFile(); if (Objects.equals(dataDir, packageInfo.getCredentialProtectedDataDirFile())) { flags |= Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE; } else if (Objects.equals(dataDir, packageInfo.getDeviceProtectedDataDirFile())) { flags |= Context.CONTEXT_DEVICE_PROTECTED_STORAGE; } } mMainThread = mainThread; mActivityToken = activityToken; mFlags = flags; if (user == null) { user = Process.myUserHandle(); } mUser = user; mPackageInfo = packageInfo; mSplitName = splitName; mClassLoader = classLoader; mResourcesManager = ResourcesManager.getInstance(); if (container != null) { mBasePackageName = container.mBasePackageName; mOpPackageName = container.mOpPackageName; setResources(container.mResources); mDisplay = container.mDisplay; } else { mBasePackageName = packageInfo.mPackageName; ApplicationInfo ainfo = packageInfo.getApplicationInfo(); if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) { // Special case: system components allow themselves to be loaded in to other // processes. For purposes of app ops, we must then consider the context as // belonging to the package of this process, not the system itself, otherwise // the package+uid verifications in app ops will fail. mOpPackageName = ActivityThread.currentPackageName(); } else { mOpPackageName = mBasePackageName; } } mContentResolver = new ApplicationContentResolver(this, mainThread); } void setResources(Resources r) { if (r instanceof CompatResources) { ((CompatResources) r).setContext(this); } mResources = r; } void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) { mPackageInfo.installSystemApplicationInfo(info, classLoader); } final void scheduleFinalCleanup(String who, String what) { mMainThread.scheduleContextCleanup(this, who, what); } final void performFinalCleanup(String who, String what) { //Log.i(TAG, "Cleanup up context: " + this); mPackageInfo.removeContextRegistrations(getOuterContext(), who, what); } final Context getReceiverRestrictedContext() { if (mReceiverRestrictedContext != null) { return mReceiverRestrictedContext; } return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext()); } final void setOuterContext(Context context) { mOuterContext = context; } final Context getOuterContext() { return mOuterContext; } @Override public IBinder getActivityToken() { return mActivityToken; } private void checkMode(int mode) { if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.N) { if ((mode & MODE_WORLD_READABLE) != 0) { throw new SecurityException("MODE_WORLD_READABLE no longer supported"); } if ((mode & MODE_WORLD_WRITEABLE) != 0) { throw new SecurityException("MODE_WORLD_WRITEABLE no longer supported"); } } } @SuppressWarnings("deprecation") 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"); }
Ensure that given directories exist, trying to create them if missing. If unable to create, they are filtered by replacing with null.
/** * Ensure that given directories exist, trying to create them if missing. If * unable to create, they are filtered by replacing with {@code null}. */
private File[] ensureExternalDirsExistOrFilter(File[] dirs) { final StorageManager sm = getSystemService(StorageManager.class); final File[] result = new File[dirs.length]; for (int i = 0; i < dirs.length; i++) { File dir = dirs[i]; if (!dir.exists()) { if (!dir.mkdirs()) { // recheck existence in case of cross-process race if (!dir.exists()) { // Failing to mkdir() may be okay, since we might not have // enough permissions; ask vold to create on our behalf. try { sm.mkdirs(dir); } catch (Exception e) { Log.w(TAG, "Failed to ensure " + dir + ": " + e); dir = null; } } } } result[i] = dir; } return result; } // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- private static final class ApplicationContentResolver extends ContentResolver { private final ActivityThread mMainThread; public ApplicationContentResolver(Context context, ActivityThread mainThread) { super(context); mMainThread = Preconditions.checkNotNull(mainThread); } @Override protected IContentProvider acquireProvider(Context context, String auth) { return mMainThread.acquireProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); } @Override protected IContentProvider acquireExistingProvider(Context context, String auth) { return mMainThread.acquireExistingProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); } @Override public boolean releaseProvider(IContentProvider provider) { return mMainThread.releaseProvider(provider, true); } @Override protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), false); } @Override public boolean releaseUnstableProvider(IContentProvider icp) { return mMainThread.releaseProvider(icp, false); } @Override public void unstableProviderDied(IContentProvider icp) { mMainThread.handleUnstableProviderDied(icp.asBinder(), true); } @Override public void appNotRespondingViaProvider(IContentProvider icp) { mMainThread.appNotRespondingViaProvider(icp.asBinder()); }
@hide
/** @hide */
protected int resolveUserIdFromAuthority(String auth) { return ContentProvider.getUserIdFromAuthority(auth, getUserId()); } } }