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