package org.geogebra.web.html5.main; import org.geogebra.common.main.App; import org.geogebra.common.main.ExamEnvironment; import org.geogebra.common.main.Feature; import org.geogebra.common.util.GTimer; import org.geogebra.common.util.GTimerListener; import org.geogebra.common.util.debug.Log; /** * */ public class ExamEnvironmentW extends ExamEnvironment { private App app; private boolean wasAirplaneModeOn, wasWifiEnabled, wasTaskLocked, wasBluetoothEnabled, wasScreenOn; /** * @param app * application */ public ExamEnvironmentW(App app) { super(); this.app = app; } @Override public void setStart(long time) { super.setStart(time); // airplane mode should be on when started wasAirplaneModeOn = true; // wifi should be disabled when started wasWifiEnabled = false; // bluetooth should be disabled when started wasBluetoothEnabled = false; // screen should be on when started wasScreenOn = true; // no cheat at start isCheating = false; if (app.getVersion().isAndroidWebview()) { setJavascriptTargetToExamEnvironment(); exportGeoGebraAndroidMethods(); if (checkLockTaskAvailable()) { // task should locked when started wasTaskLocked = true; watchTaskLock(); } if (app.has(Feature.EXAM_ANDROID_CHECK_SCREEN_STATE)){ watchScreenState(); } } } private GTimer checkTaskLockTimer = null; private void watchTaskLock() { Log.debug("watch task lock"); // set timer to check continuously if task is locked if (checkTaskLockTimer != null && checkTaskLockTimer.isRunning()) { checkTaskLockTimer.stop(); } checkTaskLockTimer = app.newTimer(new GTimerListener() { @Override public void onRun() { if (checkTaskLocked()) { taskLocked(); } else { taskUnlocked(); } } }, 1000); checkTaskLockTimer.startRepeat(); } private GTimer checkScreenState = null; private void watchScreenState() { Log.debug("watch screen state"); // set timer to check continuously screen stated if (checkScreenState != null && checkScreenState.isRunning()) { checkScreenState.stop(); } checkScreenState = app.newTimer(new GTimerListener() { @Override public void onRun() { if (isScreenOff()){ screenOff(); } else { screenOn(); } } }, 1000); checkScreenState.startRepeat(); } /** * @return whether task locking API is available */ public static native boolean checkLockTaskAvailable() /*-{ return $wnd.GeoGebraExamAndroidJsBinder.checkLockTaskAvailable(); }-*/; /** * @return whether task is locked */ public static native boolean checkTaskLocked() /*-{ return $wnd.GeoGebraExamAndroidJsBinder.checkTaskLocked(); }-*/; /** * Lock task over API */ public static native void startLockTask() /*-{ $wnd.GeoGebraExamAndroidJsBinder.startLockTask(); }-*/; /** * @return whether screen is inactive */ public static native boolean isScreenOff() /*-{ return $wnd.GeoGebraExamAndroidJsBinder.isScreenOff(); }-*/; @Override public void exit() { if (app.getVersion().isAndroidWebview()) { // stop timer if necessary if (checkTaskLockTimer != null && checkTaskLockTimer.isRunning()) { checkTaskLockTimer.stop(); } setJavascriptTargetToNone(); } super.exit(); } /** * @return set target to none */ public static native boolean setJavascriptTargetToNone() /*-{ return $wnd.GeoGebraExamAndroidJsBinder.setJavascriptTargetToNone(); }-*/; private static native boolean setJavascriptTargetToExamEnvironment() /*-{ return $wnd.GeoGebraExamAndroidJsBinder .setJavascriptTargetToExamEnvironment(); }-*/; private native void exportGeoGebraAndroidMethods() /*-{ var that = this; $wnd.examEnvironment_airplaneModeTurnedOn = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::airplaneModeTurnedOn()(); }); $wnd.examEnvironment_airplaneModeTurnedOff = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::airplaneModeTurnedOff()(); }); $wnd.examEnvironment_wifiEnabled = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::wifiEnabled()(); }); $wnd.examEnvironment_wifiDisabled = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::wifiDisabled()(); }); $wnd.examEnvironment_bluetoothEnabled = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::bluetoothEnabled()(); }); $wnd.examEnvironment_bluetoothDisabled = $entry(function() { that.@org.geogebra.web.html5.main.ExamEnvironmentW::bluetoothDisabled()(); }); }-*/; /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void airplaneModeTurnedOff() { Log.debug("ExamEnvironmentW: airplane mode turned off"); if (getStart() > 0) { initLists(); if (wasAirplaneModeOn) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.AIRPLANE_MODE_OFF); wasAirplaneModeOn = false; Log.debug("STARTED CHEATING: airplane mode off"); } } } /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void airplaneModeTurnedOn() { Log.debug("ExamEnvironmentW: airplane mode turned on"); if (getStart() > 0) { initLists(); if (!wasAirplaneModeOn) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.AIRPLANE_MODE_ON); wasAirplaneModeOn = true; isCheating = true; Log.debug("STOPPED CHEATING: airplane mode on"); } } } /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void wifiEnabled() { Log.debug("ExamEnvironmentW: wifi enabled"); if (getStart() > 0) { initLists(); if (!wasWifiEnabled) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.WIFI_ENABLED); wasWifiEnabled = true; isCheating = true; Log.debug("STARTED CHEATING: wifi enabled"); } } } /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void wifiDisabled() { Log.debug("ExamEnvironmentW: wifi disabled"); if (getStart() > 0) { initLists(); if (wasWifiEnabled) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.WIFI_DISABLED); wasWifiEnabled = false; Log.debug("STOPPED CHEATING: wifi disabled"); } } } /** * Run this when unlocked task detected; notifies about cheating */ public void taskUnlocked() { if (getStart() > 0) { if (wasTaskLocked) { initLists(); cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.TASK_UNLOCKED); wasTaskLocked = false; isCheating = true; Log.debug("STARTED CHEATING: task unlocked"); } } } /** * If task was previously unlocked, add cheating end to the log */ public void taskLocked() { if (getStart() > 0) { if (!wasTaskLocked) { initLists(); cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.TASK_LOCKED); wasTaskLocked = true; Log.debug("STOPPED CHEATING: task locked"); } } } /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void bluetoothEnabled() { Log.debug("ExamEnvironmentW: bluetooth enabled"); if (getStart() > 0) { initLists(); if (!wasBluetoothEnabled) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.BLUETOOTH_ENABLED); wasBluetoothEnabled = true; isCheating = true; Log.debug("STARTED CHEATING: bluetooth enabled"); } } } /** * this method is called through js (see exportGeoGebraAndroidMethods()) */ public void bluetoothDisabled() { Log.debug("ExamEnvironmentW: bluetooth disabled"); if (getStart() > 0) { initLists(); if (wasBluetoothEnabled) { cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.BLUETOOTH_DISABLED); wasBluetoothEnabled = false; Log.debug("STOPPED CHEATING: bluetooth disabled"); } } } private boolean isCheating; @Override public boolean isCheating() { if (app.has(Feature.EXAM_ANDROID_CHECK_SCREEN_STATE) && app.getVersion().isAndroidWebview()) { return isCheating; } return super.isCheating(); } @Override protected void addCheatingWindowsLeft(long time){ if (app.getVersion().isAndroidWebview()) { if (isScreenOff()) { screenOff(); } } super.addCheatingWindowsLeft(time); } /** * Callback for screen going off */ public void screenOff() { if (getStart() > 0) { if (wasScreenOn) { initLists(); long time = System.currentTimeMillis(); cheatingTimes.add(time); cheatingEvents.add(CheatingEvent.SCREEN_OFF); wasScreenOn = false; Log.debug("screen: off"); } } } /** * Callback for screen going on */ public void screenOn() { if (getStart() > 0) { if (!wasScreenOn) { initLists(); cheatingTimes.add(System.currentTimeMillis()); cheatingEvents.add(CheatingEvent.SCREEN_ON); wasScreenOn = true; Log.debug("screen: on"); } } } }