blob: 9951e8597a8b4c3dbe7c5cb090d00ba73abc44f4 [file] [log] [blame]
Neil Fullerb5579072018-05-30 14:35:24 +01001/*
2 * Copyright (C) 2018 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.timedetector;
18
Neil Fuller4980bbc2018-06-12 21:06:20 +010019import static org.junit.Assert.assertEquals;
Neil Fuller4980bbc2018-06-12 21:06:20 +010020import static org.junit.Assert.assertTrue;
Neil Fuller4773b9d2018-06-08 18:44:49 +010021import static org.mockito.ArgumentMatchers.any;
22import static org.mockito.ArgumentMatchers.anyString;
23import static org.mockito.ArgumentMatchers.eq;
24import static org.mockito.Mockito.doNothing;
Neil Fuller4773b9d2018-06-08 18:44:49 +010025import static org.mockito.Mockito.mock;
26import static org.mockito.Mockito.verify;
Neil Fuller4980bbc2018-06-12 21:06:20 +010027import static org.mockito.Mockito.when;
Neil Fullerb5579072018-05-30 14:35:24 +010028
Neil Fuller3aedd492019-11-23 11:33:57 +000029import android.app.timedetector.ManualTimeSuggestion;
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010030import android.app.timedetector.PhoneTimeSuggestion;
Neil Fuller4773b9d2018-06-08 18:44:49 +010031import android.content.Context;
Neil Fuller4980bbc2018-06-12 21:06:20 +010032import android.content.pm.PackageManager;
Neil Fuller40cf2952019-11-28 09:47:30 +000033import android.os.Handler;
34import android.os.HandlerThread;
35import android.os.Looper;
36import android.os.Message;
Neil Fuller4773b9d2018-06-08 18:44:49 +010037import android.util.TimestampedValue;
38
Brett Chabot8091d9e2019-02-26 14:52:33 -080039import androidx.test.runner.AndroidJUnit4;
40
41import com.android.server.timedetector.TimeDetectorStrategy.Callback;
42
Neil Fuller40cf2952019-11-28 09:47:30 +000043import org.junit.After;
Neil Fullerb5579072018-05-30 14:35:24 +010044import org.junit.Before;
45import org.junit.Test;
46import org.junit.runner.RunWith;
47
Neil Fuller4980bbc2018-06-12 21:06:20 +010048import java.io.PrintWriter;
49
Neil Fullerb5579072018-05-30 14:35:24 +010050@RunWith(AndroidJUnit4.class)
51public class TimeDetectorServiceTest {
52
Neil Fuller4773b9d2018-06-08 18:44:49 +010053 private Context mMockContext;
Neil Fuller4980bbc2018-06-12 21:06:20 +010054 private StubbedTimeDetectorStrategy mStubbedTimeDetectorStrategy;
55 private Callback mMockCallback;
56
57 private TimeDetectorService mTimeDetectorService;
Neil Fuller40cf2952019-11-28 09:47:30 +000058 private HandlerThread mHandlerThread;
59 private TestHandler mTestHandler;
60
Neil Fuller4773b9d2018-06-08 18:44:49 +010061
Neil Fullerb5579072018-05-30 14:35:24 +010062 @Before
63 public void setUp() {
Neil Fuller4773b9d2018-06-08 18:44:49 +010064 mMockContext = mock(Context.class);
Neil Fuller40cf2952019-11-28 09:47:30 +000065
66 // Create a thread + handler for processing the work that the service posts.
67 mHandlerThread = new HandlerThread("TimeDetectorServiceTest");
68 mHandlerThread.start();
69 mTestHandler = new TestHandler(mHandlerThread.getLooper());
70
Neil Fuller4980bbc2018-06-12 21:06:20 +010071 mMockCallback = mock(Callback.class);
72 mStubbedTimeDetectorStrategy = new StubbedTimeDetectorStrategy();
Neil Fuller4773b9d2018-06-08 18:44:49 +010073
Neil Fuller4980bbc2018-06-12 21:06:20 +010074 mTimeDetectorService = new TimeDetectorService(
Neil Fuller40cf2952019-11-28 09:47:30 +000075 mMockContext, mTestHandler, mMockCallback,
Neil Fuller4980bbc2018-06-12 21:06:20 +010076 mStubbedTimeDetectorStrategy);
Neil Fuller4773b9d2018-06-08 18:44:49 +010077 }
78
Neil Fuller40cf2952019-11-28 09:47:30 +000079 @After
80 public void tearDown() throws Exception {
81 mHandlerThread.quit();
82 mHandlerThread.join();
Neil Fullerb5579072018-05-30 14:35:24 +010083 }
84
85 @Test
Neil Fuller40cf2952019-11-28 09:47:30 +000086 public void testSuggestPhoneTime() throws Exception {
Neil Fuller4773b9d2018-06-08 18:44:49 +010087 doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
88
Neil Fulleraf3eeaf2019-10-15 14:37:37 +010089 PhoneTimeSuggestion phoneTimeSuggestion = createPhoneTimeSuggestion();
90 mTimeDetectorService.suggestPhoneTime(phoneTimeSuggestion);
Neil Fuller40cf2952019-11-28 09:47:30 +000091 mTestHandler.assertTotalMessagesEnqueued(1);
Neil Fuller3aedd492019-11-23 11:33:57 +000092
93 verify(mMockContext).enforceCallingPermission(
94 eq(android.Manifest.permission.SET_TIME),
95 anyString());
Neil Fuller40cf2952019-11-28 09:47:30 +000096
97 mTestHandler.waitForEmptyQueue();
98 mStubbedTimeDetectorStrategy.verifySuggestPhoneTimeCalled(phoneTimeSuggestion);
99 }
100
101 @Test
102 public void testSuggestManualTime() throws Exception {
103 doNothing().when(mMockContext).enforceCallingPermission(anyString(), any());
104
105 ManualTimeSuggestion manualTimeSuggestion = createManualTimeSuggestion();
106 mTimeDetectorService.suggestManualTime(manualTimeSuggestion);
107 mTestHandler.assertTotalMessagesEnqueued(1);
108
109 verify(mMockContext).enforceCallingPermission(
110 eq(android.Manifest.permission.SET_TIME),
111 anyString());
112
113 mTestHandler.waitForEmptyQueue();
Neil Fuller3aedd492019-11-23 11:33:57 +0000114 mStubbedTimeDetectorStrategy.verifySuggestManualTimeCalled(manualTimeSuggestion);
115 }
116
117 @Test
Neil Fuller4980bbc2018-06-12 21:06:20 +0100118 public void testDump() {
119 when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
120 .thenReturn(PackageManager.PERMISSION_GRANTED);
121
122 mTimeDetectorService.dump(null, null, null);
123
124 verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
125 mStubbedTimeDetectorStrategy.verifyDumpCalled();
126 }
127
128 @Test
Neil Fuller40cf2952019-11-28 09:47:30 +0000129 public void testAutoTimeDetectionToggle() throws Exception {
130 mTimeDetectorService.handleAutoTimeDetectionToggle();
131 mTestHandler.assertTotalMessagesEnqueued(1);
132 mTestHandler.waitForEmptyQueue();
133 mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionToggleCalled();
Neil Fuller4980bbc2018-06-12 21:06:20 +0100134
135 mTimeDetectorService.handleAutoTimeDetectionToggle();
Neil Fuller40cf2952019-11-28 09:47:30 +0000136 mTestHandler.assertTotalMessagesEnqueued(2);
137 mTestHandler.waitForEmptyQueue();
138 mStubbedTimeDetectorStrategy.verifyHandleAutoTimeDetectionToggleCalled();
Neil Fullerb5579072018-05-30 14:35:24 +0100139 }
140
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100141 private static PhoneTimeSuggestion createPhoneTimeSuggestion() {
142 int phoneId = 1234;
Neil Fuller568fd892019-11-20 14:39:06 +0000143 PhoneTimeSuggestion suggestion = new PhoneTimeSuggestion(phoneId);
Neil Fuller4773b9d2018-06-08 18:44:49 +0100144 TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
Neil Fuller568fd892019-11-20 14:39:06 +0000145 suggestion.setUtcTime(timeValue);
146 return suggestion;
Neil Fuller4773b9d2018-06-08 18:44:49 +0100147 }
Neil Fuller4980bbc2018-06-12 21:06:20 +0100148
Neil Fuller3aedd492019-11-23 11:33:57 +0000149 private static ManualTimeSuggestion createManualTimeSuggestion() {
150 TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
151 return new ManualTimeSuggestion(timeValue);
152 }
153
Neil Fuller4980bbc2018-06-12 21:06:20 +0100154 private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
155
156 // Call tracking.
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100157 private PhoneTimeSuggestion mLastPhoneSuggestion;
Neil Fuller3aedd492019-11-23 11:33:57 +0000158 private ManualTimeSuggestion mLastManualSuggestion;
Neil Fuller40cf2952019-11-28 09:47:30 +0000159 private boolean mLastAutoTimeDetectionToggleCalled;
Neil Fuller4980bbc2018-06-12 21:06:20 +0100160 private boolean mDumpCalled;
161
162 @Override
163 public void initialize(Callback ignored) {
164 }
165
166 @Override
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100167 public void suggestPhoneTime(PhoneTimeSuggestion timeSuggestion) {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100168 resetCallTracking();
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100169 mLastPhoneSuggestion = timeSuggestion;
Neil Fuller4980bbc2018-06-12 21:06:20 +0100170 }
171
172 @Override
Neil Fuller3aedd492019-11-23 11:33:57 +0000173 public void suggestManualTime(ManualTimeSuggestion timeSuggestion) {
174 resetCallTracking();
175 mLastManualSuggestion = timeSuggestion;
176 }
177
178 @Override
Neil Fuller40cf2952019-11-28 09:47:30 +0000179 public void handleAutoTimeDetectionChanged() {
Neil Fuller4980bbc2018-06-12 21:06:20 +0100180 resetCallTracking();
Neil Fuller40cf2952019-11-28 09:47:30 +0000181 mLastAutoTimeDetectionToggleCalled = true;
Neil Fuller4980bbc2018-06-12 21:06:20 +0100182 }
183
184 @Override
185 public void dump(PrintWriter pw, String[] args) {
186 resetCallTracking();
187 mDumpCalled = true;
188 }
189
190 void resetCallTracking() {
Neil Fulleraf3eeaf2019-10-15 14:37:37 +0100191 mLastPhoneSuggestion = null;
Neil Fuller3aedd492019-11-23 11:33:57 +0000192 mLastManualSuggestion = null;
Neil Fuller40cf2952019-11-28 09:47:30 +0000193 mLastAutoTimeDetectionToggleCalled = false;
Neil Fuller4980bbc2018-06-12 21:06:20 +0100194 mDumpCalled = false;
195 }
196
Neil Fuller3aedd492019-11-23 11:33:57 +0000197 void verifySuggestPhoneTimeCalled(PhoneTimeSuggestion expectedSuggestion) {
198 assertEquals(expectedSuggestion, mLastPhoneSuggestion);
199 }
200
201 public void verifySuggestManualTimeCalled(ManualTimeSuggestion expectedSuggestion) {
202 assertEquals(expectedSuggestion, mLastManualSuggestion);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100203 }
204
Neil Fuller40cf2952019-11-28 09:47:30 +0000205 void verifyHandleAutoTimeDetectionToggleCalled() {
206 assertTrue(mLastAutoTimeDetectionToggleCalled);
Neil Fuller4980bbc2018-06-12 21:06:20 +0100207 }
208
209 void verifyDumpCalled() {
210 assertTrue(mDumpCalled);
211 }
212 }
Neil Fuller40cf2952019-11-28 09:47:30 +0000213
214 /**
215 * A Handler that can track posts/sends and wait for work to be completed.
216 */
217 private static class TestHandler extends Handler {
218
219 private int mMessagesSent;
220
221 TestHandler(Looper looper) {
222 super(looper);
223 }
224
225 @Override
226 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
227 mMessagesSent++;
228 return super.sendMessageAtTime(msg, uptimeMillis);
229 }
230
231 /** Asserts the number of messages posted or sent is as expected. */
232 void assertTotalMessagesEnqueued(int expected) {
233 assertEquals(expected, mMessagesSent);
234 }
235
236 /**
237 * Waits for all currently enqueued work due to be processed to be completed before
238 * returning.
239 */
240 void waitForEmptyQueue() throws InterruptedException {
241 while (!getLooper().getQueue().isIdle()) {
242 Thread.sleep(100);
243 }
244 }
245 }
Neil Fullerb5579072018-05-30 14:35:24 +0100246}