1 /* 2 * Copyright (C) 2015 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 package com.android.compatibility.common.tradefed.targetprep; 17 18 import static com.android.tradefed.targetprep.UserHelper.RUN_TESTS_AS_USER_KEY; 19 20 import com.android.tradefed.config.Option; 21 import com.android.tradefed.config.OptionClass; 22 import com.android.tradefed.device.DeviceNotAvailableException; 23 import com.android.tradefed.device.ITestDevice; 24 import com.android.tradefed.invoker.TestInformation; 25 import com.android.tradefed.log.LogUtil.CLog; 26 import com.android.tradefed.result.error.DeviceErrorIdentifier; 27 import com.android.tradefed.targetprep.BuildError; 28 import com.android.tradefed.targetprep.TargetSetupError; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * Checks that a given setting on the device is one of the given values 35 */ 36 @OptionClass(alias="settings-preparer") 37 public class SettingsPreparer extends PreconditionPreparer { 38 39 public enum SettingType { 40 SECURE, 41 GLOBAL, 42 SYSTEM; 43 } 44 45 /* This option must be defined, but is not explicitly marked mandatory, as subclasses of 46 * the SettingsPreparer class can define mSettingName at runtime */ 47 @Option(name = "device-setting", description = "The setting on the device to be checked") 48 protected String mSettingName = null; 49 50 /* This option must be defined, but is not explicitly marked mandatory, as subclasses of 51 * the SettingsPreparer class can define mSettingType at runtime */ 52 @Option(name = "setting-type", 53 description = "If the setting is 'secure', 'global', or 'system'") 54 protected SettingType mSettingType = null; 55 56 @Option(name = "set-value", description = "The value to be set for the setting") 57 protected String mSetValue = null; 58 59 @Option(name = "expected-values", description = "The set of expected values of the setting") 60 protected List<String> mExpectedSettingValues = new ArrayList<String>(); 61 62 @Option(name = "failure-message", description = "The text printed for an unexpected value") 63 protected String mFailureMessage = null; 64 65 @Override run(TestInformation testInfo)66 public void run(TestInformation testInfo) 67 throws TargetSetupError, BuildError, DeviceNotAvailableException { 68 ITestDevice device = testInfo.getDevice(); 69 if (mSettingName == null) { 70 throw new TargetSetupError("The \"device-setting\" option must be defined for the " + 71 "SettingsPreparer class", device.getDeviceDescriptor()); 72 } 73 74 if (mSettingType == null) { 75 throw new TargetSetupError("The \"setting-type\" option must be defined for the " + 76 "SettingsPreparer class", device.getDeviceDescriptor()); 77 } 78 79 /* At least one of the options "set-value" and "expected-values" must be set */ 80 if (mSetValue == null && mExpectedSettingValues.isEmpty()) { 81 throw new TargetSetupError("At least one of the options \"set-value\" and " + 82 "\"expected-values\" must be set", device.getDeviceDescriptor()); 83 } 84 85 String testUser = testInfo.properties().get(RUN_TESTS_AS_USER_KEY); 86 String userArg = " "; 87 if (testUser != null && !testUser.isEmpty() && mSettingType != SettingType.GLOBAL) { 88 userArg = String.format(" --user %s ", testUser); 89 } 90 91 String shellCmdGet = 92 !mExpectedSettingValues.isEmpty() 93 ? String.format("settings get %s%s%s", mSettingType, userArg, mSettingName) 94 : ""; 95 String shellCmdPut = 96 (mSetValue != null) 97 ? String.format( 98 "settings put %s%s%s %s", 99 mSettingType, userArg, mSettingName, mSetValue) 100 : ""; 101 102 /* Case 1: Both expected-values and set-value are given */ 103 if (mSetValue != null && !mExpectedSettingValues.isEmpty()) { 104 // first ensure that the set-value given can be found in expected-values 105 if (!mExpectedSettingValues.contains(mSetValue)) { 106 throw new TargetSetupError( 107 String.format( 108 "set-value for %s is %s, but value not found in expected-values:" 109 + " %s", 110 mSettingName, mSetValue, mExpectedSettingValues.toString()), 111 device.getDeviceDescriptor(), 112 DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE); 113 } 114 String currentSettingValue = device.executeShellCommand(shellCmdGet).trim(); 115 // only change unexpected setting value 116 if (!mExpectedSettingValues.contains(currentSettingValue)) { 117 CLog.d("Changing value for %s from %s to %s", 118 mSettingName, currentSettingValue, mSetValue); 119 device.executeShellCommand(shellCmdPut); 120 } 121 return; 122 } 123 124 /* Case 2: Only set-value given */ 125 if (mSetValue != null) { 126 CLog.d("Setting %s to value %s", mSettingName, mSetValue); 127 device.executeShellCommand(shellCmdPut); 128 return; 129 } 130 131 /* Case 3: Only expected-values given */ 132 String currentSettingValue = device.executeShellCommand(shellCmdGet).trim(); 133 if (!mExpectedSettingValues.contains(currentSettingValue)) { 134 if (mFailureMessage == null) { 135 mFailureMessage = String.format( 136 "Device setting \"%s\" returned \"%s\", not found in %s", 137 mSettingName, currentSettingValue, mExpectedSettingValues.toString()); 138 } 139 throw new TargetSetupError( 140 mFailureMessage, 141 device.getDeviceDescriptor(), 142 DeviceErrorIdentifier.DEVICE_UNEXPECTED_RESPONSE); 143 } 144 } 145 146 } 147