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 package com.android.tradefed.device.internal; 17 18 import com.android.annotations.VisibleForTesting; 19 import com.android.tradefed.device.DeviceNotAvailableException; 20 import com.android.tradefed.device.ITestDevice; 21 import com.android.tradefed.device.NativeDevice; 22 import com.android.tradefed.device.StubDevice; 23 import com.android.tradefed.error.HarnessRuntimeException; 24 import com.android.tradefed.error.IHarnessException; 25 import com.android.tradefed.invoker.IInvocationContext; 26 import com.android.tradefed.invoker.logger.CurrentInvocation; 27 import com.android.tradefed.invoker.logger.CurrentInvocation.IsolationGrade; 28 import com.android.tradefed.invoker.logger.InvocationMetricLogger; 29 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey; 30 import com.android.tradefed.log.LogUtil.CLog; 31 import com.android.tradefed.result.error.InfraErrorIdentifier; 32 import com.android.tradefed.service.TradefedFeatureClient; 33 import com.android.tradefed.util.SerializationUtil; 34 35 import com.proto.tradefed.feature.FeatureResponse; 36 37 import java.io.IOException; 38 import java.util.HashMap; 39 import java.util.Map; 40 import java.util.regex.Matcher; 41 import java.util.regex.Pattern; 42 43 /** 44 * Utility handling generically device resetting. This is meant to only be used internally to the 45 * test harness. This shouldn't be called during a test. 46 */ 47 public class DeviceResetHandler { 48 49 private final TradefedFeatureClient mClient; 50 private final IInvocationContext mContext; 51 DeviceResetHandler()52 public DeviceResetHandler() { 53 this(new TradefedFeatureClient(), CurrentInvocation.getInvocationContext()); 54 } 55 DeviceResetHandler(IInvocationContext context)56 public DeviceResetHandler(IInvocationContext context) { 57 this(new TradefedFeatureClient(), context); 58 } 59 60 @VisibleForTesting DeviceResetHandler(TradefedFeatureClient client, IInvocationContext context)61 DeviceResetHandler(TradefedFeatureClient client, IInvocationContext context) { 62 mClient = client; 63 mContext = context; 64 } 65 66 /** 67 * Calls reset of the given device. 68 * 69 * @param device The device to reset. 70 * @return True if reset was successful, false otherwise. 71 * @throws DeviceNotAvailableException 72 */ resetDevice(ITestDevice device)73 public boolean resetDevice(ITestDevice device) throws DeviceNotAvailableException { 74 if (device.getIDevice() instanceof StubDevice) { 75 CLog.d("Device '%s' is a stub device. skipping reset.", device.getSerialNumber()); 76 return true; 77 } 78 FeatureResponse response; 79 try { 80 Map<String, String> args = new HashMap<>(); 81 args.put(DeviceResetFeature.DEVICE_NAME, mContext.getDeviceName(device)); 82 response = mClient.triggerFeature(DeviceResetFeature.DEVICE_RESET_FEATURE_NAME, args); 83 CLog.d("Response from reset request: %s", response.getResponse()); 84 } finally { 85 mClient.close(); 86 } 87 if (response.hasErrorInfo()) { 88 String trace = response.getErrorInfo().getErrorTrace(); 89 // Handle if it's an exception error. 90 Object o = null; 91 try { 92 o = SerializationUtil.deserialize(trace); 93 CLog.e("Reset failed: %s", o); 94 } catch (IOException | RuntimeException e) { 95 CLog.e(e); 96 } 97 if (o instanceof DeviceNotAvailableException) { 98 throw (DeviceNotAvailableException) o; 99 } else if (o instanceof IHarnessException) { 100 IHarnessException exception = (IHarnessException) o; 101 throw new HarnessRuntimeException( 102 "Exception while resetting the device.", exception); 103 } else if (o instanceof Exception) { 104 throw new HarnessRuntimeException( 105 "Exception while resetting the device.", 106 (Exception) o, InfraErrorIdentifier.UNDETERMINED); 107 } 108 return false; 109 } 110 if (device instanceof NativeDevice) { 111 ((NativeDevice) device).resetContentProviderSetup(); 112 } 113 CurrentInvocation.setModuleIsolation(IsolationGrade.FULLY_ISOLATED); 114 CurrentInvocation.setRunIsolation(IsolationGrade.FULLY_ISOLATED); 115 116 // Save powerwash performance data 117 Pattern durationPattern = Pattern.compile("Powerwash\\sfinished\\sin (\\d+)\\sms"); 118 Matcher matcher; 119 matcher = durationPattern.matcher(response.getResponse()); 120 if (matcher.find()) { 121 InvocationMetricLogger.addInvocationMetrics(InvocationMetricKey.DEVICE_RESET_COUNT, 1); 122 InvocationMetricLogger.addInvocationMetrics( 123 InvocationMetricKey.DEVICE_POWERWASH_DURATIONS, matcher.group(1)); 124 } 125 return true; 126 } 127 } 128