1 package org.robolectric; 2 3 import static android.os.Build.VERSION_CODES.LOLLIPOP; 4 5 import android.app.Application; 6 import android.content.Context; 7 import android.content.res.Configuration; 8 import android.content.res.Resources; 9 import android.util.DisplayMetrics; 10 import org.robolectric.android.Bootstrap; 11 import org.robolectric.android.ConfigurationV25; 12 import org.robolectric.res.ResourceTable; 13 import org.robolectric.util.Scheduler; 14 import org.robolectric.util.TempDirectory; 15 16 public class RuntimeEnvironment { 17 public static Context systemContext; 18 public static Application application; 19 20 private volatile static Thread mainThread = Thread.currentThread(); 21 private static Object activityThread; 22 private static int apiLevel; 23 private static Scheduler masterScheduler; 24 private static ResourceTable systemResourceTable; 25 private static ResourceTable appResourceTable; 26 private static ResourceTable compileTimeResourceTable; 27 private static TempDirectory tempDirectory = new TempDirectory("no-test-yet"); 28 29 /** 30 * Tests if the given thread is currently set as the main thread. 31 * 32 * @param thread the thread to test. 33 * @return <tt>true</tt> if the specified thread is the main thread, <tt>false</tt> otherwise. 34 * @see #isMainThread() 35 */ isMainThread(Thread thread)36 public static boolean isMainThread(Thread thread) { 37 return thread == mainThread; 38 } 39 40 /** 41 * Tests if the current thread is currently set as the main thread. 42 * 43 * @return <tt>true</tt> if the current thread is the main thread, <tt>false</tt> otherwise. 44 */ isMainThread()45 public static boolean isMainThread() { 46 return isMainThread(Thread.currentThread()); 47 } 48 49 /** 50 * Retrieves the main thread. The main thread is the thread to which the main looper is attached. 51 * Defaults to the thread that initialises the <tt>RuntimeEnvironment</tt> class. 52 * 53 * @return The main thread. 54 * @see #setMainThread(Thread) 55 * @see #isMainThread() 56 */ getMainThread()57 public static Thread getMainThread() { 58 return mainThread; 59 } 60 61 /** 62 * Sets the main thread. The main thread is the thread to which the main looper is attached. 63 * Defaults to the thread that initialises the <tt>RuntimeEnvironment</tt> class. 64 * 65 * @param newMainThread the new main thread. 66 * @see #setMainThread(Thread) 67 * @see #isMainThread() 68 */ setMainThread(Thread newMainThread)69 public static void setMainThread(Thread newMainThread) { 70 mainThread = newMainThread; 71 } 72 getActivityThread()73 public static Object getActivityThread() { 74 return activityThread; 75 } 76 setActivityThread(Object newActivityThread)77 public static void setActivityThread(Object newActivityThread) { 78 activityThread = newActivityThread; 79 } 80 81 /** 82 * Returns a qualifier string describing the current {@link Configuration} of the system resources. 83 * 84 * @return a qualifier string as described (https://developer.android.com/guide/topics/resources/providing-resources.html#QualifierRules)[here]. 85 */ getQualifiers()86 public static String getQualifiers() { 87 Resources systemResources = Resources.getSystem(); 88 return getQualifiers(systemResources.getConfiguration(), systemResources.getDisplayMetrics()); 89 } 90 91 /** 92 * Returns a qualifier string describing the given configuration and display metrics. 93 * 94 * @param configuration the configuration. 95 * @param displayMetrics the display metrics. 96 * @return a qualifier string as described (https://developer.android.com/guide/topics/resources/providing-resources.html#QualifierRules)[here]. 97 */ getQualifiers(Configuration configuration, DisplayMetrics displayMetrics)98 public static String getQualifiers(Configuration configuration, DisplayMetrics displayMetrics) { 99 return ConfigurationV25.resourceQualifierString(configuration, displayMetrics); 100 } 101 102 /** 103 * Overrides the current device configuration. 104 * 105 * If `newQualifiers` starts with a plus (`+`), the prior configuration is used as the base 106 * configuration, with the given changes applied additively. Otherwise, default values are used 107 * for unspecified properties, as described [here](http://robolectric.org/device-configuration/). 108 * 109 * @param newQualifiers the qualifiers to apply 110 */ setQualifiers(String newQualifiers)111 public static void setQualifiers(String newQualifiers) { 112 Configuration configuration; 113 DisplayMetrics displayMetrics = new DisplayMetrics(); 114 if (newQualifiers.startsWith("+")) { 115 configuration = new Configuration(Resources.getSystem().getConfiguration()); 116 displayMetrics.setTo(Resources.getSystem().getDisplayMetrics()); 117 } else { 118 configuration = new Configuration(); 119 } 120 Bootstrap.applyQualifiers(newQualifiers, getApiLevel(), configuration, displayMetrics); 121 122 Resources systemResources = Resources.getSystem(); 123 systemResources.updateConfiguration(configuration, displayMetrics); 124 125 if (application != null) { 126 application.getResources().updateConfiguration(configuration, displayMetrics); 127 } 128 } 129 getApiLevel()130 public static int getApiLevel() { 131 return apiLevel; 132 } 133 castNativePtr(long ptr)134 public static Number castNativePtr(long ptr) { 135 // Weird, using a ternary here doesn't work, there's some auto promotion of boxed types happening. 136 if (getApiLevel() >= LOLLIPOP) { 137 return ptr; 138 } else { 139 return (int) ptr; 140 } 141 } 142 143 /** 144 * Retrieves the current master scheduler. This scheduler is always used by the main 145 * {@link android.os.Looper Looper}, and if the global scheduler option is set it is also used for 146 * the background scheduler and for all other {@link android.os.Looper Looper}s 147 * @return The current master scheduler. 148 * @see #setMasterScheduler(Scheduler) 149 * see org.robolectric.Robolectric#getForegroundThreadScheduler() 150 * see org.robolectric.Robolectric#getBackgroundThreadScheduler() 151 */ getMasterScheduler()152 public static Scheduler getMasterScheduler() { 153 return masterScheduler; 154 } 155 156 /** 157 * Sets the current master scheduler. See {@link #getMasterScheduler()} for details. 158 * Note that this method is primarily intended to be called by the Robolectric core setup code. 159 * Changing the master scheduler during a test will have unpredictable results. 160 * @param masterScheduler the new master scheduler. 161 * @see #getMasterScheduler() 162 * see org.robolectric.Robolectric#getForegroundThreadScheduler() 163 * see org.robolectric.Robolectric#getBackgroundThreadScheduler() 164 */ setMasterScheduler(Scheduler masterScheduler)165 public static void setMasterScheduler(Scheduler masterScheduler) { 166 RuntimeEnvironment.masterScheduler = masterScheduler; 167 } 168 setSystemResourceTable(ResourceTable systemResourceTable)169 public static void setSystemResourceTable(ResourceTable systemResourceTable) { 170 RuntimeEnvironment.systemResourceTable = systemResourceTable; 171 } 172 setAppResourceTable(ResourceTable appResourceTable)173 public static void setAppResourceTable(ResourceTable appResourceTable) { 174 RuntimeEnvironment.appResourceTable = appResourceTable; 175 } 176 getSystemResourceTable()177 public static ResourceTable getSystemResourceTable() { 178 return systemResourceTable; 179 } 180 getAppResourceTable()181 public static ResourceTable getAppResourceTable() { 182 return appResourceTable; 183 } 184 setCompileTimeResourceTable(ResourceTable compileTimeResourceTable)185 public static void setCompileTimeResourceTable(ResourceTable compileTimeResourceTable) { 186 RuntimeEnvironment.compileTimeResourceTable = compileTimeResourceTable; 187 } 188 getCompileTimeResourceTable()189 public static ResourceTable getCompileTimeResourceTable() { 190 return compileTimeResourceTable; 191 } 192 setTempDirectory(TempDirectory tempDirectory)193 public static void setTempDirectory(TempDirectory tempDirectory) { 194 RuntimeEnvironment.tempDirectory = tempDirectory; 195 } 196 getTempDirectory()197 public static TempDirectory getTempDirectory() { 198 return tempDirectory; 199 } 200 } 201