Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b19041a authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support Environment APIs" into main

parents f341d1ba fbbfb0c2
Loading
Loading
Loading
Loading
+123 −51
Original line number Diff line number Diff line
@@ -36,6 +36,10 @@ import android.content.pm.PackageManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
import android.ravenwood.annotation.RavenwoodKeepWholeClass;
import android.ravenwood.annotation.RavenwoodRedirect;
import android.ravenwood.annotation.RavenwoodRedirectionClass;
import android.ravenwood.annotation.RavenwoodThrow;
import android.text.TextUtils;
import android.util.Log;

@@ -51,6 +55,8 @@ import java.util.UUID;
/**
 * Provides access to environment variables.
 */
@RavenwoodKeepWholeClass
@RavenwoodRedirectionClass("Environment_ravenwood")
public class Environment {
    private static final String TAG = "Environment";

@@ -99,11 +105,11 @@ public class Environment {

    private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
    private static final String DIR_ANDROID_DATA_PATH = getDirectoryPath(ENV_ANDROID_DATA, "/data");
    private static final File DIR_ANDROID_DATA = new File(DIR_ANDROID_DATA_PATH);
    private static final File DIR_ANDROID_DATA = newFilePrep(DIR_ANDROID_DATA_PATH);
    private static final File DIR_ANDROID_EXPAND = getDirectory(ENV_ANDROID_EXPAND, "/mnt/expand");
    private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
    private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
    private static final File DIR_METADATA = new File("/metadata");
    private static final File DIR_METADATA = newFilePrep("/metadata");
    private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
    private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
    private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
@@ -162,6 +168,51 @@ public class Environment {
    private static Boolean sLegacyStorageAppOp;
    private static Boolean sNoIsolatedStorageAppOp;

    /**
     * On a real device, it's a no-op, but on ravenwood, it'll remap the path such that
     * it'll work on the Ravenwood environment, and also create the directory.
     *
     * We use it on Ravenwood because Ravenwood has no "installd" or anything that'd create the
     * directories for us. OTOH, we can't just create the directories on the device side
     * because we need to set the correct owners/permissions on them, which we can't do here.
     */
    @RavenwoodRedirect
    private static File prep(File dir) {
        return dir;
    }

    /** Same as {@link #prep(File)} */
    @RavenwoodRedirect
    private static String prep(String dir) {
        return dir;
    }

    /**
     * Same as prep(new File(...)).
     * Must only be used when the path is known to be a directory, not file.
     */
    private static File newFilePrep(String path) {
        return prep(new File(path));
    }

    /** See {@link #newFilePrep(String)} */
    private static File newFilePrep(String path, String subdir) {
        return prep(new File(path, subdir));
    }

    /** See {@link #newFilePrep(String)} */
    private static File newFilePrep(File path, String subdir) {
        return prep(new File(path, subdir));
    }

    /**
     * On a real device, it's just {@link System#getenv()}, but on Ravenwood, we use a java prop.
     */
    @RavenwoodRedirect(comment = "Use java props on Ravenwood")
    private static String getEnvPath(String variableName) {
        return System.getenv(variableName);
    }

    static {
        initForCurrentUser();
    }
@@ -346,7 +397,7 @@ public class Environment {
     */
    @Deprecated
    public static File getUserSystemDirectory(int userId) {
        return new File(new File(getDataSystemDirectory(), "users"), Integer.toString(userId));
        return newFilePrep(new File(getDataSystemDirectory(), "users"), Integer.toString(userId));
    }

    /**
@@ -363,7 +414,7 @@ public class Environment {
     */
    @Deprecated
    public static File getUserConfigDirectory(int userId) {
        return new File(new File(new File(
        return newFilePrep(new File(new File(
                getDataDirectory(), "misc"), "user"), Integer.toString(userId));
    }

@@ -387,7 +438,7 @@ public class Environment {
        if (TextUtils.isEmpty(volumeUuid)) {
            return DIR_ANDROID_DATA;
        } else {
            return new File("/mnt/expand/" + volumeUuid);
            return newFilePrep("/mnt/expand/" + volumeUuid);
        }
    }

@@ -396,7 +447,7 @@ public class Environment {
        if (TextUtils.isEmpty(volumeUuid)) {
            return DIR_ANDROID_DATA_PATH;
        } else {
            return getExpandDirectory().getAbsolutePath() + File.separator + volumeUuid;
            return prep(getExpandDirectory().getAbsolutePath() + File.separator + volumeUuid);
        }
    }

@@ -408,7 +459,7 @@ public class Environment {
    /** {@hide} */
    @UnsupportedAppUsage
    public static File getDataSystemDirectory() {
        return new File(getDataDirectory(), "system");
        return newFilePrep(getDataDirectory(), "system");
    }

    /**
@@ -418,7 +469,7 @@ public class Environment {
    @SystemApi
    @FlaggedApi(android.crashrecovery.flags.Flags.FLAG_ENABLE_CRASHRECOVERY)
    public static @NonNull File getDataSystemDeviceProtectedDirectory() {
        return buildPath(getDataDirectory(), "system_de");
        return buildPathPrep(getDataDirectory(), "system_de");
    }

    /** Use {@link #getDataSystemDeviceProtectedDirectory()} instead.
@@ -426,7 +477,7 @@ public class Environment {
     */
    @Deprecated
    public static @NonNull File getDataSystemDeDirectory() {
        return buildPath(getDataDirectory(), "system_de");
        return buildPathPrep(getDataDirectory(), "system_de");
    }

    /**
@@ -434,7 +485,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataSystemCeDirectory() {
        return buildPath(getDataDirectory(), "system_ce");
        return buildPathPrep(getDataDirectory(), "system_ce");
    }

    /**
@@ -454,7 +505,7 @@ public class Environment {
     * @hide
     */
    public static File getDataSystemCeDirectory(int userId) {
        return buildPath(getDataDirectory(), "system_ce", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "system_ce", String.valueOf(userId));
    }

    /**
@@ -474,95 +525,95 @@ public class Environment {
     * @hide
     */
    public static File getDataSystemDeDirectory(int userId) {
        return buildPath(getDataDirectory(), "system_de", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "system_de", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataMiscDirectory() {
        return new File(getDataDirectory(), "misc");
        return newFilePrep(getDataDirectory(), "misc");
    }

    /** {@hide} */
    public static File getDataMiscCeDirectory() {
        return buildPath(getDataDirectory(), "misc_ce");
        return buildPathPrep(getDataDirectory(), "misc_ce");
    }

    /** {@hide} */
    public static File getDataMiscCeDirectory(int userId) {
        return buildPath(getDataDirectory(), "misc_ce", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "misc_ce", String.valueOf(userId));
    }

    /** {@hide} */
    private static File getDataMiscCeDirectory(String volumeUuid, int userId) {
        return buildPath(getDataDirectory(volumeUuid), "misc_ce", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(volumeUuid), "misc_ce", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataMiscCeSharedSdkSandboxDirectory(String volumeUuid, int userId,
            String packageName) {
        return buildPath(getDataMiscCeDirectory(volumeUuid, userId), "sdksandbox",
        return buildPathPrep(getDataMiscCeDirectory(volumeUuid, userId), "sdksandbox",
                packageName, "shared");
    }

    /** {@hide} */
    public static File getDataMiscDeDirectory(int userId) {
        return buildPath(getDataDirectory(), "misc_de", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "misc_de", String.valueOf(userId));
    }

    /** {@hide} */
    private static File getDataMiscDeDirectory(String volumeUuid, int userId) {
        return buildPath(getDataDirectory(volumeUuid), "misc_de", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(volumeUuid), "misc_de", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataMiscDeSharedSdkSandboxDirectory(String volumeUuid, int userId,
            String packageName) {
        return buildPath(getDataMiscDeDirectory(volumeUuid, userId), "sdksandbox",
        return buildPathPrep(getDataMiscDeDirectory(volumeUuid, userId), "sdksandbox",
                packageName, "shared");
    }

    private static File getDataProfilesDeDirectory(int userId) {
        return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataVendorCeDirectory(int userId) {
        return buildPath(getDataDirectory(), "vendor_ce", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "vendor_ce", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataVendorDeDirectory(int userId) {
        return buildPath(getDataDirectory(), "vendor_de", String.valueOf(userId));
        return buildPathPrep(getDataDirectory(), "vendor_de", String.valueOf(userId));
    }

    /** {@hide} */
    public static File getDataRefProfilesDePackageDirectory(String packageName) {
        return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName);
        return buildPathPrep(getDataDirectory(), "misc", "profiles", "ref", packageName);
    }

    /** {@hide} */
    public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
        return buildPath(getDataProfilesDeDirectory(userId), packageName);
        return buildPathPrep(getDataProfilesDeDirectory(userId), packageName);
    }

    /** {@hide} */
    public static File getDataAppDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), "app");
        return newFilePrep(getDataDirectory(volumeUuid), "app");
    }

    /** {@hide} */
    public static File getDataStagingDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), "app-staging");
        return newFilePrep(getDataDirectory(volumeUuid), "app-staging");
    }

    /** {@hide} */
    public static File getDataUserCeDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), DIR_USER_CE);
        return newFilePrep(getDataDirectory(volumeUuid), DIR_USER_CE);
    }

    /** {@hide} */
    public static File getDataUserCeDirectory(String volumeUuid, int userId) {
        return new File(getDataUserCeDirectory(volumeUuid), String.valueOf(userId));
        return newFilePrep(getDataUserCeDirectory(volumeUuid), String.valueOf(userId));
    }

    /** {@hide} */
@@ -570,7 +621,7 @@ public class Environment {
    public static File getDataUserCePackageDirectory(@Nullable String volumeUuid, int userId,
            @NonNull String packageName) {
        // TODO: keep consistent with installd
        return new File(getDataUserCeDirectory(volumeUuid, userId), packageName);
        return newFilePrep(getDataUserCeDirectory(volumeUuid, userId), packageName);
    }

    /**
@@ -599,12 +650,12 @@ public class Environment {

    /** {@hide} */
    public static File getDataUserDeDirectory(String volumeUuid) {
        return new File(getDataDirectory(volumeUuid), DIR_USER_DE);
        return newFilePrep(getDataDirectory(volumeUuid), DIR_USER_DE);
    }

    /** {@hide} */
    public static File getDataUserDeDirectory(String volumeUuid, int userId) {
        return new File(getDataUserDeDirectory(volumeUuid), String.valueOf(userId));
        return newFilePrep(getDataUserDeDirectory(volumeUuid), String.valueOf(userId));
    }

    /** {@hide} */
@@ -612,7 +663,7 @@ public class Environment {
    public static File getDataUserDePackageDirectory(@Nullable String volumeUuid, int userId,
            @NonNull String packageName) {
        // TODO: keep consistent with installd
        return new File(getDataUserDeDirectory(volumeUuid, userId), packageName);
        return newFilePrep(getDataUserDeDirectory(volumeUuid, userId), packageName);
    }

    /**
@@ -647,7 +698,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsDirectory() {
        return new File(getDataDirectory(), "preloads");
        return newFilePrep(getDataDirectory(), "preloads");
    }

    /**
@@ -655,7 +706,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsDemoDirectory() {
        return new File(getDataPreloadsDirectory(), "demo");
        return newFilePrep(getDataPreloadsDirectory(), "demo");
    }

    /**
@@ -663,7 +714,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsAppsDirectory() {
        return new File(getDataPreloadsDirectory(), "apps");
        return newFilePrep(getDataPreloadsDirectory(), "apps");
    }

    /**
@@ -671,7 +722,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsMediaDirectory() {
        return new File(getDataPreloadsDirectory(), "media");
        return newFilePrep(getDataPreloadsDirectory(), "media");
    }

    /**
@@ -680,7 +731,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsFileCacheDirectory(String packageName) {
        return new File(getDataPreloadsFileCacheDirectory(), packageName);
        return newFilePrep(getDataPreloadsFileCacheDirectory(), packageName);
    }

    /**
@@ -689,7 +740,7 @@ public class Environment {
     * {@hide}
     */
    public static File getDataPreloadsFileCacheDirectory() {
        return new File(getDataPreloadsDirectory(), "file_cache");
        return newFilePrep(getDataPreloadsDirectory(), "file_cache");
    }

    /**
@@ -697,7 +748,7 @@ public class Environment {
     * {@hide}
     */
    public static File getPackageCacheDirectory() {
        return new File(getDataSystemDirectory(), "package_cache");
        return newFilePrep(getDataSystemDirectory(), "package_cache");
    }

    /**
@@ -710,9 +761,9 @@ public class Environment {
    @SystemApi
    public static @NonNull Collection<File> getInternalMediaDirectories() {
        final ArrayList<File> res = new ArrayList<>();
        addCanonicalFile(res, new File(Environment.getRootDirectory(), "media"));
        addCanonicalFile(res, new File(Environment.getOemDirectory(), "media"));
        addCanonicalFile(res, new File(Environment.getProductDirectory(), "media"));
        addCanonicalFile(res, newFilePrep(Environment.getRootDirectory(), "media"));
        addCanonicalFile(res, newFilePrep(Environment.getOemDirectory(), "media"));
        addCanonicalFile(res, newFilePrep(Environment.getProductDirectory(), "media"));
        return res;
    }

@@ -789,6 +840,7 @@ public class Environment {
     * @see #getExternalStorageState()
     * @see #isExternalStorageRemovable()
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static File getExternalStorageDirectory() {
        throwIfUserRequired();
        return sCurrentUser.getExternalDirs()[0];
@@ -796,14 +848,16 @@ public class Environment {

    /** {@hide} */
    @UnsupportedAppUsage
    @RavenwoodThrow(reason = "not supporting env var based API for now")
    public static File getLegacyExternalStorageDirectory() {
        return new File(System.getenv(ENV_EXTERNAL_STORAGE));
        return newFilePrep(getEnvPath(ENV_EXTERNAL_STORAGE));
    }

    /** {@hide} */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    @RavenwoodThrow(reason = "not supporting env var based API for now")
    public static File getLegacyExternalStorageObbDirectory() {
        return buildPath(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
        return buildPathPrep(getLegacyExternalStorageDirectory(), DIR_ANDROID, DIR_OBB);
    }

    /**
@@ -1288,6 +1342,7 @@ public class Environment {
     *         {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
     *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static String getExternalStorageState() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return getExternalStorageState(externalDir);
@@ -1297,6 +1352,7 @@ public class Environment {
     * @deprecated use {@link #getExternalStorageState(File)}
     */
    @Deprecated
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static String getStorageState(File path) {
        return getExternalStorageState(path);
    }
@@ -1311,6 +1367,7 @@ public class Environment {
     *         {@link #MEDIA_MOUNTED_READ_ONLY}, {@link #MEDIA_SHARED},
     *         {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static String getExternalStorageState(File path) {
        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
        if (volume != null) {
@@ -1328,6 +1385,7 @@ public class Environment {
     *         or false if the storage device is built in and cannot be
     *         physically removed.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageRemovable() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return isExternalStorageRemovable(externalDir);
@@ -1343,6 +1401,7 @@ public class Environment {
     * @throws IllegalArgumentException if the path is not a valid storage
     *             device.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageRemovable(@NonNull File path) {
        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
        if (volume != null) {
@@ -1366,6 +1425,7 @@ public class Environment {
     * @see DevicePolicyManager#setStorageEncryption(android.content.ComponentName,
     *      boolean)
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageEmulated() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return isExternalStorageEmulated(externalDir);
@@ -1386,6 +1446,7 @@ public class Environment {
     * @throws IllegalArgumentException if the path is not a valid storage
     *             device.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageEmulated(@NonNull File path) {
        final StorageVolume volume = StorageManager.getStorageVolume(path, UserHandle.myUserId());
        if (volume != null) {
@@ -1407,6 +1468,7 @@ public class Environment {
     * Non-legacy apps can continue to discover and read media belonging to
     * other apps via {@link android.provider.MediaStore}.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageLegacy() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return isExternalStorageLegacy(externalDir);
@@ -1427,6 +1489,7 @@ public class Environment {
     * @throws IllegalArgumentException if the path is not a valid storage
     * device.
     */
    @RavenwoodThrow(blockedBy = StorageManager.class)
    public static boolean isExternalStorageLegacy(@NonNull File path) {
        final Context context = AppGlobals.getInitialApplication();
        final int uid = context.getApplicationInfo().uid;
@@ -1488,11 +1551,13 @@ public class Environment {
        return sNoIsolatedStorageAppOp;
    }

    @RavenwoodThrow(blockedBy = StorageManager.class)
    private static boolean isScopedStorageEnforced(boolean defaultScopedStorage,
            boolean forceEnableScopedStorage) {
        return defaultScopedStorage && forceEnableScopedStorage;
    }

    @RavenwoodThrow(blockedBy = StorageManager.class)
    private static boolean isScopedStorageDisabled(boolean defaultScopedStorage,
            boolean forceEnableScopedStorage) {
        return !defaultScopedStorage && !forceEnableScopedStorage;
@@ -1506,6 +1571,7 @@ public class Environment {
     * <p>To request access, use
     * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}.
     */
    @RavenwoodThrow(blockedBy = AppOpsManager.class)
    public static boolean isExternalStorageManager() {
        final File externalDir = sCurrentUser.getExternalDirs()[0];
        return isExternalStorageManager(externalDir);
@@ -1518,6 +1584,7 @@ public class Environment {
     * <p>To request access, use
     * {@link android.provider.Settings#ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION}.
     */
    @RavenwoodThrow(blockedBy = AppOpsManager.class)
    public static boolean isExternalStorageManager(@NonNull File path) {
        final Context context = Objects.requireNonNull(AppGlobals.getInitialApplication());
        String packageName = Objects.requireNonNull(context.getPackageName());
@@ -1542,15 +1609,15 @@ public class Environment {
        }
    }

    static File getDirectory(String variableName, String defaultPath) {
        String path = System.getenv(variableName);
        return path == null ? new File(defaultPath) : new File(path);
    private static File getDirectory(String variableName, String defaultPath) {
        return new File(getDirectoryPath(variableName, defaultPath));
    }

    @NonNull
    static String getDirectoryPath(@NonNull String variableName, @NonNull String defaultPath) {
        String path = System.getenv(variableName);
        return path == null ? defaultPath : path;
    private static String getDirectoryPath(
            @NonNull String variableName, @NonNull String defaultPath) {
        String path = getEnvPath(variableName);
        return prep(path == null ? defaultPath : path);
    }

    /** {@hide} */
@@ -1594,9 +1661,14 @@ public class Environment {
                cur = new File(cur, segment);
            }
        }
        // buildPath may be used for a filepath too, so we can't just always do mkdirs on it.
        return cur;
    }

    private static File buildPathPrep(File base, String... segments) {
        return prep(buildPath(base, segments));
    }

    /**
     * If the given path exists on emulated external storage, return the
     * translated backing path hosted on internal storage. This bypasses any
+84 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.os;

import android.util.Log;

import com.android.ravenwood.common.RavenwoodCommonUtils;

import java.io.File;
import java.util.Objects;

/**
 * Ravenwood redirect target class from {@link Environment}.
 */
public class Environment_ravenwood {
    private static final String TAG = "Environment_ravenwood";

    private static final boolean VERBOSE = RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;

    private Environment_ravenwood() {
    }

    private static volatile File sRootDir;

    /** Called by ravenwood to initialize it. */
    public static void init(File rootDir) {
        sRootDir = Objects.requireNonNull(rootDir);
    }

    /** Redirected from the corresponding {@link Environment} method. */
    static String getEnvPath(String variableName) {
        return System.getProperty("ravenwood.env." + variableName);
    }

    /** Redirected from the corresponding {@link Environment} method. */
    static File prep(File path) {
        prep(path.getAbsolutePath());
        return path;
    }

    /** Redirected from the corresponding {@link Environment} method. */
    static String prep(String path) {
        if (path != null) {
            path = translateAbsolutePathForRavenwood(path);
            if (VERBOSE) {
                Log.v(TAG, "mkdirs: " + path);
            }
            new File(path).mkdirs();
        }
        return path;
    }

    private static String translateAbsolutePathForRavenwood(String path) {
        if (!path.startsWith("/")) {
            throw new RuntimeException(
                    "Path doesn't start with a '/'. Actual=" + path);
        }
        var root = Objects.requireNonNull(sRootDir);
        if (path.startsWith(root.toString())) {
            if (VERBOSE) {
                Log.v(TAG, "translate: " + path + " is already translated");
            }
            return path;
        }
        var ret = new File(root, path).getAbsolutePath();
        if (VERBOSE) {
            Log.v(TAG, "translate: " + path + " -> " + ret);
        }
        return ret;
    }
}
+218 −7

File changed.

Preview size limit exceeded, changes collapsed.

+1 −2
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

@@ -89,7 +88,7 @@ public class RavenwoodContext extends RavenwoodBaseContext {
        mMainThread = mainThread;
        mResourcesSupplier = resourcesSupplier;

        mDataDir = Files.createTempDirectory(mPackageName).toFile();
        mDataDir = RavenwoodDriver.sAppDataDir;

        // Services provided by a typical shipping device
        registerService(ClipboardManager.class,
+10 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.os.Binder;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Environment_ravenwood;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Looper_ravenwood;
@@ -84,6 +85,7 @@ import org.junit.runner.Description;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
@@ -230,6 +232,9 @@ public class RavenwoodDriver {
    private static final long sCallingIdentity =
            packBinderIdentityToken(false, FIRST_APPLICATION_UID, sMyPid);

    static volatile File sRootDir;
    static volatile File sAppDataDir;

    /**
     * Initialize the global environment.
     */
@@ -349,6 +354,11 @@ public class RavenwoodDriver {

        assertMockitoVersion();

        sRootDir = Files.createTempDirectory("ravenwood-root-dir-").toFile();
        sAppDataDir = new File(sRootDir, "data/app/appdatadir/");
        sAppDataDir.mkdirs();
        Environment_ravenwood.init(sRootDir);

        Log.i(TAG, "TargetPackageName=" + sTargetPackageName);
        Log.i(TAG, "TestPackageName=" + sTestPackageName);
        Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel);
Loading