1 /*
2  * Copyright (C) 2023 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.connection;
17 
18 import com.android.ddmlib.IDevice;
19 import com.android.tradefed.build.IBuildInfo;
20 import com.android.tradefed.device.IConfigurableVirtualDevice;
21 import com.android.tradefed.device.ITestDevice;
22 import com.android.tradefed.device.ManagedTestDeviceFactory;
23 import com.android.tradefed.device.NativeDevice;
24 import com.android.tradefed.device.NullDevice;
25 import com.android.tradefed.device.RemoteAndroidDevice;
26 import com.android.tradefed.device.TestDeviceOptions.InstanceType;
27 import com.android.tradefed.device.cloud.GceAvdInfo;
28 import com.android.tradefed.device.cloud.RemoteAndroidVirtualDevice;
29 import com.android.tradefed.log.ITestLogger;
30 import com.android.tradefed.log.LogUtil.CLog;
31 import com.android.tradefed.util.IRunUtil;
32 import com.android.tradefed.util.MultiMap;
33 
34 /**
35  * Default connection representation of a device, assumed to be a standard adb connection of the
36  * device.
37  */
38 public class DefaultConnection extends AbstractConnection {
39 
40     private final IRunUtil mRunUtil;
41     private final ITestDevice mDevice;
42     private final IBuildInfo mBuildInfo;
43     private final MultiMap<String, String> mAttributes;
44     private final String mInitialIpDevice;
45     private final String mInitialUser;
46     private final Integer mInitialDeviceNumOffset;
47     private final String mInitialSerial;
48     private final ITestLogger mTestLogger;
49 
50     private final boolean mTemporaryHolder;
51 
createInopConnection(ConnectionBuilder builder)52     public static DefaultConnection createInopConnection(ConnectionBuilder builder) {
53         return new DefaultConnection(builder);
54     }
55 
56     /** Create the requested connection. */
createConnection(ConnectionBuilder builder)57     public static DefaultConnection createConnection(ConnectionBuilder builder) {
58         ITestDevice device = builder.device;
59         if (device == null) {
60             return new DefaultConnection(builder);
61         }
62 
63         final InstanceType type = device.getOptions().getInstanceType();
64         CLog.d("Instance type for connection: %s", type);
65 
66         final boolean isCuttlefish = type.equals(InstanceType.CUTTLEFISH)
67                 || type.equals(InstanceType.REMOTE_NESTED_AVD);
68 
69         if (device instanceof RemoteAndroidVirtualDevice) {
70             ((NativeDevice) device).setFastbootEnabled(isCuttlefish);
71             ((NativeDevice) device).setLogStartDelay(0);
72             return new AdbSshConnection(builder);
73         }
74         if (device instanceof RemoteAndroidDevice) {
75             return new AdbTcpConnection(builder);
76         }
77 
78         CLog.d("Instance type for connection: %s", type);
79         if (isCuttlefish) {
80             if (ManagedTestDeviceFactory.isTcpDeviceSerial(device.getSerialNumber())) {
81                 // TODO: Add support for remote environment
82                 // If the device is already started just go for TcpConnection
83                 return new AdbTcpConnection(builder);
84             } else {
85                 ((NativeDevice) device).setLogStartDelay(0);
86                 return new AdbSshConnection(builder);
87             }
88         }
89 
90         return new DefaultConnection(builder);
91     }
92 
93     /** Builder used to described the connection. */
94     public static class ConnectionBuilder {
95 
96         ITestDevice device;
97         IBuildInfo buildInfo;
98         MultiMap<String, String> attributes;
99         IRunUtil runUtil;
100         ITestLogger logger;
101         GceAvdInfo existingAvdInfo;
102 
ConnectionBuilder( IRunUtil runUtil, ITestDevice device, IBuildInfo buildInfo, ITestLogger logger)103         public ConnectionBuilder(
104                 IRunUtil runUtil, ITestDevice device, IBuildInfo buildInfo, ITestLogger logger) {
105             this.runUtil = runUtil;
106             this.device = device;
107             this.buildInfo = buildInfo;
108             this.logger = logger;
109             attributes = new MultiMap<String, String>();
110         }
111 
addAttributes(MultiMap<String, String> attributes)112         public ConnectionBuilder addAttributes(MultiMap<String, String> attributes) {
113             this.attributes.putAll(attributes);
114             return this;
115         }
116 
setExistingAvdInfo(GceAvdInfo info)117         public ConnectionBuilder setExistingAvdInfo(GceAvdInfo info) {
118             existingAvdInfo = info;
119             return this;
120         }
121     }
122 
123     /** Constructor */
DefaultConnection(ConnectionBuilder builder)124     protected DefaultConnection(ConnectionBuilder builder) {
125         mRunUtil = builder.runUtil;
126         mDevice = builder.device;
127         mBuildInfo = builder.buildInfo;
128         mAttributes = builder.attributes;
129         IDevice idevice = mDevice.getIDevice();
130         mInitialSerial = mDevice.getSerialNumber();
131         mTestLogger = builder.logger;
132         if (idevice instanceof IConfigurableVirtualDevice) {
133             mInitialIpDevice = ((IConfigurableVirtualDevice) idevice).getKnownDeviceIp();
134             mInitialUser = ((IConfigurableVirtualDevice) idevice).getKnownUser();
135             mInitialDeviceNumOffset = ((IConfigurableVirtualDevice) idevice).getDeviceNumOffset();
136         } else {
137             mInitialIpDevice = null;
138             mInitialUser = null;
139             mInitialDeviceNumOffset = null;
140         }
141         if (idevice instanceof NullDevice) {
142             mTemporaryHolder = ((NullDevice) idevice).isTemporary();
143         } else {
144             mTemporaryHolder = false;
145         }
146     }
147 
148     /** Returns {@link IRunUtil} to execute commands. */
getRunUtil()149     protected IRunUtil getRunUtil() {
150         return mRunUtil;
151     }
152 
getDevice()153     public final ITestDevice getDevice() {
154         return mDevice;
155     }
156 
getBuildInfo()157     public final IBuildInfo getBuildInfo() {
158         return mBuildInfo;
159     }
160 
getAttributes()161     public final MultiMap<String, String> getAttributes() {
162         return mAttributes;
163     }
164 
165     /**
166      * Returns the initial associated ip to the device if any. Returns null if no known initial ip.
167      */
getInitialIp()168     public String getInitialIp() {
169         return mInitialIpDevice;
170     }
171 
172     /** Returns the initial known user if any. Returns null if no initial known user. */
getInitialUser()173     public String getInitialUser() {
174         return mInitialUser;
175     }
176 
177     /** Returns the known device num offset if any. Returns null if not available. */
getInitialDeviceNumOffset()178     public Integer getInitialDeviceNumOffset() {
179         return mInitialDeviceNumOffset;
180     }
181 
182     /** Returns the initial serial name of the device. */
getInitialSerial()183     public String getInitialSerial() {
184         return mInitialSerial;
185     }
186 
187     /** Returns the {@link ITestLogger} to log files. */
getLogger()188     public ITestLogger getLogger() {
189         return mTestLogger;
190     }
191 
wasTemporaryHolder()192     public boolean wasTemporaryHolder() {
193         return mTemporaryHolder;
194     }
195 }
196