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