package io.selendroid.standalone.server.handler;
import io.netty.handler.codec.http.HttpMethod;
import io.selendroid.standalone.server.BaseSelendroidStandaloneHandler;
import org.json.JSONException;
import org.json.JSONObject;
import io.selendroid.server.common.Response;
import io.selendroid.server.common.SelendroidResponse;
import io.selendroid.server.common.http.HttpRequest;
import io.selendroid.standalone.android.AndroidDevice;
import io.selendroid.standalone.android.KeyEvent;
import io.selendroid.standalone.android.impl.DefaultAndroidEmulator;
import io.selendroid.standalone.server.model.ActiveSession;
import io.selendroid.standalone.server.util.HttpClientUtil;
import java.util.logging.Level;
import java.util.logging.Logger;
public class NetworkConnectionHandler extends BaseSelendroidStandaloneHandler {
private static final Logger log = Logger.getLogger(NetworkConnectionHandler.class.getName());
public NetworkConnectionHandler(String mappedUri) {
super(mappedUri);
}
@Override
public Response handleRequest(HttpRequest request, JSONObject payload) throws JSONException {
// Currently we only support changing the Airplane Mode setting
// so we're going to only look at that bit of the ConnectionType.
// check that we actually want to toggle the setting by getting the current airplane mode setting
String sessionId = getSessionId(request);
ActiveSession session = getActiveSession(request);
// the URL happens to be the same, except we need to use GET instead of POST
String url = "http://localhost:" + session.getSelendroidServerPort() + request.uri();
Integer connectionType = getPayload(request).getJSONObject("parameters").getInt("type");
try {
JSONObject r = HttpClientUtil.parseJsonResponse(HttpClientUtil.executeRequest(url, HttpMethod.GET));
// Airplane mode is the first bit, so even is disabled, odd is disabled
if (r.getInt("value") % 2 == connectionType % 2) {
// airplane modes are the same
return new SelendroidResponse(sessionId, null);
}
} catch (Exception e) {
log.log(Level.SEVERE, "Cannot change network connection", e);
return new SelendroidResponse(sessionId, null);
}
Boolean airplaneMode = connectionType % 2 == 1;
AndroidDevice device = getSelendroidDriver(request).getActiveSession(getSessionId(request)).getDevice();
int deviceAPILevel = Integer.parseInt(device.getTargetPlatform().getApi());
device.invokeActivity("android.settings.AIRPLANE_MODE_SETTINGS");
// tap to make sure none of the selections are currently highlighted
device.runAdbCommand("shell input tap 600 100");
device.inputKeyevent(KeyEvent.KEYCODE_DPAD_DOWN);
device.inputKeyevent(KeyEvent.KEYCODE_DPAD_CENTER);
if (airplaneMode) {
// adb connection needs a recycle when switching airplane mode on
device.restartADB();
// killing the server kills all the tcp forwards, need to re-establish them.
for (ActiveSession activeSession : getSelendroidDriver(request).getActiveSessions()) {
device.forwardPort(activeSession.getSelendroidServerPort(), activeSession.getSelendroidServerPort());
}
} else if (deviceAPILevel == 17 && device instanceof DefaultAndroidEmulator) {
// data doesn't automatically get re-enabled when toggling it back on
device.runAdbCommand("shell svc data disable");
device.runAdbCommand("shell svc data enable");
}
// nice and magical, this will 'close' the settings view and reopen the last application, the one under test! :)
if (deviceAPILevel >= 21) {
//click default back button 3 times to get back to the app under test. app > Settings > Network Settings
device.inputKeyevent(KeyEvent.KEYCODE_BACK);
device.inputKeyevent(KeyEvent.KEYCODE_BACK);
device.inputKeyevent(KeyEvent.KEYCODE_BACK);
} else {
//click back button at the top of the Network Settings Activity
device.inputKeyevent(KeyEvent.KEYCODE_DPAD_UP);
device.inputKeyevent(KeyEvent.KEYCODE_DPAD_CENTER);
}
// airplane mode is 1, Data + WIFI is 6
return new SelendroidResponse(sessionId, airplaneMode ? 1 : 6);
}
}