1 /*
2  * Copyright (C) 2020 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.sensorratepermission.cts.eventconnectionapi30;
18 
19 import android.content.Context;
20 import android.hardware.Sensor;
21 import android.hardware.SensorManager;
22 import android.hardware.SensorPrivacyManager;
23 import android.hardware.cts.helpers.SensorRatePermissionEventConnectionTestHelper;
24 import android.hardware.cts.helpers.TestSensorEnvironment;
25 import android.hardware.cts.helpers.TestSensorEvent;
26 import android.hardware.cts.helpers.TestSensorEventListener;
27 import android.hardware.cts.helpers.TestSensorManager;
28 import android.os.UserHandle;
29 
30 import androidx.test.platform.app.InstrumentationRegistry;
31 
32 import org.junit.After;
33 import org.junit.Assert;
34 import org.junit.Assume;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.junit.runners.Parameterized;
39 
40 import java.util.Collection;
41 import java.util.List;
42 import java.util.concurrent.CountDownLatch;
43 import java.util.concurrent.TimeUnit;
44 
45 
46 /**
47  * Test sampling rates obtained by event connections:
48  * - App targets API 30
49  *
50  * Expected behaviors:
51  * - Sampling rate is capped if the mic toggle is on
52  * - Sampling rate is not capped if the mic toggle is off
53  */
54 @RunWith(Parameterized.class)
55 public class EventConnectionAPI30Test {
56     private static final int NUM_EVENTS_COUNT = 1024;
57 
58     private static SensorRatePermissionEventConnectionTestHelper mEventConnectionTestHelper;
59     private static SensorPrivacyManager mSensorPrivacyManager;
60     private static TestSensorEnvironment mTestEnvironment;
61     private static int mUncappedMinDelayMicros;
62     private static int mCappedMinDelayMicros;
63     private static int mUserID;
64 
65     private final int sensorType;
66 
EventConnectionAPI30Test(int sensorType)67     public EventConnectionAPI30Test(int sensorType) {
68         this.sensorType = sensorType;
69     }
70 
71     @Parameterized.Parameters
cappedSensorTypeSet()72     public static Collection cappedSensorTypeSet() {
73         return SensorRatePermissionEventConnectionTestHelper.CAPPED_SENSOR_TYPE_SET;
74     }
75 
76     @Before
setUp()77     public void setUp() {
78         Context context = InstrumentationRegistry.getInstrumentation().getContext();
79         SensorManager sensorManager = context.getSystemService(SensorManager.class);
80         Sensor sensor = sensorManager.getDefaultSensor(sensorType);
81         Assume.assumeTrue("Failed to find a sensor!", sensor != null);
82 
83         mTestEnvironment = new TestSensorEnvironment(
84                 context,
85                 sensor,
86                 SensorManager.SENSOR_DELAY_FASTEST,
87                 (int) TimeUnit.SECONDS.toMicros(5));
88         Assume.assumeTrue("Failed to create mTestEnvironment!", mTestEnvironment != null);
89 
90         mEventConnectionTestHelper = new SensorRatePermissionEventConnectionTestHelper(
91                 mTestEnvironment);
92         Assume.assumeTrue("Failed to create mEventConnectionTestHelper!",
93                 mEventConnectionTestHelper != null);
94 
95         mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
96         Assume.assumeTrue(mSensorPrivacyManager
97                 .supportsSensorToggle(SensorPrivacyManager.Sensors.MICROPHONE));
98         // In context of this app (targetSDK = 30), this returns the original supported min delay
99         // of the sensor
100         mUncappedMinDelayMicros = mTestEnvironment.getSensor().getMinDelay();
101         mCappedMinDelayMicros = (int) TimeUnit.SECONDS.toMicros(1)
102                 / SensorRatePermissionEventConnectionTestHelper.CAPPED_SAMPLE_RATE_HZ;
103         mUserID = UserHandle.myUserId();
104     }
105 
106     @After
tearDown()107     public void tearDown() throws InterruptedException {
108         if (mEventConnectionTestHelper != null) {
109             mEventConnectionTestHelper.flipAndAssertMicToggleOff(mUserID, mSensorPrivacyManager);
110         }
111     }
112 
113     @Test
testSamplingRateMicToggleOff()114     public void testSamplingRateMicToggleOff() throws InterruptedException {
115         // Only run this test if minDelay of the sensor is smaller than the capped min delay
116         if (mUncappedMinDelayMicros >= mCappedMinDelayMicros) {
117             return;
118         }
119 
120         mEventConnectionTestHelper.flipAndAssertMicToggleOff(mUserID, mSensorPrivacyManager);
121         List<TestSensorEvent> events = mEventConnectionTestHelper.getSensorEvents(
122                 true,
123                 NUM_EVENTS_COUNT);
124         double obtainedRate = SensorRatePermissionEventConnectionTestHelper.computeAvgRate(events,
125                 Long.MIN_VALUE, Long.MAX_VALUE);
126 
127         Assert.assertTrue(mEventConnectionTestHelper.errorWhenBelowExpectedRate(),
128                 obtainedRate
129                         > SensorRatePermissionEventConnectionTestHelper.CAPPED_SAMPLE_RATE_HZ);
130     }
131 
132     @Test
testSamplingRateMicToggleOn()133     public void testSamplingRateMicToggleOn() throws InterruptedException {
134         mEventConnectionTestHelper.flipAndAssertMicToggleOn(mUserID, mSensorPrivacyManager);
135 
136         List<TestSensorEvent> events = mEventConnectionTestHelper.getSensorEvents(
137                 true,
138                 NUM_EVENTS_COUNT);
139         double obtainedRate = SensorRatePermissionEventConnectionTestHelper.computeAvgRate(events,
140                 Long.MIN_VALUE, Long.MAX_VALUE);
141 
142         Assert.assertTrue(mEventConnectionTestHelper.errorWhenExceedCappedRate(),
143                 obtainedRate
144                         <= SensorRatePermissionEventConnectionTestHelper.CAPPED_SAMPLE_RATE_HZ);
145     }
146 
147     /**
148      * Test the case where a connection is ongoing while the mic toggle changes its state:
149      * off -> on -> off. This test is to show that the sensor service is able to cap/uncap the
150      * rate of ongoing SensorEventConnections when the state of the mic toggle changes.
151      */
152     @Test
testSamplingRateMicToggleOffOnOff()153     public void testSamplingRateMicToggleOffOnOff() throws InterruptedException {
154         // Only run this test if minDelay of the sensor is smaller than the capped min delay
155         if (mUncappedMinDelayMicros >= mCappedMinDelayMicros) {
156             return;
157         }
158         // Start with the mic toggle off
159         mEventConnectionTestHelper.flipAndAssertMicToggleOff(mUserID, mSensorPrivacyManager);
160         // Register a listener
161         TestSensorEventListener listener = new TestSensorEventListener(mTestEnvironment);
162         TestSensorManager testSensorManager = new TestSensorManager(mTestEnvironment);
163         testSensorManager.registerListener(listener);
164 
165         // Flip the mic toggle on and clear all the events so far.
166         mEventConnectionTestHelper.flipAndAssertMicToggleOn(mUserID, mSensorPrivacyManager);
167         listener.clearEvents();
168 
169         // Wait for 1000 events and check the sampling rates.
170         CountDownLatch eventLatch = listener.getLatchForSensorEvents(1000 /*numOfEvents*/);
171         listener.waitForEvents(eventLatch, 1000 /*numOfEvents*/, false);
172         List<TestSensorEvent> events = listener.getCollectedEvents();
173         double rateWhenMicToggleOn =
174                 SensorRatePermissionEventConnectionTestHelper.computeAvgRate(events,
175                         Long.MIN_VALUE, Long.MAX_VALUE);
176         Assert.assertTrue(mEventConnectionTestHelper.errorWhenExceedCappedRate(),
177                 rateWhenMicToggleOn
178                         <= SensorRatePermissionEventConnectionTestHelper.CAPPED_SAMPLE_RATE_HZ);
179 
180         // Flip the mic toggle off, clear all the events so far.
181         mEventConnectionTestHelper.flipAndAssertMicToggleOff(mUserID, mSensorPrivacyManager);
182         listener.clearEvents();
183 
184         // Wait for 2000 events and check the sampling rates.
185         eventLatch = listener.getLatchForSensorEvents(2000 /*numOfEvents*/);
186         listener.waitForEvents(eventLatch, 2000 /*numOfEvents*/, false);
187         events = listener.getCollectedEvents();
188         double rateWhenMicToggleOff = SensorRatePermissionEventConnectionTestHelper.computeAvgRate(
189                 events, Long.MIN_VALUE, Long.MAX_VALUE);
190         Assert.assertTrue(mEventConnectionTestHelper.errorWhenBelowExpectedRate(),
191                 rateWhenMicToggleOff
192                         > SensorRatePermissionEventConnectionTestHelper.CAPPED_SAMPLE_RATE_HZ);
193 
194         listener.clearEvents();
195         testSensorManager.unregisterListener();
196     }
197 }
198