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 
17 package android.hardware.cts.helpers;
18 
19 import android.hardware.Sensor;
20 import android.hardware.SensorPrivacyManager;
21 import android.os.Handler;
22 
23 import com.android.compatibility.common.util.ShellUtils;
24 import com.android.compatibility.common.util.SystemUtil;
25 
26 import com.google.common.collect.ImmutableSet;
27 
28 import org.junit.Assert;
29 
30 import java.util.List;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.TimeUnit;
33 import java.util.stream.Collectors;
34 
35 /**
36  * A helper class to test sensor APIs related to sampling rates of SensorEventConnections.
37  */
38 public class SensorRatePermissionEventConnectionTestHelper {
39     public static final int CAPPED_SAMPLE_RATE_HZ = 270; // Capped rate 200 Hz + headroom
40     // Set of sensors that are throttled
41     public static final ImmutableSet<Integer> CAPPED_SENSOR_TYPE_SET = ImmutableSet.of(
42             Sensor.TYPE_ACCELEROMETER,
43             Sensor.TYPE_ACCELEROMETER_UNCALIBRATED,
44             Sensor.TYPE_GYROSCOPE,
45             Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
46             Sensor.TYPE_MAGNETIC_FIELD,
47             Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED
48     );
49 
50     private final TestSensorEnvironment mTestSensorEnvironment;
51     private final TestSensorManager mTestSensorManager;
52 
SensorRatePermissionEventConnectionTestHelper(TestSensorEnvironment environment)53     public SensorRatePermissionEventConnectionTestHelper(TestSensorEnvironment environment) {
54         mTestSensorEnvironment = environment;
55         mTestSensorManager = new TestSensorManager(mTestSensorEnvironment);
56     }
57 
computeAvgRate(List<TestSensorEvent> events, long startTimestamp, long endTimestamp)58     public static double computeAvgRate(List<TestSensorEvent> events,
59             long startTimestamp, long endTimestamp) {
60 
61         List<TestSensorEvent> filteredEvents = events.stream()
62                 .filter(event -> event.timestamp > startTimestamp && event.timestamp < endTimestamp)
63                 .collect(Collectors.toList());
64 
65         double rate = Double.MIN_VALUE;
66         int numOfEvents = filteredEvents.size();
67         if (numOfEvents >= 2) {
68             long lastTimestamp = filteredEvents.get(numOfEvents - 1).timestamp;
69             long firstTimestamp = filteredEvents.get(0).timestamp;
70             rate = SensorCtsHelper.getFrequency(
71                     (lastTimestamp - firstTimestamp) / (numOfEvents - 1),
72                     TimeUnit.NANOSECONDS);
73         }
74         return rate;
75     }
76 
77     /**
78      * Error message being shown in Assert statements of unit tests when the sampling rate exceeds
79      * the allowed capped rate.
80      */
errorWhenExceedCappedRate()81     public String errorWhenExceedCappedRate() {
82         Sensor sensor = mTestSensorEnvironment.getSensor();
83         return String.format(
84                 "%s: Sampling rate is expected to be less than or equal to %d (Hz)",
85                 sensor.getName(),
86                 CAPPED_SAMPLE_RATE_HZ);
87     }
88 
89     /**
90      * Error message being shown in Assert statements of unit tests when the sampling rate is below
91      * its expected rate.
92      */
errorWhenBelowExpectedRate()93     public String errorWhenBelowExpectedRate() {
94         Sensor sensor = mTestSensorEnvironment.getSensor();
95         return String.format(
96                 "%s: Sampling rate is expected to larger than to %d (Hz)",
97                 sensor.getName(),
98                 CAPPED_SAMPLE_RATE_HZ);
99     }
100 
101     /**
102      * Flip the microphone toggle to off and assert that it is indeed off.
103      */
flipAndAssertMicToggleOff(int userID, SensorPrivacyManager spm)104     public void flipAndAssertMicToggleOff(int userID, SensorPrivacyManager spm) {
105         ShellUtils.runShellCommand("cmd sensor_privacy disable " + userID + " microphone");
106         SystemUtil.runWithShellPermissionIdentity(() -> {
107             Assert.assertTrue("Failed to switch the mic toggle off!",
108                     !spm.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.MICROPHONE));
109         });
110     }
111 
112     /**
113      * Flip the microphone toggle to off and assert that it is indeed on.
114      */
flipAndAssertMicToggleOn(int userID, SensorPrivacyManager spm)115     public void flipAndAssertMicToggleOn(int userID, SensorPrivacyManager spm) {
116         ShellUtils.runShellCommand("cmd sensor_privacy enable " + userID + " microphone");
117         SystemUtil.runWithShellPermissionIdentity(() -> {
118             Assert.assertTrue("Failed to switch the mic toggle on!",
119                     spm.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.MICROPHONE));
120         });
121     }
122 
123     /**
124      * Register a listener and waits until there are numOfEvents events
125      *
126      * @param specifyHandler true if a {@link Handler} is associated with the instance.
127      */
getSensorEvents(boolean specifyHandler, int numOfEvents)128     public List<TestSensorEvent> getSensorEvents(boolean specifyHandler, int numOfEvents)
129             throws InterruptedException {
130         TestSensorEventListener listener = new TestSensorEventListener(mTestSensorEnvironment);
131         CountDownLatch eventLatch = mTestSensorManager.registerListener(
132                 listener,
133                 numOfEvents,
134                 specifyHandler);
135         listener.waitForEvents(eventLatch, numOfEvents, false);
136         List<TestSensorEvent> testSensorEventList = listener.getCollectedEvents();
137         listener.clearEvents();
138         mTestSensorManager.unregisterListener();
139         return testSensorEventList;
140     }
141 }
142