1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.internal.ravenwood; 17 18 import android.ravenwood.annotation.RavenwoodNativeSubstitutionClass; 19 20 /** 21 * Class to interact with the Ravenwood environment. 22 */ 23 @android.ravenwood.annotation.RavenwoodKeepWholeClass 24 @RavenwoodNativeSubstitutionClass( 25 "com.android.platform.test.ravenwood.nativesubstitution.RavenwoodEnvironment_host") 26 public final class RavenwoodEnvironment { 27 public static final String TAG = "RavenwoodEnvironment"; 28 29 private static RavenwoodEnvironment sInstance = new RavenwoodEnvironment(); 30 private static Workaround sWorkaround = new Workaround(); 31 RavenwoodEnvironment()32 private RavenwoodEnvironment() { 33 if (isRunningOnRavenwood()) { 34 ensureRavenwoodInitializedInternal(); 35 } 36 } 37 38 /** 39 * @return the singleton instance. 40 */ getInstance()41 public static RavenwoodEnvironment getInstance() { 42 return sInstance; 43 } 44 45 /** 46 * Initialize the ravenwood environment if it hasn't happened already, if running on Ravenwood. 47 * 48 * No-op if called on the device side. 49 */ ensureRavenwoodInitialized()50 public static void ensureRavenwoodInitialized() { 51 } 52 ensureRavenwoodInitialized$ravenwood()53 private static void ensureRavenwoodInitialized$ravenwood() { 54 getInstance(); // This is enough to initialize the environment. 55 } 56 57 /** Initialize the ravenwood environment */ ensureRavenwoodInitializedInternal()58 private static native void ensureRavenwoodInitializedInternal(); 59 60 /** 61 * USE IT SPARINGLY! Returns true if it's running on Ravenwood, hostside test environment. 62 * 63 * <p>Using this allows code to behave differently on a real device and on Ravenwood, but 64 * generally speaking, that's a bad idea because we want the test target code to behave 65 * differently. 66 * 67 * <p>This should be only used when different behavior is absolutely needed. 68 * 69 * <p>If someone needs it without having access to the SDK, the following hack would work too. 70 * <code>System.getProperty("java.class.path").contains("ravenwood")</code> 71 */ 72 @android.ravenwood.annotation.RavenwoodReplace isRunningOnRavenwood()73 public boolean isRunningOnRavenwood() { 74 return false; 75 } 76 isRunningOnRavenwood$ravenwood()77 private boolean isRunningOnRavenwood$ravenwood() { 78 return true; 79 } 80 81 /** 82 * See {@link Workaround}. It's only usablke on Ravenwood. 83 */ workaround()84 public static Workaround workaround() { 85 if (getInstance().isRunningOnRavenwood()) { 86 return sWorkaround; 87 } 88 throw new IllegalStateException("Workaround can only be used on Ravenwood"); 89 } 90 91 /** 92 * A set of APIs used to work around missing features on Ravenwood. Ideally, this class should 93 * be empty, and all its APIs should be able to be implemented properly. 94 */ 95 public static class Workaround { Workaround()96 Workaround() { 97 } 98 99 /** 100 * @return whether the app's target SDK level is at least Q. 101 */ isTargetSdkAtLeastQ()102 public boolean isTargetSdkAtLeastQ() { 103 return true; 104 } 105 } 106 } 107