• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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