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.time.cts.host; 18 19 import static android.app.time.cts.shell.DeviceConfigKeys.NAMESPACE_SYSTEM_TIME; 20 21 import static com.google.common.truth.Truth.assertThat; 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import android.app.time.cts.shell.DeviceConfigShellHelper; 25 import android.app.time.cts.shell.DeviceShellCommandExecutor; 26 import android.app.time.cts.shell.LocationShellHelper; 27 import android.app.time.cts.shell.host.HostShellCommandExecutor; 28 import android.app.time.cts.shell.TimeZoneDetectorShellHelper; 29 import android.cts.statsdatom.lib.AtomTestUtils; 30 import android.cts.statsdatom.lib.ConfigUtils; 31 import android.cts.statsdatom.lib.DeviceUtils; 32 import android.cts.statsdatom.lib.ReportUtils; 33 34 import com.android.os.AtomsProto; 35 import com.android.os.AtomsProto.TimeZoneDetectorState.DetectionMode; 36 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 37 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 38 39 import org.junit.After; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 44 import java.util.List; 45 46 /** Host-side CTS tests for the time zone detector service stats logging. */ 47 @RunWith(DeviceJUnit4ClassRunner.class) 48 public class TimeZoneDetectorStatsTest extends BaseHostJUnit4Test { 49 50 private TimeZoneDetectorShellHelper mTimeZoneDetectorShellHelper; 51 private LocationShellHelper mLocationShellHelper; 52 private DeviceConfigShellHelper mDeviceConfigShellHelper; 53 private DeviceConfigShellHelper.PreTestState mDeviceConfigPreTestState; 54 55 @Before setUp()56 public void setUp() throws Exception { 57 DeviceShellCommandExecutor shellCommandExecutor = new HostShellCommandExecutor(getDevice()); 58 mTimeZoneDetectorShellHelper = new TimeZoneDetectorShellHelper(shellCommandExecutor); 59 mLocationShellHelper = new LocationShellHelper(shellCommandExecutor); 60 mDeviceConfigShellHelper = new DeviceConfigShellHelper(shellCommandExecutor); 61 mDeviceConfigPreTestState = mDeviceConfigShellHelper.setSyncModeForTest( 62 DeviceConfigShellHelper.SYNC_DISABLED_MODE_UNTIL_REBOOT, NAMESPACE_SYSTEM_TIME); 63 64 ConfigUtils.removeConfig(getDevice()); 65 ReportUtils.clearReports(getDevice()); 66 } 67 68 @After tearDown()69 public void tearDown() throws Exception { 70 ConfigUtils.removeConfig(getDevice()); 71 ReportUtils.clearReports(getDevice()); 72 mDeviceConfigShellHelper.restoreDeviceConfigStateForTest(mDeviceConfigPreTestState); 73 } 74 75 @Test testAtom_TimeZoneDetectorState()76 public void testAtom_TimeZoneDetectorState() throws Exception { 77 // Enable the atom. 78 ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, 79 AtomsProto.Atom.TIME_ZONE_DETECTOR_STATE_FIELD_NUMBER); 80 Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); 81 82 // This should trigger a pull. 83 AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice()); 84 Thread.sleep(AtomTestUtils.WAIT_TIME_LONG); 85 86 // Extract and assert about TimeZoneDetectorState. 87 List<AtomsProto.Atom> atoms = ReportUtils.getGaugeMetricAtoms(getDevice()); 88 89 boolean found = false; 90 for (AtomsProto.Atom atom : atoms) { 91 if (atom.hasTimeZoneDetectorState()) { 92 AtomsProto.TimeZoneDetectorState state = atom.getTimeZoneDetectorState(); 93 94 // There are a few parts of the pull metric we can check easily via the command 95 // line. Checking more would require adding more commands or something that dumps a 96 // proto. This test provides at least some coverage that the atom is working / 97 // matches actual state. 98 99 // The shell reports the same info the atom does for geo detection supported. 100 boolean geoDetectionSupportedFromShell = 101 mTimeZoneDetectorShellHelper.isGeoDetectionSupported(); 102 assertThat(state.getGeoSupported()).isEqualTo(geoDetectionSupportedFromShell); 103 104 // The shell reports the same info the atom does for location enabled. 105 boolean locationEnabledForCurrentUserFromShell = 106 mLocationShellHelper.isLocationEnabledForCurrentUser(); 107 assertThat(state.getLocationEnabled()) 108 .isEqualTo(locationEnabledForCurrentUserFromShell); 109 110 // The shell reports the user's setting for auto detection. 111 boolean autoDetectionEnabledFromShell = 112 mTimeZoneDetectorShellHelper.isAutoDetectionEnabled(); 113 assertThat(state.getAutoDetectionSetting()) 114 .isEqualTo(autoDetectionEnabledFromShell); 115 116 boolean telephonyDetectionSupportedFromShell = 117 mTimeZoneDetectorShellHelper.isTelephonyDetectionSupported(); 118 boolean noAutoDetectionSupported = 119 !(telephonyDetectionSupportedFromShell || geoDetectionSupportedFromShell); 120 // The atom reports the functional state for "detection mode", which is derived from 121 // device config and settings. This logic basically repeats the logic used on the 122 // device. 123 DetectionMode expectedDetectionMode; 124 if (noAutoDetectionSupported || !autoDetectionEnabledFromShell) { 125 expectedDetectionMode = DetectionMode.MANUAL; 126 } else { 127 boolean geoDetectionSettingEnabledFromShell = 128 mTimeZoneDetectorShellHelper.isGeoDetectionEnabled(); 129 boolean expectedGeoDetectionEnabled = 130 geoDetectionSupportedFromShell 131 && locationEnabledForCurrentUserFromShell 132 && geoDetectionSettingEnabledFromShell; 133 if (expectedGeoDetectionEnabled) { 134 expectedDetectionMode = DetectionMode.GEO; 135 } else { 136 expectedDetectionMode = DetectionMode.TELEPHONY; 137 } 138 } 139 assertThat(state.getDetectionMode()).isEqualTo(expectedDetectionMode); 140 141 found = true; 142 break; 143 } 144 } 145 assertWithMessage("Did not find a matching atom TimeZoneDetectorState") 146 .that(found).isTrue(); 147 } 148 } 149