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