/******************************************************************************* * Copyright 2013-2016 alladin-IT GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package at.alladin.rmbt.android.test; import java.text.DecimalFormat; import java.text.Format; import java.text.MessageFormat; import java.util.List; import java.util.Locale; import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.content.ServiceConnection; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.support.v4.app.Fragment; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import at.alladin.openrmbt.android.R; import at.alladin.rmbt.android.graphview.GraphService; import at.alladin.rmbt.android.graphview.GraphService.GraphData; import at.alladin.rmbt.android.graphview.GraphView; import at.alladin.rmbt.android.main.RMBTMainActivity; import at.alladin.rmbt.android.test.RMBTService.RMBTBinder; import at.alladin.rmbt.android.test.SmoothGraph.SmoothingFunction; import at.alladin.rmbt.android.util.Helperfunctions; import at.alladin.rmbt.android.util.InformationCollector; import at.alladin.rmbt.android.util.net.NetworkUtil; import at.alladin.rmbt.android.util.net.NetworkUtil.MinMax; import at.alladin.rmbt.android.views.GroupCountView; import at.alladin.rmbt.android.views.ProgressView; import at.alladin.rmbt.android.views.ResultGraphView; import at.alladin.rmbt.client.helper.IntermediateResult; import at.alladin.rmbt.client.helper.NdtStatus; import at.alladin.rmbt.client.helper.TestStatus; import at.alladin.rmbt.client.v2.task.QoSTestEnum; public class RMBTTestFragment extends Fragment implements ServiceConnection { private static final String TAG = "RMBTTestFragment"; /** * used for smoothing the speed graph: amount of data needed for smoothing function */ public static final int SMOOTHING_DATA_AMOUNT = 3; // min 3 /** * smoothing function used for speed graph. * BEWARE: different functions could require different data amounts */ public static final SmoothingFunction SMOOTHING_FUNCTION = SmoothingFunction.CENTERED_MOVING_AVARAGE; private static final long UPDATE_DELAY = 100; private static final int SLOW_UPDATE_COUNT = 20; private static final int PROGRESS_SEGMENTS_TOTAL = 132; private static final int PROGRESS_SEGMENTS_INIT = 16; private static final int PROGRESS_SEGMENTS_PING = 17; private static final int PROGRESS_SEGMENTS_DOWN = 33; private static final int PROGRESS_SEGMENTS_UP = 33; private static final int PROGRESS_SEGMENTS_QOS = 33; private static final long GRAPH_MAX_NSECS = 8000000000L; private final Format pingFormat = new DecimalFormat("@@ ms"); private Format speedFormat; private final Format percentFormat = DecimalFormat.getPercentInstance(); private boolean qosMode = false; private Context context; private TestView testView; private GraphView graphView; private GraphService speedGraph; private GraphService signalGraph; private boolean uploadGraph; private boolean graphStarted; private TextView textView; private ViewGroup groupCountContainerView; private ViewGroup qosProgressView; private ViewGroup infoView; private IntermediateResult intermediateResult; private int lastNetworkType; private String lastNetworkTypeString; private Integer lastSignal; private int lastSignalType; private RMBTService rmbtService; private long updateCounter; private String bottomText; private Location lastLocation; private String lastOperatorName; private String lastServerName; private String lastIP; private TestStatus lastStatus; private String lastStatusString; private long lastShownWaitTime = -1; private String waitText; private boolean stopLoop; private Dialog errorDialog; private Dialog abortDialog; private ProgressDialog progressDialog; private boolean showQoSErrorToast = false; private Handler handler; private static final long MAX_COUNTER_WITHOUT_RESULT = 100; GraphData signalGraphData; GraphData speedGraphData; private final Runnable resultSwitcherRunnable = new Runnable() { @Override public void run() { final RMBTMainActivity mainActivity = getMainActivity(); if (mainActivity == null) return; mainActivity.setHistoryDirty(true); mainActivity.checkSettings(true, null); if (getMainActivity() == null) return; if (isVisible()) switchToResult(); } }; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); handler = new Handler(); context = getActivity().getApplicationContext(); bottomText = getResources().getString(R.string.test_bottom_test); waitText = getResources().getString(R.string.test_progress_text_wait); speedFormat = new DecimalFormat(String.format("@@ %s", getActivity().getResources().getString(R.string.test_mbps))); } protected RMBTMainActivity getMainActivity() { return (RMBTMainActivity) getActivity(); } @Override public void onServiceConnected(final ComponentName name, final IBinder service) { Log.d(TAG, "service connected"); final RMBTBinder binder = (RMBTBinder) service; rmbtService = binder.getService(); } @Override public void onServiceDisconnected(final ComponentName name) { Log.d(TAG, "service disconnected"); rmbtService = null; } @Override public void onStop() { super.onStop(); speedGraphData = speedGraph.getGraphData(); signalGraphData = signalGraph.getGraphData(); handler.removeCallbacks(updateTask); handler.removeCallbacks(resultSwitcherRunnable); context.unbindService(this); getActivity().getActionBar().show(); ((RMBTMainActivity) getActivity()).setLockNavigationDrawer(false); //getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @Override public void onStart() { super.onStart(); getActivity().getActionBar().hide(); ((RMBTMainActivity) getActivity()).setLockNavigationDrawer(true); // Bind to RMBTService final Intent serviceIntent = new Intent(context, RMBTService.class); context.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE); handler.post(updateTask); //getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.test, container, false); return createView(view, inflater, savedInstanceState); } /** * * @param view * @param inflater * @return */ private View createView(final View view, final LayoutInflater inflater, final Bundle savedInstanceState) { testView = (TestView) view.findViewById(R.id.test_view); graphView = (GraphView) view.findViewById(R.id.test_graph); infoView = (ViewGroup) view.findViewById(R.id.test_view_info_container); textView = (TextView) view.findViewById(R.id.test_text); qosProgressView = (ViewGroup) view.findViewById(R.id.test_view_qos_container); groupCountContainerView = (ViewGroup) view.findViewById(R.id.test_view_group_count_container); if (savedInstanceState != null) { if (testView != null) { testView.setHeaderString(savedInstanceState.getString("header_string")); testView.setSubHeaderString(savedInstanceState.getString("sub_header_string", testView.getSubHeaderString())); testView.setResultPingString(savedInstanceState.getString("ping_string", testView.getResultPingString())); testView.setResultDownString(savedInstanceState.getString("down_string", testView.getResultDownString())); testView.setResultUpString(savedInstanceState.getString("up_string", testView.getResultUpString())); } if (textView != null) { textView.setText(savedInstanceState.getString("test_info")); } } else { if (textView != null) { textView.setText("\n\n\n"); } } if (graphView != null) { if (speedGraphData == null) { speedGraph = SmoothGraph.addGraph(graphView, Color.parseColor("#00f940"), SMOOTHING_DATA_AMOUNT, SMOOTHING_FUNCTION, false); } else { speedGraph = SmoothGraph.addGraph(graphView, SMOOTHING_DATA_AMOUNT, SMOOTHING_FUNCTION, false, speedGraphData); } speedGraph.setMaxTime(GRAPH_MAX_NSECS); if (signalGraphData == null) { signalGraph = SimpleGraph.addGraph(graphView, Color.parseColor("#f8a000"), GRAPH_MAX_NSECS); } else { signalGraph = SimpleGraph.addGraph(graphView, GRAPH_MAX_NSECS, signalGraphData); } //graphView.getLabelInfoVerticalList().add(new GraphLabel(getActivity().getString(R.string.test_dbm), "#f8a000")); graphView.setRowLinesLabelList(ResultGraphView.SPEED_LABELS); } //uploadGraph = false; graphStarted = false; final Resources res = getActivity().getResources(); final String progressTitle = res.getString(R.string.test_progress_title); final String progressText = res.getString(R.string.test_progress_text); lastShownWaitTime = -1; if (progressDialog == null) { progressDialog = ProgressDialog.show(getActivity(), progressTitle, progressText, true, false); progressDialog.setOnKeyListener(backKeyListener); } return view; } @Override public void onDestroyView() { super.onDestroyView(); if (progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } } @Override public void onDestroy() { super.onDestroy(); if (testView != null) testView.recycle(); if (graphView != null) graphView.recycle(); dismissDialogs(); System.gc(); } @Override public void onDetach() { super.onDetach(); dismissDialogs(); } private void dismissDialogs() { dismissDialog(errorDialog); errorDialog = null; dismissDialog(abortDialog); abortDialog = null; dismissDialog(progressDialog); progressDialog = null; } private static void dismissDialog(Dialog dialog) { if (dialog != null) dialog.dismiss(); } private void resetGraph() { if (signalGraph != null) signalGraph.reset(); if (speedGraph != null) speedGraph.reset(); uploadGraph = false; graphStarted = false; if (graphView != null) graphView.invalidate(); } private final Runnable updateTask = new Runnable() { @Override public void run() { if (getActivity() == null) return; if (qosMode) updateQoSUI(); else updateUI(); if (rmbtService != null) { // System.out.println(rmbtService.isCompleted() + " - " + rmbtService.isConnectionError()); if (rmbtService.isCompleted() && rmbtService.getTestUuid(false) != null) { handler.postDelayed(resultSwitcherRunnable, 300); } } if (!stopLoop) handler.postDelayed(this, UPDATE_DELAY); } }; private final DialogInterface.OnKeyListener backKeyListener = new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) return onBackPressedHandler(); return false; } }; private void updateUI() { String teststatus; updateCounter++; if (rmbtService == null) return; intermediateResult = rmbtService.getIntermediateResult(intermediateResult); if (intermediateResult == null) { if (rmbtService.isConnectionError()) { if (progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } if (! rmbtService.isLoopMode()) { showErrorDialog(R.string.test_dialog_error_control_server_conn); return; } } if (!rmbtService.isTestRunning() && updateCounter > MAX_COUNTER_WITHOUT_RESULT && ! (errorDialog != null && errorDialog.isShowing())) getActivity().getSupportFragmentManager().popBackStack(); // leave return; } if (intermediateResult.status == TestStatus.WAIT) { if (progressDialog != null) { long wait = (intermediateResult.remainingWait + 999) / 1000; // round // up if (wait < 0) wait = 0; if (wait != lastShownWaitTime) { lastShownWaitTime = wait; progressDialog.setMessage(MessageFormat.format(waitText, wait)); } } return; } if (progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } boolean forceUpdate = false; if (rmbtService.getNdtStatus() == NdtStatus.RUNNING) { final String ndtStatus = String.format(Locale.US, "NDT (%d%%)", Math.round(rmbtService.getNDTProgress() * 100)); if (lastStatusString == null || !ndtStatus.equals(lastStatusString)) { forceUpdate = true; lastStatusString = ndtStatus; } } else if (lastStatus != intermediateResult.status) { lastStatus = intermediateResult.status; lastStatusString = Helperfunctions.getTestStatusString(getResources(), intermediateResult.status); forceUpdate = true; } if (updateCounter % SLOW_UPDATE_COUNT == 0 || forceUpdate) { final int networkType = rmbtService.getNetworkType(); if (lastNetworkType != networkType && networkType != 0) { lastNetworkType = networkType; lastNetworkTypeString = Helperfunctions.getNetworkTypeName(networkType); } final String operatorName = rmbtService.getOperatorName(); if (operatorName != null) lastOperatorName = operatorName; testView.setHeaderString(lastOperatorName); testView.setSubHeaderString(lastNetworkTypeString); final String serverName = rmbtService.getServerName(); if (serverName != null) lastServerName = serverName; if (lastServerName == null) lastServerName = "?"; final Location location = rmbtService.getLocation(); if (location != null && !location.equals(lastLocation)) lastLocation = location; final String locationStr_line1; final String locationStr_line2; if (lastLocation != null) { locationStr_line1 = Helperfunctions.getLocationString(context, getResources(), lastLocation,1); locationStr_line2 = Helperfunctions.getLocationString(context, getResources(), lastLocation,2); } else { locationStr_line1 = ""; locationStr_line2 = ""; } final String ip = rmbtService.getIP(); if (ip != null) lastIP = ip; if (lastIP == null) lastIP = "?"; teststatus = lastStatusString; textView.setText(MessageFormat.format(bottomText, teststatus, lastServerName, lastIP, locationStr_line1, locationStr_line2)); } Integer signal = rmbtService.getSignal(); int signalType = rmbtService.getSignalType(); if (signal == null || signal == 0) signalType = InformationCollector.SINGAL_TYPE_NO_SIGNAL; boolean signalTypeChanged = false; if (signalType != InformationCollector.SINGAL_TYPE_NO_SIGNAL) { signalTypeChanged = lastSignalType != signalType; lastSignal = signal; lastSignalType = signalType; } if (signalType == InformationCollector.SINGAL_TYPE_NO_SIGNAL && lastSignalType != InformationCollector.SINGAL_TYPE_NO_SIGNAL) { // keep old signal if we had one before signal = lastSignal; signalType = lastSignalType; } Double relativeSignal = null; MinMax<Integer> signalBounds = NetworkUtil.getSignalStrengthBounds(signalType); if (! (signalBounds.min == Integer.MIN_VALUE || signalBounds.max == Integer.MAX_VALUE)) relativeSignal = (double)(signal - signalBounds.min) / (double)(signalBounds.max - signalBounds.min); if (signalTypeChanged && graphView != null) { if (signalGraph != null) signalGraph.clearGraphDontResetTime(); if (relativeSignal != null) graphView.setSignalRange(signalBounds.min, signalBounds.max); else graphView.removeSignalRange(); graphView.invalidate(); } double speedValueRelative = 0d; int progressSegments = 0; switch (intermediateResult.status) { case WAIT: textView.setText("UDP progress: " + intermediateResult.progress); break; case INIT: progressSegments = Math.round(PROGRESS_SEGMENTS_INIT * intermediateResult.progress); if (graphStarted) resetGraph(); break; case PING: progressSegments = PROGRESS_SEGMENTS_INIT + Math.round(PROGRESS_SEGMENTS_PING * intermediateResult.progress); break; case DOWN: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + Math.round(PROGRESS_SEGMENTS_DOWN * intermediateResult.progress); speedValueRelative = intermediateResult.downBitPerSecLog; if (graphView != null) { if (uploadGraph) resetGraph(); if (graphStarted || speedValueRelative != 0) { graphStarted = true; speedGraph.addValue(speedValueRelative, SmoothGraph.FLAG_USE_CURRENT_NODE_TIME); if (relativeSignal != null) signalGraph.addValue(relativeSignal); graphView.invalidate(); } } break; case INIT_UP: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN; speedValueRelative = intermediateResult.downBitPerSecLog; break; case UP: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + Math.round(PROGRESS_SEGMENTS_UP * intermediateResult.progress); speedValueRelative = intermediateResult.upBitPerSecLog; if (graphView != null) { if (!uploadGraph) { resetGraph(); uploadGraph = true; } if (graphStarted || speedValueRelative != 0) { graphStarted = true; speedGraph.addValue(speedValueRelative, SmoothGraph.FLAG_USE_CURRENT_NODE_TIME); if (relativeSignal != null) signalGraph.addValue(relativeSignal); graphView.invalidate(); } } break; case SPEEDTEST_END: case QOS_TEST_RUNNING: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP; speedValueRelative = intermediateResult.upBitPerSecLog; qosMode = true; break; case ERROR: case ABORTED: progressSegments = 0; resetGraph(); if (! rmbtService.isLoopMode()) showErrorDialog(R.string.test_dialog_error_text); return; } testView.setSpeedValue(speedValueRelative); testView.setSignalType(signalType); if (signal != null) testView.setSignalString(String.valueOf(signal)); if (relativeSignal != null) testView.setSignalValue(relativeSignal); final double progressValue = (double) progressSegments / PROGRESS_SEGMENTS_TOTAL; final double correctProgressValue = testView.setProgressValue(progressValue); testView.setProgressString(percentFormat.format(correctProgressValue)); final String pingStr; if (intermediateResult.pingNano < 0) pingStr = "–"; else pingStr = pingFormat.format(intermediateResult.pingNano / 1000000.0); testView.setResultPingString(pingStr); final String downStr; if (intermediateResult.downBitPerSec < 0) downStr = "–"; else downStr = speedFormat.format(intermediateResult.downBitPerSec / 1000000.0); testView.setResultDownString(downStr); final String upStr; if (intermediateResult.upBitPerSec < 0) upStr = "–"; else upStr = speedFormat.format(intermediateResult.upBitPerSec / 1000000.0); testView.setResultUpString(upStr); testView.setTestStatus(intermediateResult.status); testView.invalidate(); } public boolean onBackPressed() { if (rmbtService == null || !rmbtService.isTestRunning()) return false; return onBackPressedHandler(); } public boolean onBackPressedHandler() { Log.d("RMBTTestFragment", "onbackpressed"); final RMBTMainActivity activity = (RMBTMainActivity) getActivity(); if (activity == null) return false; if ((errorDialog != null && errorDialog.isShowing()) || (progressDialog != null && progressDialog.isShowing())) { if (rmbtService != null) rmbtService.stopTest(RMBTService.BROADCAST_TEST_ABORTED); else { // to be sure test is stopped: final Intent service = new Intent(RMBTService.ACTION_ABORT_TEST, null, context, RMBTService.class); context.startService(service); } dismissDialogs(); activity.getSupportFragmentManager().popBackStack(); return true; } if (abortDialog != null && abortDialog.isShowing()) { dismissDialog(abortDialog); abortDialog = null; } else { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.test_dialog_abort_title); builder.setMessage(R.string.test_dialog_abort_text); builder.setPositiveButton(R.string.test_dialog_abort_yes, new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { if (rmbtService != null) rmbtService.stopTest(RMBTService.BROADCAST_TEST_ABORTED); getActivity().getSupportFragmentManager().popBackStack(); } }); builder.setNegativeButton(R.string.test_dialog_abort_no, null); dismissDialogs(); abortDialog = builder.show(); } return true; } protected void showErrorDialog(int errorMessageId) { stopLoop = true; final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.test_dialog_error_title); builder.setMessage(errorMessageId); builder.setNeutralButton(android.R.string.ok, null); dismissDialogs(); errorDialog = builder.create(); errorDialog.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { final RMBTMainActivity activity = (RMBTMainActivity) getActivity(); if (activity != null) activity.getSupportFragmentManager().popBackStack(); } }); errorDialog.show(); } private void switchToResult() { if (!isVisible()) { return; } if (showQoSErrorToast) { final Toast toast = Toast.makeText(getActivity(), R.string.test_toast_error_text_qos, Toast.LENGTH_LONG); toast.show(); } dismissDialogs(); final String testUuid = rmbtService == null ? null : rmbtService.getTestUuid(true); if (testUuid == null) { showErrorDialog(R.string.test_dialog_error_text); return; } ((RMBTMainActivity) getActivity()).showResultsAfterTest(testUuid); } private ProgressView extendedProgressView; private Button extendedResultButtonCancel; private Button extendedButtonDetails; private QoSTestEnum lastQoSTestStatus; public void updateQoSUI() { if (progressDialog != null) { progressDialog.dismiss(); progressDialog = null; } QoSTestEnum status = null; float progress = 0f; try { if (rmbtService != null) { QoSTestEnum _status = rmbtService.getQoSTestStatus(); if (_status == null) { _status = lastQoSTestStatus == null ? QoSTestEnum.START : lastQoSTestStatus; } status = _status; lastQoSTestStatus = status; progress = rmbtService.getQoSTestProgress(); } else { // Log.d(DEBUG_TAG, "we have no service"); QoSTestEnum _status = lastQoSTestStatus; if (_status == null) _status = QoSTestEnum.START; if (_status == QoSTestEnum.QOS_RUNNING) _status = QoSTestEnum.STOP; status = _status; } // Log.d(" DEBUG TEST", String.format("status: %s", status == null ? "null" : status.toString())); switch (status) { case START: case ERROR: progress = 0f; break; case STOP: progress = 1f; break; } double progressSegments = 0; if (extendedProgressView != null) { extendedProgressView.setProgress((progress/rmbtService.getQoSTestSize())); } switch (status) { case START: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP + Math.round(PROGRESS_SEGMENTS_QOS * (progress / rmbtService.getQoSTestSize())); break; case QOS_RUNNING: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP + Math.round(PROGRESS_SEGMENTS_QOS * (float)(progress / rmbtService.getQoSTestSize())); break; case QOS_FINISHED: progressSegments = PROGRESS_SEGMENTS_TOTAL - 1; break; case NDT_RUNNING: progressSegments = PROGRESS_SEGMENTS_TOTAL - 1; break; case STOP: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP + PROGRESS_SEGMENTS_QOS; break; case ERROR: default: break; } final double progressValue = (double) progressSegments / PROGRESS_SEGMENTS_TOTAL; Integer signal = rmbtService.getSignal(); int signalType = rmbtService.getSignalType(); if (signal == null || signal == 0) signalType = InformationCollector.SINGAL_TYPE_NO_SIGNAL; if (signalType != InformationCollector.SINGAL_TYPE_NO_SIGNAL) { lastSignal = signal; lastSignalType = signalType; } if (signalType == InformationCollector.SINGAL_TYPE_NO_SIGNAL && lastSignalType != InformationCollector.SINGAL_TYPE_NO_SIGNAL) { // keep old signal if we had one before signal = lastSignal; signalType = lastSignalType; } Double relativeSignal = null; MinMax<Integer> signalBoungs = NetworkUtil.getSignalStrengthBounds(signalType); if (! (signalBoungs.min == Integer.MIN_VALUE || signalBoungs.max == Integer.MAX_VALUE)) relativeSignal = (double)(signal - signalBoungs.min) / (double)(signalBoungs.max - signalBoungs.min); testView.setSignalType(signalType); if (signal != null) testView.setSignalString(String.valueOf(signal)); if (relativeSignal != null) testView.setSignalValue(relativeSignal); final double correctProgressValue = testView.setProgressValue(progressValue); testView.setProgressString(percentFormat.format(correctProgressValue)); testView.invalidate(); if (status == QoSTestEnum.QOS_RUNNING && extendedResultButtonCancel != null && extendedResultButtonCancel.getVisibility() == View.GONE) { extendedResultButtonCancel.setVisibility(View.VISIBLE); if (extendedButtonDetails != null) extendedButtonDetails.setVisibility(View.GONE); } if (qosProgressView != null && qosProgressView.getVisibility()!=View.VISIBLE && rmbtService != null && rmbtService.getQoSTest() != null) { final GroupCountView groupCountView = new GroupCountView(getMainActivity()); qosProgressView.setVisibility(View.VISIBLE); //register group counter view as a test progress listener: rmbtService.getQoSTest().getTestSettings().addTestProgressListener(groupCountView); groupCountView.setTaskMap(rmbtService.getQoSTest().getTestMap()); groupCountContainerView.addView(groupCountView); groupCountContainerView.invalidate(); ((GroupCountView) groupCountContainerView.getChildAt(0)).setNdtProgress(rmbtService.getNDTProgress()); if (graphView != null) { graphView.setVisibility(View.GONE); } if (infoView != null) { infoView.setVisibility(View.GONE); } } else if (qosProgressView != null && qosProgressView.getVisibility()==View.VISIBLE && rmbtService.getQoSGroupCounterMap() != null) { ((GroupCountView) groupCountContainerView.getChildAt(0)).setTaskMap(rmbtService.getQoSTest().getTestMap()); ((GroupCountView) groupCountContainerView.getChildAt(0)).setNdtProgress(rmbtService.getNDTProgress()); ((GroupCountView) groupCountContainerView.getChildAt(0)).setQoSTestStatus(rmbtService.getQoSTestStatus()); ((GroupCountView) groupCountContainerView.getChildAt(0)).updateView(rmbtService.getQoSGroupCounterMap()); } } catch (Exception e) { e.printStackTrace(); } finally { if (status != null && status == QoSTestEnum.ERROR) showQoSErrorToast = true; } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (testView != null) { outState.putString("header_string", testView.getHeaderString()); outState.putString("sub_header_string", testView.getSubHeaderString()); outState.putString("ping_string", testView.getResultPingString()); outState.putString("down_string", testView.getResultDownString()); outState.putString("up_string", testView.getResultUpString()); } if (textView != null) { outState.putString("test_info", textView.getText().toString()); } } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); LayoutInflater inflater = LayoutInflater.from(getActivity()); populateViewForOrientation(inflater, (ViewGroup) getView()); } private final String OPTION_ON_CREATE_VIEW_CREATE_SPEED_GRAPH = "create_speed_graph"; private final String OPTION_ON_CREATE_VIEW_CREATE_SIGNAL_GRAPH = "create_signal_graph"; /** * * @param inflater * @param view */ private void populateViewForOrientation(final LayoutInflater inflater, final ViewGroup view) { System.out.println("RECREATING INSTANCE FOR ORIENTATION CHANGE"); GroupCountView groupCountView = null; if (groupCountContainerView != null && groupCountContainerView.getChildAt(0) != null) { groupCountView = (GroupCountView) groupCountContainerView.getChildAt(0); groupCountContainerView.removeAllViews(); } final String infoText = String.valueOf(textView.getText()); final String header = testView.getHeaderString(); final String subHeader = testView.getSubHeaderString(); final String resultPing = testView.getResultPingString(); final String resultDown = testView.getResultDownString(); final String resultUp = testView.getResultUpString(); final GraphData signalGraphData; final GraphData speedGraphData; final MinMax<Integer> currentSignalBounds; final List<GraphView.GraphLabel> graphLabelList; if (graphView != null) { graphLabelList = graphView.getLabelInfoVerticalList(); currentSignalBounds = graphView.getSignalRange(); } else { graphLabelList = null; currentSignalBounds = null; } if (signalGraph != null) { signalGraphData = signalGraph.getGraphData(); } else { signalGraphData = null; } if (speedGraph != null) { speedGraphData = speedGraph.getGraphData(); } else { speedGraphData = null; } view.removeAllViewsInLayout(); final View v = inflater.inflate(R.layout.test, view); final Bundle options = new Bundle(); options.putBoolean(OPTION_ON_CREATE_VIEW_CREATE_SIGNAL_GRAPH, false); options.putBoolean(OPTION_ON_CREATE_VIEW_CREATE_SPEED_GRAPH, false); createView(v, inflater, options); if (groupCountContainerView != null && groupCountView != null && qosProgressView != null) { groupCountContainerView.addView(groupCountView); qosProgressView.setVisibility(View.VISIBLE); //groupCountContainerView.setVisibility(View.VISIBLE); if (graphView != null) { graphView.setVisibility(View.GONE); } if (infoView != null) { infoView.setVisibility(View.GONE); } } if (testView != null) { testView.setHeaderString(header); testView.setSubHeaderString(subHeader); testView.setResultPingString(resultPing); testView.setResultDownString(resultDown); testView.setResultUpString(resultUp); } if (textView != null) { textView.setText(infoText); } if (graphView != null) { graphView.setRowLinesLabelList(ResultGraphView.SPEED_LABELS); if (signalGraphData != null) { signalGraph = SimpleGraph.addGraph(graphView, GRAPH_MAX_NSECS, signalGraphData); if (currentSignalBounds != null) { graphView.setLabelInfoVerticalList(graphLabelList); graphView.setSignalRange(currentSignalBounds.min, currentSignalBounds.max); } } if (speedGraphData != null) { speedGraph = SmoothGraph.addGraph(graphView, SMOOTHING_DATA_AMOUNT, SMOOTHING_FUNCTION, false, speedGraphData); speedGraph.setMaxTime(GRAPH_MAX_NSECS); } } } public static double calculateProgress(IntermediateResult result, final float qosTestProgress, final int qosTestSize) { double progressSegments = 0; switch (result.status) { case WAIT: break; case INIT: progressSegments = Math.round(PROGRESS_SEGMENTS_INIT * result.progress); break; case PING: progressSegments = PROGRESS_SEGMENTS_INIT + Math.round(PROGRESS_SEGMENTS_PING * result.progress); break; case DOWN: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + Math.round(PROGRESS_SEGMENTS_DOWN * result.progress); break; case INIT_UP: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN; break; case UP: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + Math.round(PROGRESS_SEGMENTS_UP * result.progress); break; case SPEEDTEST_END: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP; break; case QOS_TEST_RUNNING: progressSegments = PROGRESS_SEGMENTS_INIT + PROGRESS_SEGMENTS_PING + PROGRESS_SEGMENTS_DOWN + PROGRESS_SEGMENTS_UP + Math.round((PROGRESS_SEGMENTS_QOS-1) * (float)(qosTestProgress / qosTestSize)); break; case QOS_END: progressSegments = PROGRESS_SEGMENTS_TOTAL - 1; break; case ERROR: case ABORTED: progressSegments = 0; break; default: break; } return (progressSegments / (double)PROGRESS_SEGMENTS_TOTAL); } }