1 /* 2 * Copyright (C) 2016 Google Inc. 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 17 package com.android.cellbroadcastreceiver.unit; 18 19 import static org.mockito.Mockito.doReturn; 20 import static org.mockito.Mockito.spy; 21 22 import android.app.Activity; 23 import android.app.ResourcesManager; 24 import android.content.Context; 25 import android.content.ContextWrapper; 26 import android.content.Intent; 27 import android.content.SharedPreferences; 28 import android.content.pm.PackageManager; 29 import android.content.res.Configuration; 30 import android.content.res.Resources; 31 import android.os.Handler; 32 import android.test.ActivityUnitTestCase; 33 import android.util.Log; 34 import android.view.Display; 35 36 import java.util.HashMap; 37 import java.util.Locale; 38 import java.util.concurrent.CountDownLatch; 39 import java.util.concurrent.TimeUnit; 40 import java.util.function.BooleanSupplier; 41 42 public class CellBroadcastActivityTestCase<T extends Activity> extends ActivityUnitTestCase<T> { 43 44 protected TestContext mContext; 45 46 private T mActivity; 47 CellBroadcastActivityTestCase(Class<T> activityClass)48 CellBroadcastActivityTestCase(Class<T> activityClass) { 49 super(activityClass); 50 } 51 52 @Override setUp()53 protected void setUp() throws Exception { 54 super.setUp(); 55 mContext = new TestContext(getInstrumentation().getTargetContext()); 56 setActivityContext(mContext); 57 } 58 59 @Override tearDown()60 protected void tearDown() throws Exception { 61 super.tearDown(); 62 } 63 startActivity()64 protected T startActivity() throws Throwable { 65 runTestOnUiThread(new Runnable() { 66 @Override 67 public void run() { 68 mActivity = startActivity(createActivityIntent(), null, null); 69 } 70 }); 71 return mActivity; 72 } 73 stopActivity()74 protected void stopActivity() throws Throwable { 75 runTestOnUiThread(new Runnable() { 76 @Override 77 public void run() { 78 getInstrumentation().callActivityOnStop(mActivity); 79 } 80 }); 81 } 82 leaveActivity()83 protected void leaveActivity() throws Throwable { 84 runTestOnUiThread(new Runnable() { 85 @Override 86 public void run() { 87 getInstrumentation().callActivityOnUserLeaving(mActivity); 88 } 89 }); 90 } 91 waitForMs(long ms)92 public static void waitForMs(long ms) { 93 try { 94 Thread.sleep(ms); 95 } catch (InterruptedException e) { 96 } 97 } 98 createActivityIntent()99 protected Intent createActivityIntent() { 100 Intent intent = new Intent(); 101 return intent; 102 } 103 injectSystemService(Class<S> cls, S service)104 protected <S> void injectSystemService(Class<S> cls, S service) { 105 mContext.injectSystemService(cls, service); 106 } 107 waitForHandlerAction(Handler h, long timeoutMillis)108 protected final void waitForHandlerAction(Handler h, long timeoutMillis) { 109 final CountDownLatch lock = new CountDownLatch(1); 110 h.post(lock::countDown); 111 while (lock.getCount() > 0) { 112 try { 113 lock.await(timeoutMillis, TimeUnit.MILLISECONDS); 114 } catch (InterruptedException e) { 115 // do nothing 116 } 117 } 118 } 119 public static class TestContext extends ContextWrapper { 120 121 private static final String TAG = TestContext.class.getSimpleName(); 122 123 private HashMap<String, Object> mInjectedSystemServices = new HashMap<>(); 124 125 private Resources mResources; 126 127 boolean mIsOverrideConfigurationEnabled; 128 129 private PackageManager mPackageManager; 130 131 private SharedPreferences mSharedPreferences; 132 TestContext(Context base)133 public TestContext(Context base) { 134 super(base); 135 mResources = spy(super.getResources()); 136 Configuration configuration = new Configuration(); 137 configuration.setLocale(Locale.ROOT); 138 doReturn(configuration).when(mResources).getConfiguration(); 139 } 140 injectSystemService(Class<S> cls, S service)141 public <S> void injectSystemService(Class<S> cls, S service) { 142 final String name = getSystemServiceName(cls); 143 mInjectedSystemServices.put(name, service); 144 } 145 injectPackageManager(PackageManager packageManager)146 public void injectPackageManager(PackageManager packageManager) { 147 mPackageManager = packageManager; 148 } 149 injectSharedPreferences(SharedPreferences sp)150 public void injectSharedPreferences(SharedPreferences sp) { 151 mSharedPreferences = sp; 152 } 153 154 @Override getDisplay()155 public Display getDisplay() { 156 return ResourcesManager.getInstance().getAdjustedDisplay(Display.DEFAULT_DISPLAY, 157 null); 158 } 159 160 @Override getApplicationContext()161 public Context getApplicationContext() { 162 return this; 163 } 164 165 @Override getSystemService(String name)166 public Object getSystemService(String name) { 167 if (mInjectedSystemServices.containsKey(name)) { 168 Log.d(TAG, "return mocked system service for " + name); 169 return mInjectedSystemServices.get(name); 170 } 171 Log.d(TAG, "return real system service for " + name); 172 return super.getSystemService(name); 173 } 174 175 @Override getResources()176 public Resources getResources() { 177 return mResources; 178 } 179 180 @Override getPackageManager()181 public PackageManager getPackageManager() { 182 if (mPackageManager != null) { 183 return mPackageManager; 184 } 185 return super.getPackageManager(); 186 } 187 188 @Override getSharedPreferences(String name, int mode)189 public SharedPreferences getSharedPreferences(String name, int mode) { 190 if (mSharedPreferences != null) { 191 return mSharedPreferences; 192 } 193 return super.getSharedPreferences(name, mode); 194 } 195 196 @Override createConfigurationContext(Configuration overrideConfiguration)197 public Context createConfigurationContext(Configuration overrideConfiguration) { 198 if (!mIsOverrideConfigurationEnabled) { 199 return this; 200 } 201 202 TestContext newTestContext = new TestContext( 203 super.createConfigurationContext(overrideConfiguration)); 204 newTestContext.mInjectedSystemServices.putAll(mInjectedSystemServices); 205 return newTestContext; 206 } 207 enableOverrideConfiguration(boolean enabled)208 public void enableOverrideConfiguration(boolean enabled) { 209 mIsOverrideConfigurationEnabled = enabled; 210 } 211 212 } 213 waitForChange(BooleanSupplier condition, long timeoutMs)214 protected void waitForChange(BooleanSupplier condition, long timeoutMs) { 215 CountDownLatch latch = new CountDownLatch(1); 216 new Thread(() -> { 217 while (latch.getCount() > 0 && !condition.getAsBoolean()) { 218 // do nothing 219 } 220 latch.countDown(); 221 }).start(); 222 223 try { 224 latch.await(timeoutMs, TimeUnit.MILLISECONDS); 225 } catch (InterruptedException e) { 226 // do nothing 227 } 228 latch.countDown(); 229 } 230 } 231