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 package android.ambientcontext.cts; 17 18 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 19 20 import static com.android.compatibility.common.util.ShellUtils.runShellCommand; 21 22 import static com.google.common.truth.Truth.assertThat; 23 24 import static org.junit.Assume.assumeTrue; 25 26 import android.app.ambientcontext.AmbientContextEvent; 27 import android.app.ambientcontext.AmbientContextManager; 28 import android.content.Context; 29 import android.os.Build.VERSION; 30 import android.os.Build.VERSION_CODES; 31 import android.os.UserHandle; 32 import android.platform.test.annotations.AppModeFull; 33 import android.service.ambientcontext.AmbientContextDetectionResult; 34 35 import androidx.test.ext.junit.runners.AndroidJUnit4; 36 37 import com.android.compatibility.common.util.DeviceConfigStateChangerRule; 38 import com.android.compatibility.common.util.RequiredServiceRule; 39 40 import org.junit.After; 41 import org.junit.Before; 42 import org.junit.Rule; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 46 import java.util.Arrays; 47 import java.util.List; 48 49 50 /** 51 * This suite of test ensures that AmbientContextManagerService behaves correctly when properly 52 * bound to an AmbientContextDetectionService implementation. 53 */ 54 @RunWith(AndroidJUnit4.class) 55 @AppModeFull( 56 reason = "PM will not recognize CtsTestAmbientContextDetectionService in instantMode.") 57 public class CtsAmbientContextDetectionServiceDeviceTest { 58 @Rule 59 public final RequiredServiceRule mRequiredServiceRule = 60 new RequiredServiceRule(Context.AMBIENT_CONTEXT_SERVICE); 61 private static final String NAMESPACE_ambient_context = "ambient_context"; 62 private static final String KEY_SERVICE_ENABLED = "service_enabled"; 63 private static final String FAKE_APP_PACKAGE = "foo.bar.baz"; 64 public static final String CTS_PACKAGE_NAME = 65 CtsAmbientContextDetectionService.class.getPackage().getName(); 66 private static final String CTS_SERVICE_NAME = CTS_PACKAGE_NAME + "/." 67 + CtsAmbientContextDetectionService.class.getSimpleName(); 68 private static final int USER_ID = UserHandle.myUserId(); 69 70 private static final AmbientContextEvent FAKE_EVENT = new AmbientContextEvent.Builder() 71 .setEventType(AmbientContextEvent.EVENT_COUGH) 72 .setConfidenceLevel(AmbientContextEvent.LEVEL_HIGH) 73 .setDensityLevel(AmbientContextEvent.LEVEL_MEDIUM) 74 .build(); 75 private static final int TEMPORARY_SERVICE_DURATION = 5000; 76 77 @Rule 78 public final DeviceConfigStateChangerRule mLookAllTheseRules = 79 new DeviceConfigStateChangerRule(getInstrumentation().getTargetContext(), 80 NAMESPACE_ambient_context, 81 KEY_SERVICE_ENABLED, 82 "true"); 83 84 @Before setUp()85 public void setUp() { 86 assumeTrue("VERSION.SDK_INT=" + VERSION.SDK_INT, 87 VERSION.SDK_INT >= VERSION_CODES.TIRAMISU); 88 clearTestableAmbientContextDetectionService(); 89 CtsAmbientContextDetectionService.reset(); 90 bindToTestService(); 91 } 92 93 @After tearDown()94 public void tearDown() { 95 clearTestableAmbientContextDetectionService(); 96 } 97 98 @Test testAmbientContextDetectionService_OnSuccess()99 public void testAmbientContextDetectionService_OnSuccess() { 100 // From manager, call startDetection() on test service 101 assertThat(CtsAmbientContextDetectionService.hasPendingRequest()).isFalse(); 102 callStartDetection(); 103 assertThat(CtsAmbientContextDetectionService.hasPendingRequest()).isTrue(); 104 105 // From test service, respond with onSuccess 106 CtsAmbientContextDetectionService.respondSuccess(FAKE_EVENT); 107 108 // From manager, verify callback was called 109 assertThat(getLastStatusCode()).isEqualTo(AmbientContextManager.STATUS_SUCCESS); 110 } 111 112 @Test testAmbientContextDetectionService_OnServiceUnavailable()113 public void testAmbientContextDetectionService_OnServiceUnavailable() { 114 // From manager, call startDetection() on test service 115 assertThat(CtsAmbientContextDetectionService.hasPendingRequest()).isFalse(); 116 callStartDetection(); 117 assertThat(CtsAmbientContextDetectionService.hasPendingRequest()).isTrue(); 118 119 // From test service, cancel the request and respond with STATUS_SERVICE_UNAVAILABLE 120 CtsAmbientContextDetectionService.respondFailure( 121 AmbientContextManager.STATUS_SERVICE_UNAVAILABLE); 122 123 // From manager, verify that the callback was called with STATUS_SERVICE_UNAVAILABLE 124 assertThat(getLastStatusCode()).isEqualTo( 125 AmbientContextManager.STATUS_SERVICE_UNAVAILABLE); 126 } 127 128 @Test testAmbientContextDetectionService_QueryEventStatus()129 public void testAmbientContextDetectionService_QueryEventStatus() { 130 assertThat(CtsAmbientContextDetectionService.hasQueryRequest()).isFalse(); 131 callQueryServiceStatus(); 132 assertThat(CtsAmbientContextDetectionService.hasQueryRequest()).isTrue(); 133 134 // From test service, respond with STATUS_ACCESS_DENIED 135 CtsAmbientContextDetectionService.respondFailure( 136 AmbientContextManager.STATUS_ACCESS_DENIED); 137 138 // From manager, verify callback was called 139 assertThat(getLastStatusCode()).isEqualTo(AmbientContextManager.STATUS_ACCESS_DENIED); 140 } 141 142 @Test testConstructAmbientContextDetectionResult()143 public void testConstructAmbientContextDetectionResult() { 144 List<AmbientContextEvent> events = Arrays.asList(new AmbientContextEvent[] {FAKE_EVENT}); 145 AmbientContextDetectionResult result = new AmbientContextDetectionResult 146 .Builder(FAKE_APP_PACKAGE) 147 .addEvents(events) 148 .build(); 149 List<AmbientContextEvent> actualEvents = result.getEvents(); 150 assertThat(actualEvents.size()).isEqualTo(1); 151 assertThat(actualEvents).contains(FAKE_EVENT); 152 153 result = new AmbientContextDetectionResult 154 .Builder(FAKE_APP_PACKAGE) 155 .addEvents(events) 156 .clearEvents() 157 .build(); 158 assertThat(result.getEvents()).isEmpty(); 159 } 160 getLastStatusCode()161 private int getLastStatusCode() { 162 return Integer.parseInt(runShellCommand( 163 "cmd ambient_context get-last-status-code")); 164 } 165 bindToTestService()166 private void bindToTestService() { 167 // On Manager, bind to test service 168 assertThat(getAmbientContextDetectionServiceComponent()).isNotEqualTo(CTS_SERVICE_NAME); 169 setTestableAmbientContextDetectionService(CTS_SERVICE_NAME); 170 assertThat(CTS_SERVICE_NAME).contains(getAmbientContextDetectionServiceComponent()); 171 } 172 getAmbientContextDetectionServiceComponent()173 private String getAmbientContextDetectionServiceComponent() { 174 return runShellCommand("cmd ambient_context get-bound-package %d", USER_ID); 175 } 176 177 /** 178 * This call is asynchronous (manager spawns + binds to service and then asynchronously makes a 179 * call). 180 * As such, we need to ensure consistent testing results, by waiting until we receive a response 181 * in our test service w/ CountDownLatch(s). 182 */ callStartDetection()183 private void callStartDetection() { 184 runShellCommand("cmd ambient_context start-detection %d %s", 185 USER_ID, FAKE_APP_PACKAGE); 186 CtsAmbientContextDetectionService.onReceivedResponse(); 187 } 188 189 /** 190 * This call is asynchronous (manager spawns + binds to service and then asynchronously makes a 191 * call). 192 * As such, we need to ensure consistent testing results, by waiting until we receive a response 193 * in our test service w/ CountDownLatch(s). 194 */ callQueryServiceStatus()195 private void callQueryServiceStatus() { 196 runShellCommand("cmd ambient_context query-service-status %d %s", 197 USER_ID, FAKE_APP_PACKAGE); 198 CtsAmbientContextDetectionService.onReceivedResponse(); 199 } 200 setTestableAmbientContextDetectionService(String service)201 private void setTestableAmbientContextDetectionService(String service) { 202 runShellCommand("cmd ambient_context set-temporary-service %d %s %d", 203 USER_ID, service, TEMPORARY_SERVICE_DURATION); 204 } 205 clearTestableAmbientContextDetectionService()206 private void clearTestableAmbientContextDetectionService() { 207 runShellCommand("cmd ambient_context set-temporary-service %d", USER_ID); 208 } 209 } 210