blob: 10442b7e467d0d446c73efb70c1e6e0845ac4955 [file] [log] [blame]
Bernardo Rufinoaf547f42017-11-13 15:49:41 +00001/*
2 * Copyright (C) 2017 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
17package com.android.server.backup.transport;
18
19import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
Bernardo Rufinoab953332017-11-22 22:10:32 +000020import static com.google.common.truth.Truth.assertThat;
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000021import static org.mockito.ArgumentMatchers.any;
22import static org.mockito.ArgumentMatchers.anyInt;
23import static org.mockito.ArgumentMatchers.eq;
24import static org.mockito.ArgumentMatchers.isNull;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.when;
27import static org.robolectric.Shadows.shadowOf;
28
29import android.content.ComponentName;
30import android.content.Context;
31import android.content.Intent;
32import android.content.ServiceConnection;
33import android.os.Handler;
34import android.os.Looper;
35import android.os.UserHandle;
36import android.platform.test.annotations.Presubmit;
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000037import com.android.internal.backup.IBackupTransport;
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +000038import com.android.server.EventLogTags;
Bernardo Rufino90a88022017-11-13 17:19:15 +000039import com.android.server.backup.TransportManager;
40import com.android.server.testing.FrameworkRobolectricTestRunner;
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +000041import com.android.server.testing.ShadowEventLog;
Bernardo Rufino90a88022017-11-13 17:19:15 +000042import com.android.server.testing.SystemLoaderClasses;
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000043import org.junit.Before;
44import org.junit.Test;
45import org.junit.runner.RunWith;
46import org.mockito.ArgumentCaptor;
47import org.mockito.Mock;
48import org.mockito.MockitoAnnotations;
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000049import org.robolectric.annotation.Config;
50import org.robolectric.shadows.ShadowLooper;
51
Bernardo Rufino90a88022017-11-13 17:19:15 +000052@RunWith(FrameworkRobolectricTestRunner.class)
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +000053@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowEventLog.class})
Bernardo Rufino90a88022017-11-13 17:19:15 +000054@SystemLoaderClasses({TransportManager.class, TransportClient.class})
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000055@Presubmit
56public class TransportClientTest {
57 private static final String PACKAGE_NAME = "some.package.name";
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000058
59 @Mock private Context mContext;
60 @Mock private TransportConnectionListener mTransportConnectionListener;
61 @Mock private TransportConnectionListener mTransportConnectionListener2;
62 @Mock private IBackupTransport.Stub mIBackupTransport;
63 private TransportClient mTransportClient;
Bernardo Rufino90a88022017-11-13 17:19:15 +000064 private ComponentName mTransportComponent;
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +000065 private String mTransportString;
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000066 private Intent mBindIntent;
67 private ShadowLooper mShadowLooper;
68
69 @Before
70 public void setUp() throws Exception {
71 MockitoAnnotations.initMocks(this);
72
73 Looper mainLooper = Looper.getMainLooper();
74 mShadowLooper = shadowOf(mainLooper);
Bernardo Rufino90a88022017-11-13 17:19:15 +000075 mTransportComponent =
76 new ComponentName(PACKAGE_NAME, PACKAGE_NAME + ".transport.Transport");
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +000077 mTransportString = mTransportComponent.flattenToShortString();
Bernardo Rufino90a88022017-11-13 17:19:15 +000078 mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000079 mTransportClient =
80 new TransportClient(
Annie Meng789bf282018-01-15 12:10:38 +000081 mContext, mBindIntent, mTransportComponent, "1", new Handler(mainLooper));
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000082
83 when(mContext.bindServiceAsUser(
84 eq(mBindIntent),
85 any(ServiceConnection.class),
86 anyInt(),
87 any(UserHandle.class)))
88 .thenReturn(true);
89 }
90
Bernardo Rufinoab953332017-11-22 22:10:32 +000091 @Test
Bernardo Rufinoab953332017-11-22 22:10:32 +000092 public void testGetTransportComponent_returnsTransportComponent() {
Bernardo Rufino90a88022017-11-13 17:19:15 +000093 assertThat(mTransportClient.getTransportComponent()).isEqualTo(mTransportComponent);
Bernardo Rufinoab953332017-11-22 22:10:32 +000094 }
95
Bernardo Rufinoaf547f42017-11-13 15:49:41 +000096 @Test
97 public void testConnectAsync_callsBindService() throws Exception {
98 mTransportClient.connectAsync(mTransportConnectionListener, "caller");
99
100 verify(mContext)
101 .bindServiceAsUser(
102 eq(mBindIntent),
103 any(ServiceConnection.class),
104 anyInt(),
105 any(UserHandle.class));
106 }
107
108 @Test
109 public void testConnectAsync_callsListenerWhenConnected() throws Exception {
110 mTransportClient.connectAsync(mTransportConnectionListener, "caller");
111
112 // Simulate framework connecting
113 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
Bernardo Rufino90a88022017-11-13 17:19:15 +0000114 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000115
116 mShadowLooper.runToEndOfTasks();
117 verify(mTransportConnectionListener)
118 .onTransportConnectionResult(any(IBackupTransport.class), eq(mTransportClient));
119 }
120
121 @Test
122 public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected()
123 throws Exception {
124 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
125 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
126
127 mTransportClient.connectAsync(mTransportConnectionListener2, "caller2");
128
Bernardo Rufino90a88022017-11-13 17:19:15 +0000129 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000130
131 mShadowLooper.runToEndOfTasks();
132 verify(mTransportConnectionListener)
133 .onTransportConnectionResult(any(IBackupTransport.class), eq(mTransportClient));
134 verify(mTransportConnectionListener2)
135 .onTransportConnectionResult(any(IBackupTransport.class), eq(mTransportClient));
136 }
137
138 @Test
139 public void testConnectAsync_whenAlreadyConnected_callsListener() throws Exception {
140 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
141 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
Bernardo Rufino90a88022017-11-13 17:19:15 +0000142 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000143
144 mTransportClient.connectAsync(mTransportConnectionListener2, "caller2");
145
146 mShadowLooper.runToEndOfTasks();
147 verify(mTransportConnectionListener2)
148 .onTransportConnectionResult(any(IBackupTransport.class), eq(mTransportClient));
149 }
150
151 @Test
152 public void testConnectAsync_whenFrameworkDoesntBind_callsListener() throws Exception {
153 when(mContext.bindServiceAsUser(
154 eq(mBindIntent),
155 any(ServiceConnection.class),
156 anyInt(),
157 any(UserHandle.class)))
158 .thenReturn(false);
159
160 mTransportClient.connectAsync(mTransportConnectionListener, "caller");
161
162 mShadowLooper.runToEndOfTasks();
163 verify(mTransportConnectionListener)
164 .onTransportConnectionResult(isNull(), eq(mTransportClient));
165 }
166
167 @Test
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +0000168 public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000169 when(mContext.bindServiceAsUser(
170 eq(mBindIntent),
171 any(ServiceConnection.class),
172 anyInt(),
173 any(UserHandle.class)))
174 .thenReturn(false);
175
176 mTransportClient.connectAsync(mTransportConnectionListener, "caller");
177
178 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
179 verify(mContext).unbindService(eq(connection));
180 }
181
182 @Test
183 public void testConnectAsync_afterServiceDisconnectedBeforeNewConnection_callsListener()
184 throws Exception {
185 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
186 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
Bernardo Rufino90a88022017-11-13 17:19:15 +0000187 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
188 connection.onServiceDisconnected(mTransportComponent);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000189
190 mTransportClient.connectAsync(mTransportConnectionListener2, "caller1");
191
192 verify(mTransportConnectionListener2)
193 .onTransportConnectionResult(isNull(), eq(mTransportClient));
194 }
195
196 @Test
197 public void testConnectAsync_afterServiceDisconnectedAfterNewConnection_callsListener()
198 throws Exception {
199 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
200 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
Bernardo Rufino90a88022017-11-13 17:19:15 +0000201 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
202 connection.onServiceDisconnected(mTransportComponent);
203 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000204
205 mTransportClient.connectAsync(mTransportConnectionListener2, "caller1");
206
207 // Yes, it should return null because the object became unusable, check design doc
208 verify(mTransportConnectionListener2)
209 .onTransportConnectionResult(isNull(), eq(mTransportClient));
210 }
211
Annie Meng789bf282018-01-15 12:10:38 +0000212 @Test
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000213 public void testConnectAsync_callsListenerIfBindingDies() throws Exception {
Annie Meng789bf282018-01-15 12:10:38 +0000214 mTransportClient.connectAsync(mTransportConnectionListener, "caller");
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000215
216 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
Bernardo Rufino90a88022017-11-13 17:19:15 +0000217 connection.onBindingDied(mTransportComponent);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000218
219 mShadowLooper.runToEndOfTasks();
Annie Meng789bf282018-01-15 12:10:38 +0000220 verify(mTransportConnectionListener)
221 .onTransportConnectionResult(isNull(), eq(mTransportClient));
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000222 }
223
224 @Test
225 public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies()
226 throws Exception {
Annie Meng789bf282018-01-15 12:10:38 +0000227 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000228 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
229
Annie Meng789bf282018-01-15 12:10:38 +0000230 mTransportClient.connectAsync(mTransportConnectionListener2, "caller2");
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000231
Bernardo Rufino90a88022017-11-13 17:19:15 +0000232 connection.onBindingDied(mTransportComponent);
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000233
234 mShadowLooper.runToEndOfTasks();
Annie Meng789bf282018-01-15 12:10:38 +0000235 verify(mTransportConnectionListener)
236 .onTransportConnectionResult(isNull(), eq(mTransportClient));
237 verify(mTransportConnectionListener2)
238 .onTransportConnectionResult(isNull(), eq(mTransportClient));
239 }
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000240
Bernardo Rufinoaa56a6c2018-01-16 14:10:19 +0000241 @Test
242 public void testConnectAsync_beforeFrameworkCall_logsBoundTransition() {
243 ShadowEventLog.clearEvents();
244
245 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
246
247 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
248 }
249
250 @Test
251 public void testConnectAsync_afterOnServiceConnected_logsBoundAndConnectedTransitions() {
252 ShadowEventLog.clearEvents();
253
254 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
255 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
256 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
257
258 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
259 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 1);
260 }
261
262 @Test
263 public void testConnectAsync_afterOnBindingDied_logsBoundAndUnboundTransitions() {
264 ShadowEventLog.clearEvents();
265
266 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
267 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
268 connection.onBindingDied(mTransportComponent);
269
270 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 1);
271 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
272 }
273
274 @Test
275 public void testUnbind_whenConnected_logsDisconnectedAndUnboundTransitions() {
276 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
277 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
278 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
279 ShadowEventLog.clearEvents();
280
281 mTransportClient.unbind("caller1");
282
283 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
284 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
285 }
286
287 @Test
288 public void testOnServiceDisconnected_whenConnected_logsDisconnectedAndUnboundTransitions() {
289 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
290 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
291 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
292 ShadowEventLog.clearEvents();
293
294 connection.onServiceDisconnected(mTransportComponent);
295
296 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
297 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
298 }
299
300 @Test
301 public void testOnBindingDied_whenConnected_logsDisconnectedAndUnboundTransitions() {
302 mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
303 ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
304 connection.onServiceConnected(mTransportComponent, mIBackupTransport);
305 ShadowEventLog.clearEvents();
306
307 connection.onBindingDied(mTransportComponent);
308
309 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_CONNECTION, mTransportString, 0);
310 assertEventLogged(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, mTransportString, 0);
311 }
312
313 private void assertEventLogged(int tag, Object... values) {
314 assertThat(ShadowEventLog.hasEvent(tag, values)).isTrue();
315 }
316
Bernardo Rufinoaf547f42017-11-13 15:49:41 +0000317 private ServiceConnection verifyBindServiceAsUserAndCaptureServiceConnection(Context context) {
318 ArgumentCaptor<ServiceConnection> connectionCaptor =
319 ArgumentCaptor.forClass(ServiceConnection.class);
320 verify(context)
321 .bindServiceAsUser(
322 any(Intent.class),
323 connectionCaptor.capture(),
324 anyInt(),
325 any(UserHandle.class));
326 return connectionCaptor.getValue();
327 }
328}