1 /*
2  * Copyright (C) 2021 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 
17 package android.car.test.util;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import android.content.BroadcastReceiver;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.res.Resources;
26 import android.os.Handler;
27 import android.os.MessageQueue;
28 import android.test.mock.MockContext;
29 import android.util.ArrayMap;
30 
31 import com.google.common.collect.Lists;
32 
33 import java.util.ArrayList;
34 import java.util.Map;
35 import java.util.concurrent.CountDownLatch;
36 
37 /**
38  * A fake implementation for {@link android.content.Context}, that provides the following
39  * functions:
40  * <ul>
41  *     <li> Fake implementations for {@link #registerReceiver} and {@link #unregisterReceiver}.
42  *     The helper methods {@link #verifyReceiverRegistered} and
43  *     {@link #verifyReceiverNotRegistered} can be used to validate the state.
44  *     <li> Fake implementation for {@link #sendBroadcast} that sends the intent to a registered
45  *     {@link BroadcastReceiver}.
46  *     <li> Fake implementations for {@link #getSystemService} and {@link #getSystemServiceName}.
47  *     Helper method {@link #setSystemService} can be used to provide values returned by these
48  *     methods.
49  *     <li> Fake implementation for {@link #getResources}. Helper method {@link #setResources}
50  *     can be used to provide a value for this.
51  * </ul>
52  */
53 // TODO(b/202420937): Add unit tests for this class.
54 public final class FakeContext extends MockContext {
55 
56     private final Map<String, Object> mSystemServices = new ArrayMap<>();
57 
58     private BroadcastReceiver mReceiver;
59     private IntentFilter mIntentFilter;
60     private Handler mHandler;
61     private Resources mResources;
62 
setSystemService(Class<T> serviceClass, T serviceInstance)63     public <T> void setSystemService(Class<T> serviceClass, T serviceInstance) {
64         mSystemServices.put(serviceClass.getName(), serviceInstance);
65     }
66 
67     @Override
getSystemService(String name)68     public Object getSystemService(String name) {
69         return mSystemServices.get(name);
70     }
71 
72     @Override
getSystemServiceName(Class<?> serviceClass)73     public String getSystemServiceName(Class<?> serviceClass) {
74         return serviceClass.getName();
75     }
76 
77     @Override
getResources()78     public Resources getResources() {
79         return mResources;
80     }
81 
setResources(Resources resources)82     public void setResources(Resources resources) {
83         mResources = resources;
84     }
85 
86     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)87     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
88         return registerReceiver(receiver, filter, null, null);
89     }
90 
91     @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)92     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
93             String broadcastPermission, Handler scheduler) {
94         mReceiver = receiver;
95         mIntentFilter = filter;
96         mHandler = scheduler;
97 
98         return null;
99     }
100 
101     @Override
sendBroadcast(Intent intent)102     public void sendBroadcast(Intent intent) {
103         if (mHandler == null) {
104             mReceiver.onReceive(this, intent);
105             return;
106         }
107 
108         CountDownLatch latch = new CountDownLatch(1);
109         MessageQueue.IdleHandler queueIdleHandler = () -> {
110             latch.countDown();
111             return false;
112         };
113         mHandler.getLooper().getQueue().addIdleHandler(queueIdleHandler);
114 
115         mHandler.post(() -> mReceiver.onReceive(this, intent));
116 
117         // wait until the queue is idle
118         try {
119             latch.await();
120         } catch (InterruptedException e) {
121             Thread.currentThread().interrupt();
122             throw new IllegalStateException(
123                     "Interrupted while waiting for Broadcast Intent to be received", e);
124         } finally {
125             mHandler.getLooper().getQueue().removeIdleHandler(queueIdleHandler);
126         }
127     }
128 
129     @Override
unregisterReceiver(BroadcastReceiver receiver)130     public void unregisterReceiver(BroadcastReceiver receiver) {
131         if (receiver == mReceiver) {
132             mReceiver = null;
133             mIntentFilter = null;
134             mHandler = null;
135         }
136     }
137 
verifyReceiverNotRegistered()138     public void verifyReceiverNotRegistered() {
139         assertThat(mIntentFilter).isNull();
140         assertThat(mReceiver).isNull();
141         assertThat(mHandler).isNull();
142     }
143 
verifyReceiverRegistered(String expectedAction)144     public void verifyReceiverRegistered(String expectedAction) {
145         assertThat(mIntentFilter.actionsIterator()).isNotNull();
146         ArrayList<String> actions = Lists.newArrayList(mIntentFilter.actionsIterator());
147         assertWithMessage("IntentFilter actions").that(actions).contains(expectedAction);
148         assertWithMessage("Registered BroadcastReceiver").that(mReceiver).isNotNull();
149     }
150 }
151