Skip to content

Commit

Permalink
Update progress bar and time remaining counter behavior
Browse files Browse the repository at this point in the history
- Display total "Time remaining counter" instead of single timer for single test (#487).
- Improve progress bar of tests (#490).
  • Loading branch information
aanorbel authored Feb 23, 2022
1 parent cdca33b commit c92aa8e
Show file tree
Hide file tree
Showing 6 changed files with 437 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@

import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.animation.Animation;
import android.widget.Button;
Expand All @@ -31,8 +27,9 @@
import org.openobservatory.ooniprobe.common.Application;
import org.openobservatory.ooniprobe.common.PreferenceManager;
import org.openobservatory.ooniprobe.common.ReachabilityManager;
import org.openobservatory.ooniprobe.common.TestProgressRepository;
import org.openobservatory.ooniprobe.common.service.RunTestService;
import org.openobservatory.ooniprobe.test.TestAsyncTask;
import org.openobservatory.ooniprobe.receiver.TestRunBroadRequestReceiver;
import org.openobservatory.ooniprobe.test.suite.AbstractSuite;
import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite;

Expand All @@ -46,7 +43,13 @@
import localhost.toolkit.app.fragment.ConfirmDialogFragment;
import localhost.toolkit.app.fragment.MessageDialogFragment;

public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener, ServiceConnection {
/**
* Serves to display progress of {@code RunTestService} running in in the background on a screen.
*
* Also contains {@link #runAsForegroundService(AbstractActivity, ArrayList<AbstractSuite>,OnTestServiceStartedListener) runAsForegroundService}
* used to start {@code RunTestService} in the background.
*/
public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener {
@BindView(R.id.running)
TextView running;
@BindView(R.id.name)
Expand All @@ -65,14 +68,24 @@ public class RunningActivity extends AbstractActivity implements ConfirmDialogFr
LottieAnimationView animation;
@BindView(R.id.proxy_icon)
RelativeLayout proxy_icon;
private Integer runtime;
private RunTestService service;
private TestRunBroadRequestReceiver receiver;
boolean isBound = false;

@Inject
PreferenceManager preferenceManager;
@Inject
TestProgressRepository testProgressRepository;

/**
* Starts {@code RunTestService} in the background.
*
* @param context
* AbstractActivity of caller used in checking if test is already running,show dialog prompts
* as well as argument for ContextCompat#startForegroundService(Context,Intent).
* @param testSuites
* List of test suites to run by {@code RunTestService}
* @param onTestServiceStartedListener
* Listener for successful start of {@code RunTestService}
*/
public static void runAsForegroundService(AbstractActivity context,
ArrayList<AbstractSuite> testSuites,
OnTestServiceStartedListener onTestServiceStartedListener) {
Expand Down Expand Up @@ -119,6 +132,14 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_running);
ButterKnife.bind(this);

testProgressRepository.getProgress().observe(this, progressValue -> {
progress.setProgress(progressValue);
});
testProgressRepository.getEta().observe(this,etaValue -> {
eta.setText(getString(R.string.Dashboard_Running_Seconds,
String.valueOf(Math.round(etaValue))));
});

if (getPreferenceManager().getProxyURL().isEmpty())
proxy_icon.setVisibility(View.GONE);
close.setOnClickListener(new View.OnClickListener() {
Expand All @@ -140,27 +161,39 @@ public void onClick(View view) {
});
}

private void applyUIChanges(){
private void applyUIChanges(RunTestService service) {
if (service == null || service.task == null ||
service.task.currentSuite == null || service.task.currentTest == null) {
return;
}
animation.setImageAssetsFolder("anim/");
animation.setRepeatCount(Animation.INFINITE);
animation.playAnimation();
progress.setIndeterminate(true);
eta.setText(R.string.Dashboard_Running_CalculatingETA);
Integer progressLevel = testProgressRepository.getProgress().getValue();
if (progressLevel != null) {
progress.setProgress(progressLevel);
} else {
progress.setIndeterminate(true);
}

Double etaValue = testProgressRepository.getEta().getValue();
if (etaValue!=null){
eta.setText(getString(R.string.Dashboard_Running_Seconds,
String.valueOf(Math.round(etaValue))));
}else {
eta.setText(R.string.Dashboard_Running_CalculatingETA);
}

if (service.task.currentSuite.getName().equals(ExperimentalSuite.NAME))
name.setText(service.task.currentTest.getName());
else
name.setText(getString(service.task.currentTest.getLabelResId()));
runtime = service.task.currentSuite.getRuntime(preferenceManager);
getWindow().setBackgroundDrawableResource(service.task.currentSuite.getColor());
if (Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(service.task.currentSuite.getColor());
}
animation.setAnimation(service.task.currentSuite.getAnim());
progress.setMax(service.task.currentSuite.getTestList(preferenceManager).length * 100);
progress.setMax(service.task.getMax(preferenceManager));
}

@Override
Expand All @@ -174,19 +207,19 @@ protected void onResume() {
return;
}
IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity");
receiver = new TestRunBroadRequestReceiver();
receiver = new TestRunBroadRequestReceiver(preferenceManager, new TestRunnerEventListener(), testProgressRepository);
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
//Bind the RunTestService
Intent intent = new Intent(this, RunTestService.class);
bindService(intent, this, Context.BIND_AUTO_CREATE);
bindService(intent, receiver, Context.BIND_AUTO_CREATE);
}

@Override
protected void onPause() {
super.onPause();
if (isBound) {
unbindService(this);
isBound = false;
if (receiver.isBound()) {
unbindService(receiver);
receiver.setBound(false);
}
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
Expand All @@ -202,62 +235,6 @@ public void onBackPressed() {
Toast.makeText(this, getString(R.string.Modal_Error_CantCloseScreen), Toast.LENGTH_SHORT).show();
}

@Override
public void onServiceConnected(ComponentName cname, IBinder binder) {
//Bind the service to this activity
RunTestService.TestBinder b = (RunTestService.TestBinder) binder;
service = b.getService();
isBound = true;
applyUIChanges();
}


@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}

public class TestRunBroadRequestReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String key = intent.getStringExtra("key");
String value = intent.getStringExtra("value");
switch (key) {
case TestAsyncTask.START:
applyUIChanges();
break;
case TestAsyncTask.RUN:
name.setText(value);
break;
case TestAsyncTask.PRG:
int prgs = Integer.parseInt(value);
progress.setIndeterminate(false);
progress.setProgress(prgs);
if (runtime != null)
eta.setText(getString(R.string.Dashboard_Running_Seconds,
String.valueOf(Math.round(runtime - ((double) prgs) / progress.getMax() * runtime))));
break;
case TestAsyncTask.LOG:
log.setText(value);
break;
case TestAsyncTask.ERR:
Toast.makeText(context, value, Toast.LENGTH_SHORT).show();
break;
case TestAsyncTask.URL:
progress.setIndeterminate(false);
runtime = service.task.currentSuite.getRuntime(preferenceManager);
break;
case TestAsyncTask.INT:
running.setText(getString(R.string.Dashboard_Running_Stopping_Title));
log.setText(getString(R.string.Dashboard_Running_Stopping_Notice));
break;
case TestAsyncTask.END:
testEnded(context);
break;
}
}
}

private void testEnded(Context context) {
startActivity(MainActivity.newIntent(context, R.id.testResults));
finish();
Expand All @@ -266,13 +243,58 @@ private void testEnded(Context context) {
@Override
public void onConfirmation(Serializable serializable, int i) {
if (i == DialogInterface.BUTTON_POSITIVE) {
if (service != null)
service.task.interrupt();
if (receiver.service != null)
receiver.service.interrupt();
}
}

public interface OnTestServiceStartedListener {
void onTestServiceStarted();
}

private class TestRunnerEventListener implements TestRunBroadRequestReceiver.EventListener {
@Override
public void onStart(RunTestService service) {
applyUIChanges(service);
}

@Override
public void onRun(String value) {
name.setText(value);
}

@Override
public void onProgress(int state, double timeLeft) {
progress.setIndeterminate(false);
progress.setProgress(state);
eta.setText(getString(R.string.Dashboard_Running_Seconds,
String.valueOf(Math.round(timeLeft))));
}

@Override
public void onLog(String value) {
log.setText(value);
}

@Override
public void onError(String value) {
Toast.makeText(RunningActivity.this, value, Toast.LENGTH_SHORT).show();
}

@Override
public void onUrl() {
progress.setIndeterminate(false);
}

@Override
public void onInterrupt() {
running.setText(getString(R.string.Dashboard_Running_Stopping_Title));
log.setText(getString(R.string.Dashboard_Running_Stopping_Notice));
}

@Override
public void onEnd(Context context) {
testEnded(context);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.openobservatory.ooniprobe.common;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
* TestProgressRepository used to track the {@link org.openobservatory.ooniprobe.common.service.RunTestService} progress with using {@link LiveData}
*/
@Singleton
public class TestProgressRepository {
/**
* Instantiates a new {@link TestProgressRepository}
*/
@Inject
TestProgressRepository() {
}

private final MutableLiveData<Integer> progressData = new MutableLiveData<>();
private final MutableLiveData<Double> etaData = new MutableLiveData<>();

/**
* Gets progress.
*
* @return the progress
*/
public LiveData<Integer> getProgress() {
return progressData;
}

/**
* Update progress.
*
* @param progress the progress
*/
public void updateProgress(Integer progress) {
progressData.setValue(progress);
}

/**
* Gets eta.
*
* @return the eta
*/
public LiveData<Double> getEta() {
return etaData;
}

/**
* Update eta.
*
* @param eta the eta
*/
public void updateEta(Double eta) {
etaData.setValue(eta);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,13 @@ public void stopTest(){
}
}

/**
* Interrupt running task by calling TestAsyncTask#interrupt()
*
* @see TestAsyncTask#interrupt()
*/
public synchronized void interrupt() {
task.interrupt();
}

}
Loading

0 comments on commit c92aa8e

Please sign in to comment.