From 1359032f187fad1dae0f0538630b9cd251dfc137 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Sep 2019 10:11:54 +0800 Subject: [PATCH 01/66] Started the implementation of automatic testing --- app/build.gradle | 6 +++--- app/src/main/res/drawable/automated_testing.xml | 13 +++++++++++++ app/src/main/res/values/untraslatable.xml | 3 +++ app/src/main/res/xml/preferences_global.xml | 9 +++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/drawable/automated_testing.xml diff --git a/app/build.gradle b/app/build.gradle index 130f396f5..1c66ae722 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId 'org.openobservatory.ooniprobe' minSdkVersion 17 targetSdkVersion 28 - versionName '2.2.0-beta.1' - versionCode 50 + versionName '2.3.0-alpha.1' + versionCode 52 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -43,7 +43,7 @@ android { } dependencies { - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0' fullImplementation 'com.google.firebase:firebase-messaging:20.0.0' fullImplementation 'com.google.firebase:firebase-core:17.2.0' diff --git a/app/src/main/res/drawable/automated_testing.xml b/app/src/main/res/drawable/automated_testing.xml new file mode 100644 index 000000000..47c5d039a --- /dev/null +++ b/app/src/main/res/drawable/automated_testing.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index 497e2118f..2c4618934 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -5,6 +5,7 @@ 30 preferences notifications + automated_testing sharing advanced send_email @@ -12,6 +13,8 @@ notifications_enabled notifications_completion notifications_news + automated_testing_enabled + upload_results upload_results_manual include_ip diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 2679269bf..7c2dede8d 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -20,6 +20,15 @@ android:key="@string/notifications_news" android:title="@string/Settings_Notifications_OnNews" /> --> + + + Date: Tue, 24 Mar 2020 12:31:28 +0100 Subject: [PATCH 02/66] Update strings.xml --- app/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 96e32f609..26e7a67a0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -389,4 +389,6 @@ Benign or innocuous content used for control Intergovernmental organizations including The United Nations Sites that haven\'t been categorized yet + Automated Testing + Run test automatically From 7a88e74b9135a342f2850c9fcb6f164c1450d0e6 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 25 Mar 2020 20:05:18 +0100 Subject: [PATCH 03/66] Added preference --- app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/values/untraslatable.xml | 2 +- app/src/main/res/xml/preferences_global.xml | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 26e7a67a0..9ca8b3d7e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -391,4 +391,6 @@ Sites that haven\'t been categorized yet Automated Testing Run test automatically + Time + Time to run tests diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index adef122ab..6ad4bd40b 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -19,7 +19,7 @@ notifications_completion notifications_news automated_testing_enabled - + automated_testing_enabled_time upload_results upload_results_manual include_ip diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 4d7036c66..cd2e7a9c8 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -28,6 +28,11 @@ android:defaultValue="false" android:key="@string/automated_testing_enabled" android:title="@string/Settings_AutomatedTesting_RunAutomatically" /> + Date: Thu, 26 Mar 2020 09:41:31 +0100 Subject: [PATCH 04/66] Adding time preference --- .../ooniprobe/common/PreferenceManager.java | 11 +++++ .../fragment/PreferenceFragment.java | 42 +++++++++++++++++++ app/src/main/res/values/untraslatable.xml | 2 +- app/src/main/res/xml/preferences_global.xml | 4 +- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java index 19c03df9c..a99045289 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java @@ -54,6 +54,17 @@ public Integer getMaxRuntime() { } } + public String getAutomatedTestingTime() { + try { + String local_notifications_time = sp.getString(r.getString(R.string.automated_testing_time), "18:00"); + String[] separated = local_notifications_time.split(":"); + int hours = Integer.valueOf(separated[0]); + int minutes = Integer.valueOf(separated[1]); + return String.format("%02d", hours) + ":" +String.format("%02d", minutes); + } catch (Exception e) { + return "18:00"; + } + } public boolean isMaxRuntimeEnabled(){ return sp.getBoolean(r.getString(R.string.max_runtime_enabled), true); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java index c9a15567e..7bcffb4a6 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java @@ -1,5 +1,7 @@ package org.openobservatory.ooniprobe.fragment; +import android.annotation.TargetApi; +import android.app.TimePickerDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -7,6 +9,7 @@ import android.os.Build; import android.os.Bundle; import android.text.TextUtils; +import android.widget.TimePicker; import android.widget.Toast; import androidx.annotation.IdRes; @@ -24,6 +27,9 @@ import org.openobservatory.ooniprobe.common.Application; import java.io.Serializable; +import java.text.NumberFormat; +import java.util.Calendar; +import java.util.Locale; import localhost.toolkit.app.fragment.ConfirmDialogFragment; import localhost.toolkit.app.fragment.MessageDialogFragment; @@ -48,12 +54,47 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { this.rootKey = rootKey; } + private void showDateDialog(Preference timePreference) { + Calendar mcurrentTime = Calendar.getInstance(); + int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY); + int minute = mcurrentTime.get(Calendar.MINUTE); + TimePickerDialog mTimePicker; + mTimePicker = new TimePickerDialog(getActivity(), new TimePickerDialog.OnTimeSetListener() { + @Override + public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) { + Locale en_locale = new Locale("en","EN"); + NumberFormat nf = NumberFormat.getInstance(en_locale); + int hour = Integer.parseInt(nf.format(selectedHour)); + int minute = Integer.parseInt(nf.format(selectedMinute)); + String time = String.format(en_locale, "%02d", hour) + ":" + String.format(en_locale, "%02d", minute); + SharedPreferences.Editor editor = getPreferenceScreen().getSharedPreferences().edit(); + editor.putString(getActivity().getString(R.string.automated_testing_time), time); + editor.commit(); + timePreference.setSummary(String.format("%02d", selectedHour) + ":" + String.format("%02d", selectedMinute)); + //NotificationHandler.setRecurringAlarm(mActivity.getApplicationContext()); + } + }, hour, minute, true); + mTimePicker.show(); + } + @Override public void onResume() { assert getArguments() != null; super.onResume(); setPreferencesFromResource(getArguments().getInt(ARG_PREFERENCES_RES_ID), getArguments().getInt(ARG_CONTAINER_RES_ID), getArguments().getString(ARG_PREFERENCE_ROOT)); + Preference timePreference = (Preference) findPreference(getActivity().getString(R.string.automated_testing_time)); + String time = ((Application) getActivity().getApplication()).getPreferenceManager().getAutomatedTestingTime(); + timePreference.setSummary(time); + timePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @Override + public boolean onPreferenceClick(Preference preference) { + showDateDialog(timePreference); + return false; + } + }); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); getActivity().setTitle(getPreferenceScreen().getTitle()); for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { @@ -136,6 +177,7 @@ else if (preference instanceof EditTextPreference) { p.setChecked(true); } } + //TODO handle set and unset alarm when enabling automated_testing_enabled } @Override diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index 6ad4bd40b..db23d6588 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -19,7 +19,7 @@ notifications_completion notifications_news automated_testing_enabled - automated_testing_enabled_time + automated_testing_time upload_results upload_results_manual include_ip diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index cd2e7a9c8..cf090d33f 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -28,10 +28,10 @@ android:defaultValue="false" android:key="@string/automated_testing_enabled" android:title="@string/Settings_AutomatedTesting_RunAutomatically" /> - Date: Thu, 26 Mar 2020 11:55:41 +0100 Subject: [PATCH 05/66] First raw implementation of alarm service --- app/src/main/AndroidManifest.xml | 14 +++++ .../ooniprobe/common/alarm/AlarmReceiver.java | 43 ++++++++++++++ .../ooniprobe/common/alarm/AlarmService.java | 57 +++++++++++++++++++ .../common/alarm/OnBootReceiver.java | 25 ++++++++ .../fragment/PreferenceFragment.java | 15 +++-- 5 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/OnBootReceiver.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d7f1ddc4e..046dc9c9b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -132,5 +132,19 @@ android:scheme="ooni" /> + + + + + + diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java new file mode 100644 index 000000000..a04631b39 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -0,0 +1,43 @@ +package org.openobservatory.ooniprobe.common.alarm; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import org.openobservatory.ooniprobe.common.NotificationService; + + +public class AlarmReceiver extends BroadcastReceiver { + + private static final String DEBUG_TAG = "AlarmReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + System.out.println(DEBUG_TAG); + //NotificationService.sendNotification(context, "", null); + + /* + String[] testArray = { + OONITests.WEB_CONNECTIVITY, + OONITests.HTTP_HEADER_FIELD_MANIPULATION, + OONITests.HTTP_INVALID_REQUEST_LINE, + OONITests.WHATSAPP, + OONITests.TELEGRAM, + OONITests.FACEBOOK_MESSENGER + }; + for (int i=0; i Date: Thu, 26 Mar 2020 12:47:22 +0100 Subject: [PATCH 06/66] Commented code --- .../ooniprobe/common/alarm/AlarmReceiver.java | 11 +++++++++++ .../ooniprobe/common/alarm/AlarmService.java | 3 --- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index a04631b39..7d90da5ba 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -4,7 +4,10 @@ import android.content.Context; import android.content.Intent; +import org.openobservatory.ooniprobe.activity.AbstractActivity; +import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.NotificationService; +import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; public class AlarmReceiver extends BroadcastReceiver { @@ -15,6 +18,14 @@ public class AlarmReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { System.out.println(DEBUG_TAG); //NotificationService.sendNotification(context, "", null); + /* + WebsitesSuite suite = new WebsitesSuite(); + Intent act = RunningActivity.newIntent((AbstractActivity) context, suite); + if (act != null) { + context.startActivity(act); + } + */ + /* String[] testArray = { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java index b07506b70..f0ba5fb17 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java @@ -38,9 +38,6 @@ public static void setRecurringAlarm(Context context) { Context.ALARM_SERVICE); alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, recurringAlarm); - /*alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, - updateTime.getTimeInMillis(), - AlarmManager.INTERVAL_DAY, recurringAlarm);*/ } public static void cancelRecurringAlarm(Context context) { From 60dec5837deb5ee85563351ac0accc66cd687393 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 27 Mar 2020 09:43:43 +0100 Subject: [PATCH 07/66] Start RunningActivity from background --- .../ooniprobe/activity/RunningActivity.java | 4 ++++ .../ooniprobe/common/alarm/AlarmReceiver.java | 15 ++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index e594b5926..a9dc30b18 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -60,6 +60,10 @@ public static Intent newIntent(AbstractActivity context, AbstractSuite testSuite return new Intent(context, RunningActivity.class).putExtra(TEST, testSuite); } + public static Intent newIntent(Context context, AbstractSuite testSuite) { + return new Intent(context, RunningActivity.class).putExtra(TEST, testSuite); + } + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 7d90da5ba..fb909a099 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -19,13 +19,18 @@ public void onReceive(Context context, Intent intent) { System.out.println(DEBUG_TAG); //NotificationService.sendNotification(context, "", null); /* - WebsitesSuite suite = new WebsitesSuite(); - Intent act = RunningActivity.newIntent((AbstractActivity) context, suite); - if (act != null) { - context.startActivity(act); - } + Two strategies + - Start running activity + - Start silent test + This second approach ahs two problems: + - TestAsyncTaskImpl extends TestAsyncTask so I need to refactor all the code to run tests + - If a test is running and the user opens the app he could potentially run another test and mess up */ + WebsitesSuite suite = new WebsitesSuite(); + Intent i = RunningActivity.newIntent(context, suite); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); /* String[] testArray = { From 42f086e0483bafaa04b65fadcefa1f5be3577770 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 27 Mar 2020 10:16:21 +0100 Subject: [PATCH 08/66] How to backgroun an activity --- .../openobservatory/ooniprobe/activity/RunningActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index a9dc30b18..965e44244 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -67,6 +67,9 @@ public static Intent newIntent(Context context, AbstractSuite testSuite) { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + //With this cunction we can move the activity to the background + //https://stackoverflow.com/questions/10008879/intent-to-start-activity-but-dont-bring-to-front + //moveTaskToBack(true); testSuite = (AbstractSuite) getIntent().getSerializableExtra(TEST); runtime = testSuite.getRuntime(getPreferenceManager()); setTheme(testSuite.getThemeDark()); From a2f4fc424fcfcedd00f8e6207bad3f7ba73acc86 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 1 Apr 2020 22:55:34 +0200 Subject: [PATCH 09/66] Clean code --- .../ooniprobe/common/alarm/AlarmReceiver.java | 41 +------------------ .../ooniprobe/common/alarm/AlarmService.java | 6 --- .../common/alarm/OnBootReceiver.java | 3 -- 3 files changed, 2 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index fb909a099..8a84841a6 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -4,56 +4,19 @@ import android.content.Context; import android.content.Intent; -import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; -import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; - public class AlarmReceiver extends BroadcastReceiver { - - private static final String DEBUG_TAG = "AlarmReceiver"; - @Override public void onReceive(Context context, Intent intent) { - System.out.println(DEBUG_TAG); + //TODO send notification before the test //NotificationService.sendNotification(context, "", null); - /* - Two strategies - - Start running activity - - Start silent test - This second approach ahs two problems: - - TestAsyncTaskImpl extends TestAsyncTask so I need to refactor all the code to run tests - - If a test is running and the user opens the app he could potentially run another test and mess up - */ + //TODO run more than one test WebsitesSuite suite = new WebsitesSuite(); Intent i = RunningActivity.newIntent(context, suite); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); - - /* - String[] testArray = { - OONITests.WEB_CONNECTIVITY, - OONITests.HTTP_HEADER_FIELD_MANIPULATION, - OONITests.HTTP_INVALID_REQUEST_LINE, - OONITests.WHATSAPP, - OONITests.TELEGRAM, - OONITests.FACEBOOK_MESSENGER - }; - for (int i=0; i Date: Thu, 2 Apr 2020 09:52:07 +0200 Subject: [PATCH 10/66] Send activity to background --- .../ooniprobe/activity/RunningActivity.java | 11 +++++++++-- .../ooniprobe/common/alarm/AlarmReceiver.java | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 965e44244..47da9cd5f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -35,6 +35,8 @@ public class RunningActivity extends AbstractActivity { private static final String TEST = "test"; + private static final String BACKGROUND_TASK = "background"; + @BindView(R.id.name) TextView name; @BindView(R.id.log) @@ -64,12 +66,17 @@ public static Intent newIntent(Context context, AbstractSuite testSuite) { return new Intent(context, RunningActivity.class).putExtra(TEST, testSuite); } + public static Intent newBackgroundIntent(Context context, AbstractSuite testSuite) { + return newIntent(context, testSuite).putExtra("background", true); + } + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //With this cunction we can move the activity to the background + //With this function we can move the activity to the background //https://stackoverflow.com/questions/10008879/intent-to-start-activity-but-dont-bring-to-front - //moveTaskToBack(true); + if (getIntent().getBooleanExtra(BACKGROUND_TASK, false)) + moveTaskToBack(true); testSuite = (AbstractSuite) getIntent().getSerializableExtra(TEST); runtime = testSuite.getRuntime(getPreferenceManager()); setTheme(testSuite.getThemeDark()); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 8a84841a6..456a37a1b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -15,7 +15,7 @@ public void onReceive(Context context, Intent intent) { //TODO run more than one test WebsitesSuite suite = new WebsitesSuite(); - Intent i = RunningActivity.newIntent(context, suite); + Intent i = RunningActivity.newBackgroundIntent(context, suite); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } From 5bdbeeb32bdabf8f77ec8dcb241bc00464e4498a Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 2 Apr 2020 10:16:22 +0200 Subject: [PATCH 11/66] Always send the local notification --- .../ooniprobe/activity/RunningActivity.java | 2 +- .../ooniprobe/common/PreferenceManager.java | 10 +++++++ .../fragment/PreferenceFragment.java | 28 ++++++++++--------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 47da9cd5f..85b7869c1 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -155,7 +155,7 @@ protected void onPostExecute(Void aVoid) { RunningActivity act = ref.get(); if (act != null && !act.isFinishing()) { if (act.background) { - if(act.getPreferenceManager().isNotificationsCompletion()) { + if(act.getPreferenceManager().isNotificationsCompletionTest()) { NotificationService.notifyTestEnded(act, act.testSuite); } } else diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java index a99045289..6f7be2ff6 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java @@ -89,6 +89,16 @@ private boolean isNotifications() { return sp.getBoolean(r.getString(R.string.notifications_enabled), true); } + //TODO how to handle local vs remote notifications? + /* + - Fdroid can't enable remote but they might to want to use local notifications + - Split the two settings + */ + public boolean isNotificationsCompletionTest() { + return sp.getBoolean(r.getString(R.string.notifications_completion), true); + } + + //Old function dependent from notifications_enabled public boolean isNotificationsCompletion() { return isNotifications() && sp.getBoolean(r.getString(R.string.notifications_completion), true); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java index cff1fb6cb..b9b24e4d5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java @@ -84,21 +84,23 @@ public void onResume() { assert getArguments() != null; super.onResume(); setPreferencesFromResource(getArguments().getInt(ARG_PREFERENCES_RES_ID), getArguments().getInt(ARG_CONTAINER_RES_ID), getArguments().getString(ARG_PREFERENCE_ROOT)); - - Preference timePreference = (Preference) findPreference(getActivity().getString(R.string.automated_testing_time)); - String time = ((Application) getActivity().getApplication()).getPreferenceManager().getAutomatedTestingTime(); - timePreference.setSummary(time); - timePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - @Override - public boolean onPreferenceClick(Preference preference) { - showDateDialog(timePreference); - return false; - } - }); - getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); getActivity().setTitle(getPreferenceScreen().getTitle()); + + Preference timePreference = findPreference(getActivity().getString(R.string.automated_testing_time)); + if (timePreference != null){ + String time = ((Application) getActivity().getApplication()).getPreferenceManager().getAutomatedTestingTime(); + timePreference.setSummary(time); + timePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + @Override + public boolean onPreferenceClick(Preference preference) { + showDateDialog(timePreference); + return false; + } + }); + } + for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { if (getPreferenceScreen().getPreference(i) instanceof EditTextPreference) { EditTextPreference editTextPreference = (EditTextPreference) getPreferenceScreen().getPreference(i); From 9801ac5060527c12d9f12b3148d0b300c64ebe55 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 3 Apr 2020 11:11:31 +0200 Subject: [PATCH 12/66] versionCode --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index bbbe8e59f..427deb8f9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId 'org.openobservatory.ooniprobe' minSdkVersion 17 targetSdkVersion 29 - versionName '2.3.2' - versionCode 59 + versionName '2.3.2-automated_testing' + versionCode 60 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From a5e05050fa644ded4027b6e4ede3729f6b1cd872 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 3 Apr 2020 12:01:28 +0200 Subject: [PATCH 13/66] Change software_name --- app/src/main/res/values/untraslatable.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index d779324a3..843f75830 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -1,6 +1,6 @@ "" - ooniprobe-android + ooniprobe-android-autotest ooniprobe: %1$s\nmeasurement-kit: %2$s 30 preferences From 16af9f9747681b070be550aa9c3ece40c4d48db2 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 3 Apr 2020 12:07:48 +0200 Subject: [PATCH 14/66] Update build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 427deb8f9..695c4d8e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { applicationId 'org.openobservatory.ooniprobe' minSdkVersion 17 targetSdkVersion 29 - versionName '2.3.2-automated_testing' + versionName '20200403-12' versionCode 60 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } From 10100b964ec4d1269dc5518f34e235874a26b987 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 9 Apr 2020 11:13:59 +0200 Subject: [PATCH 15/66] Update build.gradle --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9b09ab762..e305b3a4c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { applicationId 'org.openobservatory.ooniprobe' minSdkVersion 17 targetSdkVersion 29 - versionName '20200403-12' + versionName '2.3.2' versionCode 60 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField 'String', 'OONI_ORCHESTRATE_BASE_URL', '"https://orchestrate.ooni.io/"' From bce0aadf882512dced728e3beb1784c2ace35cc6 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 16 Apr 2020 10:48:04 +0200 Subject: [PATCH 16/66] Update preferences_global.xml --- app/src/fdroid/res/xml/preferences_global.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index 58c3d43a7..b7d6184e8 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -1,6 +1,20 @@ + + + + Date: Mon, 11 May 2020 15:53:41 +0200 Subject: [PATCH 17/66] Adapting code --- .../ooniprobe/activity/RunningActivity.java | 10 ++++++---- .../ooniprobe/common/alarm/AlarmReceiver.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 208cef943..fe7459fbd 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -1,5 +1,6 @@ package org.openobservatory.ooniprobe.activity; +import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; @@ -58,12 +59,13 @@ public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { + return new Intent(context, RunningActivity.class).putExtra(TEST, testSuites); } - public static Intent newBackgroundIntent(Context context, AbstractSuite testSuite) { - return newIntent(context, testSuite).putExtra("background", true); + public static Intent newBackgroundIntent(Context context, ArrayList testSuites) { + return newIntent(context, testSuites).putExtra("background", true); } @Override diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 456a37a1b..3a71fd19f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -4,18 +4,22 @@ import android.content.Context; import android.content.Intent; +import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; +import org.openobservatory.ooniprobe.test.TestAsyncTask; +import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import java.util.ArrayList; + public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //TODO send notification before the test //NotificationService.sendNotification(context, "", null); - - //TODO run more than one test - WebsitesSuite suite = new WebsitesSuite(); - Intent i = RunningActivity.newBackgroundIntent(context, suite); + ArrayList testSuites = new ArrayList<>(); + testSuites.addAll(TestAsyncTask.SUITES); + Intent i = RunningActivity.newBackgroundIntent(context, testSuites); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } From 30611042de282d27d71611a576e0151a59548bc3 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Tue, 19 May 2020 16:15:25 +0200 Subject: [PATCH 18/66] Update PreferenceFragment.java --- .../ooniprobe/fragment/PreferenceFragment.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java index 4b7278db4..3362ca133 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java @@ -192,12 +192,5 @@ private void checkAtLeastOneEnabled(SharedPreferences sharedPreferences, String protected PreferenceFragment newConcreteInstance(String rootKey) { return PreferenceFragment.newInstance(getArguments().getInt(ARG_PREFERENCES_RES_ID), getArguments().getInt(ARG_CONTAINER_RES_ID), rootKey); } - - @Override - public void onConfirmation(Serializable serializable, int i) { - if (i == DialogInterface.BUTTON_NEGATIVE && serializable.equals(getString(R.string.include_cc))) { - getPreferenceScreen().getSharedPreferences().edit().remove((String) serializable).apply(); - getFragmentManager().beginTransaction().replace(android.R.id.content, newConcreteInstance(rootKey)).commit(); - } - } + } From 9d4c4259bd7fef22b485e664759d0489a4f4b324 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 20 May 2020 15:25:19 +0200 Subject: [PATCH 19/66] Solve intent crash --- .../openobservatory/ooniprobe/activity/RunningActivity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index fe7459fbd..044e1e376 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -59,9 +59,10 @@ public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { - return new Intent(context, RunningActivity.class).putExtra(TEST, testSuites); + Bundle extra = new Bundle(); + extra.putSerializable(TEST, testSuites); + return new Intent(context, RunningActivity.class).putExtra(TEST, extra); } public static Intent newBackgroundIntent(Context context, ArrayList testSuites) { @@ -80,6 +81,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { setContentView(R.layout.activity_running); ButterKnife.bind(this); Bundle extra = getIntent().getBundleExtra(TEST); + //if (extra != null) testSuites = (ArrayList) extra.getSerializable(TEST); if (testSuites == null) { finish(); From 2b9f518dc8151d08f4ee2c2cd0a04231c0a8c17c Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 25 Jun 2020 11:41:09 +0200 Subject: [PATCH 20/66] Default values (revert this commit in the future) --- app/src/fdroid/res/xml/preferences_global.xml | 6 +++--- .../ooniprobe/common/alarm/OnBootReceiver.java | 3 ++- app/src/main/res/xml/preferences_global.xml | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index 358f72d08..99e10fef9 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -6,11 +6,11 @@ android:key="@string/automated_testing" android:title="@string/Settings_AutomatedTesting_Label"> @@ -236,7 +236,7 @@ android:title="@string/CategoryCode_MILX_Name" /> @@ -236,7 +236,7 @@ android:title="@string/CategoryCode_MILX_Name" /> Date: Fri, 26 Jun 2020 16:29:15 +0200 Subject: [PATCH 21/66] Update PreferenceManager.java --- .../openobservatory/ooniprobe/common/PreferenceManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java index 12e963254..402d37ed6 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java @@ -56,13 +56,13 @@ public Integer getMaxRuntime() { public String getAutomatedTestingTime() { try { - String local_notifications_time = sp.getString(r.getString(R.string.automated_testing_time), "18:00"); + String local_notifications_time = sp.getString(r.getString(R.string.automated_testing_time), "05:00"); String[] separated = local_notifications_time.split(":"); int hours = Integer.valueOf(separated[0]); int minutes = Integer.valueOf(separated[1]); return String.format("%02d", hours) + ":" +String.format("%02d", minutes); } catch (Exception e) { - return "18:00"; + return "05:00"; } } public boolean isMaxRuntimeEnabled(){ From ce1416d8882beca59d121a65b61831731ba5d085 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 12 Aug 2020 10:44:46 +0200 Subject: [PATCH 22/66] Update PreferenceFragment.java --- .../ooniprobe/fragment/PreferenceFragment.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java index d8b4a355e..eac9faf7d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java @@ -2,7 +2,6 @@ import android.annotation.TargetApi; import android.app.TimePickerDialog; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -27,7 +26,6 @@ import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.alarm.AlarmService; -import java.io.Serializable; import java.text.NumberFormat; import java.util.Calendar; import java.util.Locale; @@ -143,12 +141,13 @@ public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragme public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Preference preference = findPreference(key); - if (key.equals(getString(R.string.automated_testing_enabled))){ - if(sharedPreferences.getBoolean(key, false)) + if (key.equals(getString(R.string.automated_testing_enabled))) { + if (sharedPreferences.getBoolean(key, false)) //Enabling the alarm every time the user enabled automated_testing AlarmService.setRecurringAlarm(getActivity().getApplication()); else AlarmService.cancelRecurringAlarm(getActivity().getApplication()); + } if (key.equals(getString(R.string.send_crash)) || key.equals(getString(R.string.send_analytics)) || key.equals(getString(R.string.notifications_enabled))){ From 19d62011d95c63fb5fb126c694c451deb9f59e95 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 14 Oct 2020 14:18:22 +0100 Subject: [PATCH 23/66] Update strings.xml --- app/src/main/res/values/strings.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1ca32f9fd..5f26fcecb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -441,7 +441,4 @@ Benign or innocuous content used for control Intergovernmental organizations including The United Nations Sites that haven\'t been categorized yet - Automated Testing - Run test automatically - Time From 4446a18555a86031bde2442e568fbabf5845f36e Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 14 Oct 2020 14:27:06 +0100 Subject: [PATCH 24/66] Update RunningActivity.java --- .../openobservatory/ooniprobe/activity/RunningActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index a10eafa89..7d5820a99 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -1,6 +1,7 @@ package org.openobservatory.ooniprobe.activity; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.os.Build; import android.os.Bundle; @@ -36,6 +37,8 @@ public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { private static final String TEST = "test"; private static final String BACKGROUND_TASK = "background"; + @BindView(R.id.running) + TextView running; @BindView(R.id.name) TextView name; @BindView(R.id.log) From 43064567ecab5ffefefc956da9099b2510bcb558 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 16 Oct 2020 11:16:08 +0100 Subject: [PATCH 25/66] Adding preferences --- app/src/fdroid/res/xml/preferences_global.xml | 17 ++++++++++++++++- .../ooniprobe/common/PreferenceManager.java | 18 ++++++++++++++++++ .../ooniprobe/common/alarm/OnBootReceiver.java | 3 +-- app/src/main/res/values/untraslatable.xml | 3 +++ app/src/main/res/xml/preferences_global.xml | 17 ++++++++++++++++- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index 2a076828b..6bac0da8f 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -6,7 +6,7 @@ android:key="@string/automated_testing" android:title="@string/Settings_AutomatedTesting_Label"> + + + notifications_news automated_testing_enabled automated_testing_time + automated_testing_wifionly + automated_testing_max_runtime_enabled + automated_testing_max_runtime upload_results upload_results_manual include_ip diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 47db687df..89b5fe388 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -16,7 +16,7 @@ android:key="@string/automated_testing" android:title="@string/Settings_AutomatedTesting_Label"> + + + Date: Fri, 16 Oct 2020 11:16:18 +0100 Subject: [PATCH 26/66] New alarm service --- .../ooniprobe/common/NotificationService.java | 10 +++++ .../ooniprobe/common/alarm/AlarmReceiver.java | 38 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index bb75c563c..2310c0145 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -29,6 +29,16 @@ public static void initNotification(Application app){ NotificationService.setToken(app); } + public static void notifyTestStarted(Context c, AbstractSuite testSuite) { + setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); + sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Dashboard_Running_Running)); + } + + public static void notifyTestError(Context c, AbstractSuite testSuite) { + setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); + sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Modal_Error)); + } + public static void notifyTestEnded(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Notification_FinishedRunning)); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 3a71fd19f..1af12cf5a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -3,24 +3,50 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.util.Log; -import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; -import org.openobservatory.ooniprobe.test.TestAsyncTask; +import org.openobservatory.ooniprobe.common.Application; +import org.openobservatory.ooniprobe.common.NotificationService; +import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.common.ReachabilityManager; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import org.openobservatory.ooniprobe.test.test.AbstractTest; +import org.openobservatory.ooniprobe.test.test.WebConnectivity; import java.util.ArrayList; +import java.util.Arrays; public class AlarmReceiver extends BroadcastReceiver { + private static final String TAG = "alarm-receiver"; + @Override public void onReceive(Context context, Intent intent) { - //TODO send notification before the test - //NotificationService.sendNotification(context, "", null); - ArrayList testSuites = new ArrayList<>(); - testSuites.addAll(TestAsyncTask.SUITES); + Application app = ((Application)context.getApplicationContext()); + PreferenceManager pm = app.getPreferenceManager(); + AbstractSuite websitesSuite = new WebsitesSuite(); + AbstractTest webConnectivity = new WebConnectivity(); + + //Abort test in case the user is not connected to WiFi + if (pm.testWifiOnly() && + !ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.WIFI)) { + Log.d(TAG, "is wifi only and not wifi, aborting"); + NotificationService.notifyTestError(context, websitesSuite); + return; + } + + //TODO log stuff in countly + webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); + websitesSuite.setTestList(webConnectivity); + ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); Intent i = RunningActivity.newBackgroundIntent(context, testSuites); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + Log.d(TAG, "starting test"); + + //Send notification before the test starts + NotificationService.notifyTestStarted(context, websitesSuite); + context.startActivity(i); } } \ No newline at end of file From 1e544890c6ef84932c6b0be7b63224056f79a447 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 19 Oct 2020 12:04:10 +0100 Subject: [PATCH 27/66] Trying refactor TestAsync --- .../ooniprobe/activity/RunningActivity.java | 2 +- .../ooniprobe/common/alarm/AlarmReceiver.java | 62 ++++++++++++++++++- .../ooniprobe/test/TestAsyncTask.java | 26 +++++--- 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 7d5820a99..b6152795d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.os.Build; import android.os.Bundle; -import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.widget.ImageButton; @@ -18,6 +17,7 @@ import com.airbnb.lottie.LottieAnimationView; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ReachabilityManager; import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.model.database.Result; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 1af12cf5a..bf7acecea 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -5,11 +5,19 @@ import android.content.Intent; import android.util.Log; +import com.google.gson.Gson; + +import org.openobservatory.engine.Engine; +import org.openobservatory.engine.OONIMKTask; import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ReachabilityManager; +import org.openobservatory.ooniprobe.model.jsonresult.EventResult; +import org.openobservatory.ooniprobe.model.jsonresult.JsonResult; +import org.openobservatory.ooniprobe.model.settings.Settings; +import org.openobservatory.ooniprobe.test.TestAsyncTask; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; import org.openobservatory.ooniprobe.test.test.AbstractTest; @@ -17,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "alarm-receiver"; @@ -40,13 +49,60 @@ public void onReceive(Context context, Intent intent) { webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); websitesSuite.setTestList(webConnectivity); ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); - Intent i = RunningActivity.newBackgroundIntent(context, testSuites); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + //Intent i = RunningActivity.newBackgroundIntent(context, testSuites); + //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Log.d(TAG, "starting test"); //Send notification before the test starts NotificationService.notifyTestStarted(context, websitesSuite); + //runWebConnectivity(context, app); + //context.startActivity(i); + TestAsyncTask task = (TestAsyncTask) new TestAsyncTask(app, websitesSuite.getResult()).execute(websitesSuite.getTestList(pm)); + + } - context.startActivity(i); + public void runWebConnectivity(Context c, Application a) { + boolean submitted = false; + String report_id_1 = "r1"; + String report_id_2 = "r2"; + OONIMKTask task = null; + Settings settings = new Settings(c, a.getPreferenceManager()); + Gson gson = a.getGson(); + settings.name = "WebConnectivity"; + settings.inputs = Collections.singletonList("http://mail.google.com"); + settings.options.max_runtime = 10; + settings.annotations.origin = TAG; + settings.options.no_collector = false; + try { + task = Engine.startExperimentTask(settings.toExperimentSettings(gson, c)); + } catch (Exception exc) { + } + while (!task.isDone()){ + try { + String json = task.waitForNextEvent(); + Log.d(TAG, json); + EventResult event = gson.fromJson(json, EventResult.class); + switch (event.key) { + case "status.report_create": + report_id_1 = event.value.report_id; + break; + case "measurement": + JsonResult jr = gson.fromJson(event.value.json_str, JsonResult.class); + report_id_2 = jr.report_id; + break; + case "failure.report_create": + case "failure.measurement_submission": + case "failure.startup": + break; + case "status.measurement_submission": + submitted = true; + break; + default: + break; + } + } catch (Exception ignored) { + } + } } + } \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 97a265405..2bc518f42 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -1,11 +1,13 @@ package org.openobservatory.ooniprobe.test; +import android.content.Context; import android.os.AsyncTask; import org.openobservatory.engine.Engine; import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.AbstractActivity; +import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ExceptionManager; import org.openobservatory.ooniprobe.model.api.UrlList; import org.openobservatory.ooniprobe.model.database.Result; @@ -34,12 +36,22 @@ public class TestAsyncTask extends AsyncTask ref; + protected final Application app; private final Result result; private AbstractTest currentTest; private boolean interrupt; protected TestAsyncTask(ACT activity, Result result) { this.ref = new WeakReference<>(activity); + this.app = (Application) activity.getApplication(); + this.result = result; + result.is_viewed = false; + result.save(); + } + + public TestAsyncTask(Application app, Result result) { + this.ref = null; + this.app = app; this.result = result; result.is_viewed = false; result.save(); @@ -47,7 +59,7 @@ protected TestAsyncTask(ACT activity, Result result) { @Override protected Void doInBackground(AbstractTest... tests) { ACT act = ref.get(); - if (act != null && !act.isFinishing()) + if (app != null) try { boolean downloadUrls = false; for (AbstractTest abstractTest : tests) @@ -59,7 +71,7 @@ protected TestAsyncTask(ACT activity, Result result) { String probeCC = "XX"; try { probeCC = Engine.resolveProbeCC( - act, + app, BuildConfig.SOFTWARE_NAME, BuildConfig.VERSION_NAME, 30 @@ -69,26 +81,26 @@ protected TestAsyncTask(ACT activity, Result result) { e.printStackTrace(); ExceptionManager.logException(e); } - Response response = act.getOrchestraClient().getUrls(probeCC, act.getPreferenceManager().getEnabledCategory()).execute(); + Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); if (response.isSuccessful() && response.body() != null && response.body().results != null) { ArrayList inputs = new ArrayList<>(); for (Url url : response.body().results) inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); for (AbstractTest abstractTest : tests) { abstractTest.setInputs(inputs); - abstractTest.setMax_runtime(act.getPreferenceManager().getMaxRuntime()); + abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); } publishProgress(URL); } } for (int i = 0; i < tests.length; i++) { - if (!act.isFinishing() && !interrupt) { + if (!interrupt) { currentTest = tests[i]; - currentTest.run(act, act.getPreferenceManager(), act.getGson(), result, i, this); + currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); } } } catch (Exception e) { - publishProgress(ERR, act.getString(R.string.Modal_Error_CantDownloadURLs)); + publishProgress(ERR, app.getString(R.string.Modal_Error_CantDownloadURLs)); e.printStackTrace(); ExceptionManager.logException(e); } From 4125712f098bb8fe02f1c2366c6a7130009dd644 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 19 Oct 2020 12:29:00 +0100 Subject: [PATCH 28/66] Update TestAsyncTask.java --- .../org/openobservatory/ooniprobe/test/TestAsyncTask.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 2bc518f42..c6b0517ac 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -58,7 +58,10 @@ public TestAsyncTask(Application app, Result result) { } @Override protected Void doInBackground(AbstractTest... tests) { - ACT act = ref.get(); + //How to move this in TestAsyncTaskImpl only? + ACT act = null; + if (ref != null) + act = ref.get(); if (app != null) try { boolean downloadUrls = false; From bae53b8532d2aa43d43467526c7a624bb681f6ca Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 19 Oct 2020 14:59:25 +0100 Subject: [PATCH 29/66] fix --- .../ooniprobe/common/alarm/AlarmReceiver.java | 3 ++- .../org/openobservatory/ooniprobe/test/TestAsyncTask.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index bf7acecea..442313aef 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -48,6 +48,7 @@ public void onReceive(Context context, Intent intent) { //TODO log stuff in countly webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); websitesSuite.setTestList(webConnectivity); + ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); //Intent i = RunningActivity.newBackgroundIntent(context, testSuites); //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -58,7 +59,7 @@ public void onReceive(Context context, Intent intent) { //runWebConnectivity(context, app); //context.startActivity(i); TestAsyncTask task = (TestAsyncTask) new TestAsyncTask(app, websitesSuite.getResult()).execute(websitesSuite.getTestList(pm)); - + //Problem, the test result is shown as error until the test completes. } public void runWebConnectivity(Context c, Application a) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index c6b0517ac..cdfd59a0c 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -59,6 +59,8 @@ public TestAsyncTask(Application app, Result result) { @Override protected Void doInBackground(AbstractTest... tests) { //How to move this in TestAsyncTaskImpl only? + + //Make another class without background ACT act = null; if (ref != null) act = ref.get(); @@ -91,7 +93,8 @@ public TestAsyncTask(Application app, Result result) { inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); for (AbstractTest abstractTest : tests) { abstractTest.setInputs(inputs); - abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); + if (abstractTest.getMax_runtime() == null) + abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); } publishProgress(URL); } From ba5e67445fb8a3fc195219df15a14a791222d3c1 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 19 Oct 2020 15:00:18 +0100 Subject: [PATCH 30/66] Update AbstractTest.java --- .../org/openobservatory/ooniprobe/test/test/AbstractTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java index dc5cab848..829b48183 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java @@ -266,7 +266,7 @@ public void setInputs(List inputs) { this.inputs = inputs; } - Integer getMax_runtime() { + public Integer getMax_runtime() { return max_runtime; } From 8f79fbd12fa3fdaf83f07350b569e7a22260446d Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Tue, 20 Oct 2020 12:37:44 +0100 Subject: [PATCH 31/66] Change TestAsync class --- .../ooniprobe/activity/RunningActivity.java | 17 +++++++++------ .../ooniprobe/test/TestAsyncTask.java | 21 +------------------ 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index b6152795d..b123c96de 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -25,6 +25,7 @@ import org.openobservatory.ooniprobe.test.suite.AbstractSuite; import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.io.Serializable; @@ -107,7 +108,7 @@ private void runTest() { testSuite = testSuites.get(0); testStart(); setTestRunning(true); - task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, testSuite.getResult()).execute(testSuite.getTestList(getPreferenceManager())); + task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, (Application) getApplication(), testSuite.getResult()).execute(testSuite.getTestList(getPreferenceManager())); } } @@ -162,14 +163,18 @@ public void onBackPressed() { Toast.makeText(this, getString(R.string.Modal_Error_CantCloseScreen), Toast.LENGTH_SHORT).show(); } - private static class TestAsyncTaskImpl extends TestAsyncTask { - TestAsyncTaskImpl(RunningActivity activity, Result result) { - super(activity, result); + private static class TestAsyncTaskImpl extends TestAsyncTask { + protected final WeakReference ref; + + TestAsyncTaskImpl(ACT activity, Application app, Result result) { + super(app, result); + this.ref = new WeakReference<>(activity); } @Override protected void onProgressUpdate(String... values) { - RunningActivity act = ref.get(); + //ACT act = ref.get(); + RunningActivity act = (RunningActivity)ref.get(); if (act != null && !act.isFinishing()) switch (values[0]) { case RUN: @@ -199,7 +204,7 @@ protected void onProgressUpdate(String... values) { @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); - RunningActivity act = ref.get(); + RunningActivity act = (RunningActivity)ref.get(); act.testSuites.remove(act.testSuite); if (act.testSuites.size() == 0) endTest(act); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index cdfd59a0c..9993ecd3b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -1,12 +1,10 @@ package org.openobservatory.ooniprobe.test; -import android.content.Context; import android.os.AsyncTask; import org.openobservatory.engine.Engine; import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; -import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ExceptionManager; import org.openobservatory.ooniprobe.model.api.UrlList; @@ -20,14 +18,13 @@ import org.openobservatory.ooniprobe.test.test.AbstractTest; import org.openobservatory.ooniprobe.test.test.WebConnectivity; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import retrofit2.Response; -public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { +public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { public static final List SUITES = Arrays.asList(new WebsitesSuite(), new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite()); public static final String PRG = "PRG"; @@ -35,22 +32,12 @@ public class TestAsyncTask extends AsyncTask ref; protected final Application app; private final Result result; private AbstractTest currentTest; private boolean interrupt; - protected TestAsyncTask(ACT activity, Result result) { - this.ref = new WeakReference<>(activity); - this.app = (Application) activity.getApplication(); - this.result = result; - result.is_viewed = false; - result.save(); - } - public TestAsyncTask(Application app, Result result) { - this.ref = null; this.app = app; this.result = result; result.is_viewed = false; @@ -58,12 +45,6 @@ public TestAsyncTask(Application app, Result result) { } @Override protected Void doInBackground(AbstractTest... tests) { - //How to move this in TestAsyncTaskImpl only? - - //Make another class without background - ACT act = null; - if (ref != null) - act = ref.get(); if (app != null) try { boolean downloadUrls = false; From 40487181cfe8915cdddae131fdf19524f4a17c00 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 21 Oct 2020 12:55:25 +0100 Subject: [PATCH 32/66] Update AlarmReceiver.java --- .../openobservatory/ooniprobe/common/alarm/AlarmReceiver.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 442313aef..f51072003 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -62,6 +62,8 @@ public void onReceive(Context context, Intent intent) { //Problem, the test result is shown as error until the test completes. } + + //TODO used for early testing. TO REMOVE public void runWebConnectivity(Context c, Application a) { boolean submitted = false; String report_id_1 = "r1"; From fa7a7906441947b3279a2ccd0063983e47c84c55 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 22 Oct 2020 15:41:13 +0100 Subject: [PATCH 33/66] add TODO --- .../org/openobservatory/ooniprobe/test/test/AbstractTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java index 829b48183..31533743b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java @@ -68,6 +68,7 @@ void run(Context c, PreferenceManager pm, Gson gson, Settings settings, Result r try { task = Engine.startExperimentTask(settings.toExperimentSettings(gson, c)); } catch (Exception exc) { + //TODO call setFailureMsg here and in other point of (non) return exc.printStackTrace(); ExceptionManager.logException(exc); return; From 9e6ad3b06b794cf2284cd5f163a6b034d1e09cbf Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 26 Oct 2020 10:40:28 +0000 Subject: [PATCH 34/66] Add no internet check --- .../ooniprobe/common/alarm/AlarmReceiver.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index f51072003..092de551b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -9,7 +9,6 @@ import org.openobservatory.engine.Engine; import org.openobservatory.engine.OONIMKTask; -import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.common.PreferenceManager; @@ -45,6 +44,12 @@ public void onReceive(Context context, Intent intent) { return; } + if (!ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) { + Log.d(TAG, "no internet available"); + NotificationService.notifyTestError(context, websitesSuite); + return; + } + //TODO log stuff in countly webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); websitesSuite.setTestList(webConnectivity); @@ -62,7 +67,6 @@ public void onReceive(Context context, Intent intent) { //Problem, the test result is shown as error until the test completes. } - //TODO used for early testing. TO REMOVE public void runWebConnectivity(Context c, Application a) { boolean submitted = false; From 101fd83f6817b1083f4760976d6d96b611820ddc Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 26 Oct 2020 16:02:10 +0000 Subject: [PATCH 35/66] Start implementation of a ServiceJob --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 21 ++++++++++++++++++ .../common/service/RunTestJobService.java | 22 +++++++++++++++++++ .../common/service/RunTestService.java | 21 ++++++++++++++++++ .../ooniprobe/common/service/ServiceUtil.java | 22 +++++++++++++++++++ .../common/service/StartServiceReceiver.java | 14 ++++++++++++ 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/StartServiceReceiver.java diff --git a/app/build.gradle b/app/build.gradle index fc9fc759a..5d65d3caf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ android { defaultConfig { applicationId 'org.openobservatory.ooniprobe' - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionName '2.7.0' versionCode 65 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d6772bff1..641400ce3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -122,6 +122,27 @@ android:scheme="ooni" /> + + + + + + + + + + + + Date: Wed, 28 Oct 2020 17:28:32 +0000 Subject: [PATCH 36/66] First working(ish) implementation of the test as a service --- app/src/main/AndroidManifest.xml | 3 + .../ooniprobe/activity/RunningActivity.java | 161 ++++++++++++--- .../ooniprobe/common/alarm/AlarmReceiver.java | 3 +- .../common/service/RunTestJobService.java | 1 + .../common/service/RunTestService.java | 138 ++++++++++++- .../ooniprobe/test/TestAsyncTask.java | 184 +++++++++++++----- 6 files changed, 410 insertions(+), 80 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 641400ce3..38cbf57d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,11 @@ package="org.openobservatory.ooniprobe"> + + + diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index b123c96de..128aef40b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -1,10 +1,15 @@ package org.openobservatory.ooniprobe.activity; +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.ImageButton; @@ -13,6 +18,8 @@ import android.widget.Toast; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import com.airbnb.lottie.LottieAnimationView; @@ -20,6 +27,7 @@ import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ReachabilityManager; import org.openobservatory.ooniprobe.common.NotificationService; +import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.test.TestAsyncTask; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; @@ -35,7 +43,7 @@ import localhost.toolkit.app.fragment.ConfirmDialogFragment; import localhost.toolkit.app.fragment.MessageDialogFragment; -public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener { +public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener, ServiceConnection { private static final String TEST = "test"; private static final String BACKGROUND_TASK = "background"; @BindView(R.id.running) @@ -54,9 +62,13 @@ public class RunningActivity extends AbstractActivity implements ConfirmDialogFr LottieAnimationView animation; private ArrayList testSuites; private AbstractSuite testSuite; + //private AbstractSuite testSuite; + //TODO maybe not needed anymore private boolean background; private Integer runtime; private TestAsyncTask task; + private RunTestService service; + private MyBroadRequestReceiver receiver; public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { if (ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) { @@ -78,6 +90,7 @@ public static Intent newIntent(Context context, ArrayList testSui return new Intent(context, RunningActivity.class).putExtra(TEST, extra); } + //TODO remove public static Intent newBackgroundIntent(Context context, ArrayList testSuites) { return newIntent(context, testSuites).putExtra("background", true); } @@ -85,6 +98,8 @@ public static Intent newBackgroundIntent(Context context, ArrayList) extra.getSerializable(TEST); if (testSuites == null) { finish(); return; } - runTest(); + startService(); } private void runTest() { - if (testSuites.size() > 0) { + /*if (testSuites.size() > 0) { testSuite = testSuites.get(0); testStart(); setTestRunning(true); - task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, (Application) getApplication(), testSuite.getResult()).execute(testSuite.getTestList(getPreferenceManager())); + startService(); + //task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, (Application) getApplication(), testSuite.getResult()).execute(testSuite.getTestList(getPreferenceManager())); } + */ + } + private void applyUIChanges(int index){ + testSuite = testSuites.get(index); + applyUIChanges(testSuite); } - private void testStart(){ + private void applyUIChanges(AbstractSuite testSuite){ runtime = testSuite.getRuntime(getPreferenceManager()); getWindow().setBackgroundDrawableResource(testSuite.getColor()); if (Build.VERSION.SDK_INT >= 21) { @@ -125,35 +159,32 @@ private void testStart(){ progress.setIndeterminate(true); eta.setText(R.string.Dashboard_Running_CalculatingETA); progress.setMax(testSuite.getTestList(getPreferenceManager()).length * 100); - //TODO remove this line when web_connectiviity will be in go - close.setVisibility(testSuite.getName().equals(WebsitesSuite.NAME) ? View.GONE : View.VISIBLE); - close.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - new ConfirmDialogFragment.Builder() - .withTitle(getString(R.string.Modal_InterruptTest_Title)) - .withMessage(getString(R.string.Modal_InterruptTest_Paragraph)) - .withPositiveButton(getString(R.string.Modal_OK)) - .withNegativeButton(getString(R.string.Modal_Cancel)) - .build().show(getSupportFragmentManager(), null); - } - }); } + //TODO https://stackoverflow.com/questions/55486812/using-a-broadcastreceiver-to-update-a-progressbar @Override protected void onResume() { super.onResume(); + IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity"); + receiver = new MyBroadRequestReceiver(); + LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); + + Intent intent= new Intent(this, RunTestService.class); + bindService(intent, this, Context.BIND_AUTO_CREATE); background = false; } @Override protected void onPause() { - background = true; super.onPause(); + unbindService(this); + LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); + background = true; } @Override protected void onDestroy() { + //TODO use service running setTestRunning(false); super.onDestroy(); } @@ -163,11 +194,93 @@ public void onBackPressed() { Toast.makeText(this, getString(R.string.Modal_Error_CantCloseScreen), Toast.LENGTH_SHORT).show(); } - private static class TestAsyncTaskImpl extends TestAsyncTask { + public void startService() { + //TODO use service running + setTestRunning(true); + Intent serviceIntent = new Intent(this, RunTestService.class); + serviceIntent.putExtra("testSuites", testSuites); + ContextCompat.startForegroundService(this, serviceIntent); + //service.setOnProgressChangedListener(this); + } + + /* + @Override + public void onProgressUpdate(int progress) { + // Do update your progress... + } + */ + + //TODO this should stop the test. Do the relative close functions in there + public void stopService() { + Intent serviceIntent = new Intent(this, RunTestService.class); + stopService(serviceIntent); + Toast.makeText(RunningActivity.this, "DISConnected", Toast.LENGTH_SHORT).show(); + + } + + @Override + public void onServiceConnected(ComponentName cname, IBinder binder) { + RunTestService.TestBinder b = (RunTestService.TestBinder) binder; + service = b.getService(); + applyUIChanges(service.task.currentSuite); + if (service.task.currentTest != null) + name.setText(getString(service.task.currentTest.getLabelResId())); + Toast.makeText(RunningActivity.this, "Connected", Toast.LENGTH_SHORT).show(); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + service = null; + } + + //TODO if activity is opened when a test is running we won't get START (wrong background) + //TODO Create getCurrentTest method onResume + public class MyBroadRequestReceiver 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(Integer.parseInt(value)); + break; + case TestAsyncTask.RUN: + name.setText(value); + break; + case TestAsyncTask.PRG: + progress.setIndeterminate(false); + int prgs = Integer.parseInt(value); + progress.setProgress(prgs); + 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(); + finish(); + break; + case TestAsyncTask.URL: + progress.setIndeterminate(false); + runtime = testSuite.getRuntime(getPreferenceManager()); + break; + case TestAsyncTask.END: + if (background) { + NotificationService.notifyTestEnded(context, testSuite); + } else + startActivity(MainActivity.newIntent(context, R.id.testResults)); + stopService(); + finish(); + break; + } + } + } + //TODO remove impl and change with callbacks from service + /*private static class TestAsyncTaskImpl extends TestAsyncTask { protected final WeakReference ref; TestAsyncTaskImpl(ACT activity, Application app, Result result) { - super(app, result); + //super(app, result); this.ref = new WeakReference<>(activity); } @@ -178,6 +291,7 @@ protected void onProgressUpdate(String... values) { if (act != null && !act.isFinishing()) switch (values[0]) { case RUN: + //TODO this should be fixed in the test to be able to see it even when the test is started act.name.setText(values[1]); break; case PRG: @@ -201,6 +315,7 @@ protected void onProgressUpdate(String... values) { } } + //TODO this execute next test. Will it work in the Service? @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); @@ -212,6 +327,7 @@ protected void onPostExecute(Void aVoid) { act.runTest(); } + //TODO last test executed private void endTest(RunningActivity act){ if (act != null && !act.isFinishing()) { if (act.background) { @@ -220,10 +336,9 @@ private void endTest(RunningActivity act){ act.startActivity(MainActivity.newIntent(act, R.id.testResults)); act.finish(); } - } } - +*/ @Override public void onConfirmation(Serializable serializable, int i) { if (i == DialogInterface.BUTTON_POSITIVE) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index 092de551b..a4059f037 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -29,6 +29,7 @@ public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "alarm-receiver"; + //TODO MOVE this to RunTestJobService @Override public void onReceive(Context context, Intent intent) { Application app = ((Application)context.getApplicationContext()); @@ -63,7 +64,7 @@ public void onReceive(Context context, Intent intent) { NotificationService.notifyTestStarted(context, websitesSuite); //runWebConnectivity(context, app); //context.startActivity(i); - TestAsyncTask task = (TestAsyncTask) new TestAsyncTask(app, websitesSuite.getResult()).execute(websitesSuite.getTestList(pm)); + //TestAsyncTask task = (TestAsyncTask) new TestAsyncTask(app, websitesSuite.getResult()).execute(websitesSuite.getTestList(pm)); //Problem, the test result is shown as error until the test completes. } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java index 7aeb44f90..319fa749b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java @@ -10,6 +10,7 @@ public class RunTestJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { Intent service = new Intent(getApplicationContext(), RunTestService.class); + getApplicationContext().startService(service); ServiceUtil.scheduleJob(getApplicationContext()); // reschedule the job return true; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index c3e5f2f7c..6a219987a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -1,21 +1,151 @@ package org.openobservatory.ooniprobe.common.service; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; import android.content.Intent; +import android.os.Binder; +import android.os.Build; import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.activity.AbstractActivity; +import org.openobservatory.ooniprobe.activity.MainActivity; +import org.openobservatory.ooniprobe.activity.RunningActivity; +import org.openobservatory.ooniprobe.common.Application; +import org.openobservatory.ooniprobe.common.NotificationService; +import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.model.database.Result; +import org.openobservatory.ooniprobe.test.TestAsyncTask; +import org.openobservatory.ooniprobe.test.suite.AbstractSuite; +import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import org.openobservatory.ooniprobe.test.test.AbstractTest; +import org.openobservatory.ooniprobe.test.test.WebConnectivity; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Arrays; public class RunTestService extends Service { + public static final String CHANNEL_ID = "ForegroundServiceChannel"; + public static final int NOTIFICATION_ID = 1; + private final IBinder mBinder = new TestBinder(); + public TestAsyncTask task; + public NotificationCompat.Builder builder; + public NotificationManagerCompat notificationManager; + + @Override + public void onCreate() { + super.onCreate(); + } @Override public int onStartCommand(Intent intent, int flags, int startId) { - //TODO do something useful - return Service.START_NOT_STICKY; + //TODO use test name + ArrayList testSuites = (ArrayList) intent.getSerializableExtra("testSuites"); + //AbstractSuite testSuite = (AbstractSuite)intent.getSerializableExtra("testSuite"); + + //TODO move function to other class + createNotificationChannel(); + + Intent notificationIntent = new Intent(this, RunningActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(this, + 0, notificationIntent, 0); + + //TODO move notification to other class + //TODO add cancel action https://stackoverflow.com/questions/46750788/binding-foreground-services-with-activity + //https://developer.android.com/training/notify-user/build-notification.html#progressbar + //TODO add progress bar + //TODO check if implementation is correct https://stackoverflow.com/questions/18094209/android-displaying-progress-in-a-notification + + notificationManager = NotificationManagerCompat.from(this); + builder = new NotificationCompat.Builder(this, CHANNEL_ID); + builder.setContentTitle(getApplication().getString(R.string.Dashboard_Running_Running)) + .setContentText(getApplication().getString(R.string.Dashboard_Running_PreparingTest)) + .setSmallIcon(R.drawable.notification_icon) + .setContentIntent(pendingIntent) + .setProgress(100, 0, false) + //.addAction(android.R.drawable.ic_media_play, "Play", pplayIntent) + .build(); + + + //notificationManager.notify(notificationId, builder.build()); + + startForeground(NOTIFICATION_ID, builder.build()); + + Application app = ((Application)getApplication()); + PreferenceManager pm = app.getPreferenceManager(); + task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); + //task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, app, testSuites).execute(); + + //stopSelf(); + + return START_NOT_STICKY; + } + + @Override + public void onDestroy() { + super.onDestroy(); + builder.setContentText("Download complete") + .setProgress(0,0,false); + notificationManager.notify(1, builder.build()); } @Override public IBinder onBind(Intent intent) { - //TODO for communication return IBinder implementation - return null; + return mBinder; + } + + public class TestBinder extends Binder { + public RunTestService getService() { + return RunTestService.this; + } } + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel serviceChannel = new NotificationChannel( + CHANNEL_ID, + "Foreground Service Channel", + NotificationManager.IMPORTANCE_DEFAULT + ); + + NotificationManager manager = getSystemService(NotificationManager.class); + manager.createNotificationChannel(serviceChannel); + } + } +/* + private static class TestAsyncTaskImpl extends TestAsyncTask { + protected final WeakReference ref; + + TestAsyncTaskImpl(SRV service, Application app, ArrayList testSuites) { + super(app, testSuites); + this.ref = new WeakReference<>(service); + } + + @Override + protected void onProgressUpdate(String... values) { + super.onProgressUpdate(values); + RunTestService srv = (RunTestService)ref.get(); + srv.builder.setContentText("Download complete") + .setProgress(100,50,false); + srv.notificationManager.notify(NOTIFICATION_ID, srv.builder.build()); + } + + //TODO this execute next test. Will it work in the Service? + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + } + } + */ } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 9993ecd3b..8cfdcfae5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -1,12 +1,20 @@ package org.openobservatory.ooniprobe.test; +import android.content.Intent; import android.os.AsyncTask; +import android.widget.Toast; + +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.engine.Engine; import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.activity.MainActivity; +import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ExceptionManager; +import org.openobservatory.ooniprobe.common.NotificationService; +import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.model.api.UrlList; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.model.database.Url; @@ -24,74 +32,93 @@ import retrofit2.Response; -public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { +public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { public static final List SUITES = Arrays.asList(new WebsitesSuite(), new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite()); + public static final String START = "START"; public static final String PRG = "PRG"; public static final String LOG = "LOG"; public static final String RUN = "RUN"; public static final String ERR = "ERR"; + public static final String END = "END"; public static final String URL = "URL"; protected final Application app; - private final Result result; - private AbstractTest currentTest; + private Result result; + ArrayList testSuites; + public AbstractSuite currentSuite; + public AbstractTest currentTest; private boolean interrupt; + RunTestService service; - public TestAsyncTask(Application app, Result result) { + public TestAsyncTask(Application app, ArrayList testSuites, RunTestService service) { this.app = app; - this.result = result; - result.is_viewed = false; - result.save(); + this.testSuites = testSuites; + this.service = service; } - @Override protected Void doInBackground(AbstractTest... tests) { - if (app != null) - try { - boolean downloadUrls = false; - for (AbstractTest abstractTest : tests) - if (abstractTest instanceof WebConnectivity && abstractTest.getInputs() == null) { - downloadUrls = true; - break; - } - if (downloadUrls) { - String probeCC = "XX"; - try { - probeCC = Engine.resolveProbeCC( - app, - BuildConfig.SOFTWARE_NAME, - BuildConfig.VERSION_NAME, - 30 - ); - } - catch (Exception e) { - e.printStackTrace(); - ExceptionManager.logException(e); - } - Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); - if (response.isSuccessful() && response.body() != null && response.body().results != null) { - ArrayList inputs = new ArrayList<>(); - for (Url url : response.body().results) - inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); - for (AbstractTest abstractTest : tests) { - abstractTest.setInputs(inputs); - if (abstractTest.getMax_runtime() == null) - abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); - } - publishProgress(URL); - } + @Override + protected Void doInBackground(Void... voids) { + if (app != null){ + for (int suiteIdx = 0; suiteIdx < testSuites.size(); suiteIdx++){ + if (!interrupt){ + currentSuite = testSuites.get(suiteIdx); + result = currentSuite.getResult(); + result.is_viewed = false; + result.save(); + publishProgress(START, String.valueOf(suiteIdx)); + runTest(currentSuite.getTestList(app.getPreferenceManager())); + } + } + } + return null; + } + + private void runTest(AbstractTest ... tests){ + try { + boolean downloadUrls = false; + for (AbstractTest abstractTest : tests) + if (abstractTest instanceof WebConnectivity && abstractTest.getInputs() == null) { + downloadUrls = true; + break; + } + if (downloadUrls) { + String probeCC = "XX"; + try { + probeCC = Engine.resolveProbeCC( + app, + BuildConfig.SOFTWARE_NAME, + BuildConfig.VERSION_NAME, + 30 + ); } - for (int i = 0; i < tests.length; i++) { - if (!interrupt) { - currentTest = tests[i]; - currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); + catch (Exception e) { + e.printStackTrace(); + ExceptionManager.logException(e); + } + Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); + if (response.isSuccessful() && response.body() != null && response.body().results != null) { + ArrayList inputs = new ArrayList<>(); + for (Url url : response.body().results) + inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); + for (AbstractTest abstractTest : tests) { + abstractTest.setInputs(inputs); + if (abstractTest.getMax_runtime() == null) + abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); } + publishProgress(URL); } - } catch (Exception e) { - publishProgress(ERR, app.getString(R.string.Modal_Error_CantDownloadURLs)); - e.printStackTrace(); - ExceptionManager.logException(e); } - return null; + for (int i = 0; i < tests.length; i++) { + if (!interrupt) { + currentTest = tests[i]; + currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); + } + } + } catch (Exception e) { + publishProgress(ERR, app.getString(R.string.Modal_Error_CantDownloadURLs)); + e.printStackTrace(); + ExceptionManager.logException(e); + } } @Override public void onStart(String name) { @@ -103,7 +130,60 @@ public TestAsyncTask(Application app, Result result) { } @Override public final void onLog(String log) { - publishProgress(LOG, log); + if (!isInterrupted()) + publishProgress(LOG, log); + } + + @Override + protected void onProgressUpdate(String... values) { + sendBroadcast(values); + String key = values[0]; + if (values.length <= 1) return; + String value = values[1]; + switch (key) { + case TestAsyncTask.RUN: + service.builder.setContentText(value) + .setProgress(currentSuite.getTestList(app.getPreferenceManager()).length * 100, 0,false); + service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); + break; + case TestAsyncTask.PRG: + int prgs = Integer.parseInt(value); + service.builder.setProgress(currentSuite.getTestList(app.getPreferenceManager()).length * 100, prgs,false); + service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); + break; + case TestAsyncTask.ERR: + break; + } + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + /*suiteIdx++; + if (suiteIdx < testSuites.size() && !interrupt){ + AbstractSuite suite = testSuites.get(suiteIdx); + runTest(suite.getTestList(app.getPreferenceManager())); + } + else + */ + sendBroadcast(END); + /* + RunningActivity act = (RunningActivity)ref.get(); + act.testSuites.remove(act.testSuite); + if (act.testSuites.size() == 0) + endTest(act); + else + act.runTest(); + */ + } + + private void sendBroadcast(String... values){ + Intent broadcastIntent = new Intent(); + broadcastIntent.putExtra("key", values[0]); + if (values.length > 1) + broadcastIntent.putExtra("value", values[1]); + broadcastIntent.setAction("org.openobservatory.ooniprobe.activity.RunningActivity"); + LocalBroadcastManager.getInstance(app).sendBroadcast(broadcastIntent); } public synchronized boolean isInterrupted() { From 7d445f0c4a119590217737fd1f8d00071156c4ff Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 30 Oct 2020 09:48:27 +0000 Subject: [PATCH 37/66] Start code cleanup --- app/src/main/AndroidManifest.xml | 2 + .../ooniprobe/activity/AbstractActivity.java | 2 + .../ooniprobe/activity/RunningActivity.java | 117 ++---------------- .../ooniprobe/common/Application.java | 2 + .../ooniprobe/common/NotificationService.java | 3 +- .../common/service/RunTestService.java | 91 ++++---------- .../ooniprobe/test/TestAsyncTask.java | 20 +-- 7 files changed, 41 insertions(+), 196 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 38cbf57d5..a1f734842 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -144,6 +144,8 @@ + + testSuites; private AbstractSuite testSuite; - //private AbstractSuite testSuite; - //TODO maybe not needed anymore private boolean background; private Integer runtime; private TestAsyncTask task; private RunTestService service; - private MyBroadRequestReceiver receiver; + private TestRunBroadRequestReceiver receiver; public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { if (ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) { @@ -90,21 +83,10 @@ public static Intent newIntent(Context context, ArrayList testSui return new Intent(context, RunningActivity.class).putExtra(TEST, extra); } - //TODO remove - public static Intent newBackgroundIntent(Context context, ArrayList testSuites) { - return newIntent(context, testSuites).putExtra("background", true); - } - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //TODO remove - //With this function we can move the activity to the background - //https://stackoverflow.com/questions/10008879/intent-to-start-activity-but-dont-bring-to-front - if (getIntent().getBooleanExtra(BACKGROUND_TASK, false)) - moveTaskToBack(true); - setTheme(R.style.Theme_MaterialComponents_NoActionBar_App); setContentView(R.layout.activity_running); ButterKnife.bind(this); @@ -122,7 +104,6 @@ public void onClick(View view) { } }); - //if (extra != null) testSuites = (ArrayList) extra.getSerializable(TEST); if (testSuites == null) { finish(); @@ -131,16 +112,6 @@ public void onClick(View view) { startService(); } - private void runTest() { - /*if (testSuites.size() > 0) { - testSuite = testSuites.get(0); - testStart(); - setTestRunning(true); - startService(); - //task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, (Application) getApplication(), testSuite.getResult()).execute(testSuite.getTestList(getPreferenceManager())); - } - */ - } private void applyUIChanges(int index){ testSuite = testSuites.get(index); applyUIChanges(testSuite); @@ -161,14 +132,13 @@ private void applyUIChanges(AbstractSuite testSuite){ progress.setMax(testSuite.getTestList(getPreferenceManager()).length * 100); } - //TODO https://stackoverflow.com/questions/55486812/using-a-broadcastreceiver-to-update-a-progressbar @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity"); - receiver = new MyBroadRequestReceiver(); + receiver = new TestRunBroadRequestReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); - + //Bind the RunTestService Intent intent= new Intent(this, RunTestService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); background = false; @@ -200,22 +170,12 @@ public void startService() { Intent serviceIntent = new Intent(this, RunTestService.class); serviceIntent.putExtra("testSuites", testSuites); ContextCompat.startForegroundService(this, serviceIntent); - //service.setOnProgressChangedListener(this); } - /* - @Override - public void onProgressUpdate(int progress) { - // Do update your progress... - } - */ - //TODO this should stop the test. Do the relative close functions in there public void stopService() { Intent serviceIntent = new Intent(this, RunTestService.class); stopService(serviceIntent); - Toast.makeText(RunningActivity.this, "DISConnected", Toast.LENGTH_SHORT).show(); - } @Override @@ -225,7 +185,6 @@ public void onServiceConnected(ComponentName cname, IBinder binder) { applyUIChanges(service.task.currentSuite); if (service.task.currentTest != null) name.setText(getString(service.task.currentTest.getLabelResId())); - Toast.makeText(RunningActivity.this, "Connected", Toast.LENGTH_SHORT).show(); } @Override @@ -233,9 +192,7 @@ public void onServiceDisconnected(ComponentName name) { service = null; } - //TODO if activity is opened when a test is running we won't get START (wrong background) - //TODO Create getCurrentTest method onResume - public class MyBroadRequestReceiver extends BroadcastReceiver { + public class TestRunBroadRequestReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String key = intent.getStringExtra("key"); @@ -265,83 +222,23 @@ public void onReceive(Context context, Intent intent) { runtime = testSuite.getRuntime(getPreferenceManager()); break; case TestAsyncTask.END: + //TODO this can be removed if we use the onDestroy of the Service if (background) { NotificationService.notifyTestEnded(context, testSuite); } else startActivity(MainActivity.newIntent(context, R.id.testResults)); + //TODO I don't think the activity should be the one in charge to stop the service stopService(); finish(); break; } } } - //TODO remove impl and change with callbacks from service - /*private static class TestAsyncTaskImpl extends TestAsyncTask { - protected final WeakReference ref; - TestAsyncTaskImpl(ACT activity, Application app, Result result) { - //super(app, result); - this.ref = new WeakReference<>(activity); - } - - @Override - protected void onProgressUpdate(String... values) { - //ACT act = ref.get(); - RunningActivity act = (RunningActivity)ref.get(); - if (act != null && !act.isFinishing()) - switch (values[0]) { - case RUN: - //TODO this should be fixed in the test to be able to see it even when the test is started - act.name.setText(values[1]); - break; - case PRG: - act.progress.setIndeterminate(false); - int prgs = Integer.parseInt(values[1]); - act.progress.setProgress(prgs); - act.eta.setText(act.getString(R.string.Dashboard_Running_Seconds, String.valueOf(Math.round(act.runtime - ((double) prgs) / act.progress.getMax() * act.runtime)))); - break; - case LOG: - if (!act.task.isInterrupted()) - act.log.setText(values[1]); - break; - case ERR: - Toast.makeText(act, values[1], Toast.LENGTH_SHORT).show(); - act.finish(); - break; - case URL: - act.progress.setIndeterminate(false); - act.runtime = act.testSuite.getRuntime(act.getPreferenceManager()); - break; - } - } - - //TODO this execute next test. Will it work in the Service? - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - RunningActivity act = (RunningActivity)ref.get(); - act.testSuites.remove(act.testSuite); - if (act.testSuites.size() == 0) - endTest(act); - else - act.runTest(); - } - - //TODO last test executed - private void endTest(RunningActivity act){ - if (act != null && !act.isFinishing()) { - if (act.background) { - NotificationService.notifyTestEnded(act, act.testSuite); - } else - act.startActivity(MainActivity.newIntent(act, R.id.testResults)); - act.finish(); - } - } - } -*/ @Override public void onConfirmation(Serializable serializable, int i) { if (i == DialogInterface.BUTTON_POSITIVE) { + //TODO move these strings in a callback running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); task.interrupt(); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java index ce277a355..6956ec06d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java @@ -108,10 +108,12 @@ public Gson getGson() { return gson; } + //TODO check the RunTestService public boolean isTestRunning() { return testRunning; } + //TODO check the RunTestService public void setTestRunning(boolean testRunning) { this.testRunning = testRunning; } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index 2310c0145..643a871e0 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -29,6 +29,7 @@ public static void initNotification(Application app){ NotificationService.setToken(app); } + //TODO check these methods public static void notifyTestStarted(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Dashboard_Running_Running)); @@ -72,7 +73,7 @@ private static void setToken(Application a){ } // Register the channel with the system - private static void setChannel(Context c, String channelID, String channelName){ + public static void setChannel(Context c, String channelID, String channelName){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = (NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 6a219987a..977d70de5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -1,42 +1,28 @@ package org.openobservatory.ooniprobe.common.service; import android.app.Notification; -import android.app.NotificationChannel; -import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; import android.os.Binder; -import android.os.Build; import android.os.IBinder; -import android.util.Log; -import android.widget.Toast; -import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.ooniprobe.R; -import org.openobservatory.ooniprobe.activity.AbstractActivity; -import org.openobservatory.ooniprobe.activity.MainActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.NotificationService; -import org.openobservatory.ooniprobe.common.PreferenceManager; -import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.test.TestAsyncTask; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; -import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; -import org.openobservatory.ooniprobe.test.test.AbstractTest; -import org.openobservatory.ooniprobe.test.test.WebConnectivity; -import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Arrays; public class RunTestService extends Service { - public static final String CHANNEL_ID = "ForegroundServiceChannel"; + public static final String CHANNEL_ID = "RunTestService"; public static final int NOTIFICATION_ID = 1; private final IBinder mBinder = new TestBinder(); public TestAsyncTask task; @@ -50,23 +36,12 @@ public void onCreate() { @Override public int onStartCommand(Intent intent, int flags, int startId) { - //TODO use test name ArrayList testSuites = (ArrayList) intent.getSerializableExtra("testSuites"); - //AbstractSuite testSuite = (AbstractSuite)intent.getSerializableExtra("testSuite"); - - //TODO move function to other class - createNotificationChannel(); - + Application app = ((Application)getApplication()); + NotificationService.setChannel(getApplicationContext(), CHANNEL_ID, app.getString(R.string.Settings_AutomatedTesting_Label)); Intent notificationIntent = new Intent(this, RunningActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); - - //TODO move notification to other class - //TODO add cancel action https://stackoverflow.com/questions/46750788/binding-foreground-services-with-activity - //https://developer.android.com/training/notify-user/build-notification.html#progressbar - //TODO add progress bar - //TODO check if implementation is correct https://stackoverflow.com/questions/18094209/android-displaying-progress-in-a-notification - notificationManager = NotificationManagerCompat.from(this); builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentTitle(getApplication().getString(R.string.Dashboard_Running_Running)) @@ -77,25 +52,26 @@ public int onStartCommand(Intent intent, int flags, int startId) { //.addAction(android.R.drawable.ic_media_play, "Play", pplayIntent) .build(); + Intent intentAction = new Intent(getApplicationContext(), ActionReceiver.class); + intentAction.putExtra("action","stop"); + PendingIntent pIntent = PendingIntent.getBroadcast(this,1, intentAction,PendingIntent.FLAG_UPDATE_CURRENT); + builder.addAction(R.drawable.ooni_logo, "STOP TEST", pIntent); - //notificationManager.notify(notificationId, builder.build()); startForeground(NOTIFICATION_ID, builder.build()); - Application app = ((Application)getApplication()); - PreferenceManager pm = app.getPreferenceManager(); task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); - //task = (TestAsyncTaskImpl) new TestAsyncTaskImpl(this, app, testSuites).execute(); //stopSelf(); return START_NOT_STICKY; } + //TODO test this if it's too intrusive when app foreground @Override public void onDestroy() { super.onDestroy(); - builder.setContentText("Download complete") + builder.setContentText(getApplicationContext().getString(R.string.Notification_FinishedRunning)) .setProgress(0,0,false); notificationManager.notify(1, builder.build()); } @@ -111,41 +87,24 @@ public RunTestService getService() { } } - private void createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel serviceChannel = new NotificationChannel( - CHANNEL_ID, - "Foreground Service Channel", - NotificationManager.IMPORTANCE_DEFAULT - ); - - NotificationManager manager = getSystemService(NotificationManager.class); - manager.createNotificationChannel(serviceChannel); - } - } -/* - private static class TestAsyncTaskImpl extends TestAsyncTask { - protected final WeakReference ref; - - TestAsyncTaskImpl(SRV service, Application app, ArrayList testSuites) { - super(app, testSuites); - this.ref = new WeakReference<>(service); - } + public static class ActionReceiver extends BroadcastReceiver { @Override - protected void onProgressUpdate(String... values) { - super.onProgressUpdate(values); - RunTestService srv = (RunTestService)ref.get(); - srv.builder.setContentText("Download complete") - .setProgress(100,50,false); - srv.notificationManager.notify(NOTIFICATION_ID, srv.builder.build()); + public void onReceive(Context context, Intent intent) { + String action=intent.getStringExtra("action"); + if(action.equals("stop")){ + stopTest(); + } + //This is used to close the notification tray + Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); + context.sendBroadcast(it); } - //TODO this execute next test. Will it work in the Service? - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); + public void stopTest(){ + //TODO call interrupt test + //task.interrupt(); + System.out.println("stopTest is being called"); } } - */ + } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 8cfdcfae5..1026f2afc 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -2,18 +2,14 @@ import android.content.Intent; import android.os.AsyncTask; -import android.widget.Toast; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.engine.Engine; import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.R; -import org.openobservatory.ooniprobe.activity.MainActivity; -import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.ExceptionManager; -import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.model.api.UrlList; import org.openobservatory.ooniprobe.model.database.Result; @@ -152,6 +148,7 @@ protected void onProgressUpdate(String... values) { service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; case TestAsyncTask.ERR: + //TODO break; } } @@ -159,22 +156,7 @@ protected void onProgressUpdate(String... values) { @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); - /*suiteIdx++; - if (suiteIdx < testSuites.size() && !interrupt){ - AbstractSuite suite = testSuites.get(suiteIdx); - runTest(suite.getTestList(app.getPreferenceManager())); - } - else - */ sendBroadcast(END); - /* - RunningActivity act = (RunningActivity)ref.get(); - act.testSuites.remove(act.testSuite); - if (act.testSuites.size() == 0) - endTest(act); - else - act.runTest(); - */ } private void sendBroadcast(String... values){ From feb0d0a68796a8b0c26025e788e5a0544272c68e Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 30 Oct 2020 15:19:21 +0000 Subject: [PATCH 38/66] Stop test --- app/src/main/AndroidManifest.xml | 2 -- .../ooniprobe/activity/RunningActivity.java | 12 ++++--- .../common/service/RunTestService.java | 36 ++++++++++++------- .../ooniprobe/test/TestAsyncTask.java | 15 ++++++-- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a1f734842..38cbf57d5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -144,8 +144,6 @@ - - = 21) { @@ -221,6 +222,9 @@ public void onReceive(Context context, Intent intent) { progress.setIndeterminate(false); runtime = testSuite.getRuntime(getPreferenceManager()); break; + case TestAsyncTask.INT: + running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); + log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); case TestAsyncTask.END: //TODO this can be removed if we use the onDestroy of the Service if (background) { @@ -238,10 +242,8 @@ public void onReceive(Context context, Intent intent) { @Override public void onConfirmation(Serializable serializable, int i) { if (i == DialogInterface.BUTTON_POSITIVE) { - //TODO move these strings in a callback - running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); - log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); - task.interrupt(); + if (service != null) + service.task.interrupt(); } } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 977d70de5..da43bd0ed 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -6,11 +6,13 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.Binder; import android.os.IBinder; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.RunningActivity; @@ -24,14 +26,19 @@ public class RunTestService extends Service { public static final String CHANNEL_ID = "RunTestService"; public static final int NOTIFICATION_ID = 1; + public static final String ACTION_INTERRUPT = "interrupt_test"; private final IBinder mBinder = new TestBinder(); public TestAsyncTask task; public NotificationCompat.Builder builder; public NotificationManagerCompat notificationManager; + ActionReceiver receiver; @Override public void onCreate() { super.onCreate(); + IntentFilter filter = new IntentFilter(ACTION_INTERRUPT); + ActionReceiver receiver = new ActionReceiver(); + this.registerReceiver(receiver, filter); } @Override @@ -52,15 +59,15 @@ public int onStartCommand(Intent intent, int flags, int startId) { //.addAction(android.R.drawable.ic_media_play, "Play", pplayIntent) .build(); - Intent intentAction = new Intent(getApplicationContext(), ActionReceiver.class); - intentAction.putExtra("action","stop"); - PendingIntent pIntent = PendingIntent.getBroadcast(this,1, intentAction,PendingIntent.FLAG_UPDATE_CURRENT); - builder.addAction(R.drawable.ooni_logo, "STOP TEST", pIntent); + task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); - startForeground(NOTIFICATION_ID, builder.build()); + Intent broadcastIntent = new Intent(); + broadcastIntent.setAction(RunTestService.ACTION_INTERRUPT); + PendingIntent pIntent = PendingIntent.getBroadcast(this,1, broadcastIntent,PendingIntent.FLAG_UPDATE_CURRENT); + builder.addAction(R.drawable.ooni_logo, "STOP TEST", pIntent); - task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); + startForeground(NOTIFICATION_ID, builder.build()); //stopSelf(); @@ -74,6 +81,8 @@ public void onDestroy() { builder.setContentText(getApplicationContext().getString(R.string.Notification_FinishedRunning)) .setProgress(0,0,false); notificationManager.notify(1, builder.build()); + if (receiver != null) + this.unregisterReceiver(receiver); } @Override @@ -87,23 +96,24 @@ public RunTestService getService() { } } - public static class ActionReceiver extends BroadcastReceiver { + public class ActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - String action=intent.getStringExtra("action"); - if(action.equals("stop")){ - stopTest(); + String action = intent.getAction(); + System.out.println("stopTest onReceive is being called1.1 " + action); + if(action != null && action.equals("interrupt_test")){ + stopTest(context); } //This is used to close the notification tray Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); context.sendBroadcast(it); } - public void stopTest(){ + public void stopTest(Context context){ //TODO call interrupt test - //task.interrupt(); - System.out.println("stopTest is being called"); + System.out.println("stopTest is being called1"); + task.interrupt(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 1026f2afc..a6786574f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -38,6 +38,7 @@ public class TestAsyncTask extends AsyncTask implements Abst public static final String ERR = "ERR"; public static final String END = "END"; public static final String URL = "URL"; + public static final String INT = "INT"; protected final Application app; private Result result; ArrayList testSuites; @@ -122,7 +123,8 @@ private void runTest(AbstractTest ... tests){ } @Override public final void onProgress(int progress) { - publishProgress(PRG, Integer.toString(progress)); + if (!isInterrupted()) + publishProgress(PRG, Integer.toString(progress)); } @Override public final void onLog(String log) { @@ -147,6 +149,11 @@ protected void onProgressUpdate(String... values) { service.builder.setProgress(currentSuite.getTestList(app.getPreferenceManager()).length * 100, prgs,false); service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; + case TestAsyncTask.INT: + service.builder.setContentText(app.getString(R.string.Dashboard_Running_Stopping_Title)) + .setProgress(0, 0, true); + service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); + break; case TestAsyncTask.ERR: //TODO break; @@ -173,8 +180,10 @@ public synchronized boolean isInterrupted() { } public synchronized void interrupt(){ - interrupt = true; - if(currentTest.canInterrupt()) + if(currentTest.canInterrupt()) { + interrupt = true; currentTest.interrupt(); + sendBroadcast(INT); + } } } From 034b58ecb4b3fb448324264909360bf09251b029 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 2 Nov 2020 11:45:21 +0000 Subject: [PATCH 39/66] Check test running --- .idea/compiler.xml | 5 +--- .idea/misc.xml | 12 ++++++--- .../ooniprobe/activity/AbstractActivity.java | 6 ----- .../ooniprobe/activity/RunningActivity.java | 17 +++++------- .../ooniprobe/common/Application.java | 27 ++++++++++++++----- .../ooniprobe/common/NotificationService.java | 2 +- .../ooniprobe/common/alarm/AlarmReceiver.java | 6 ++--- .../common/service/RunTestService.java | 4 +-- .../ooniprobe/test/TestAsyncTask.java | 2 +- 9 files changed, 44 insertions(+), 37 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index b1568e3f5..61a9130cd 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,9 +1,6 @@ - - - - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 4859883cd..0edc5c834 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ - + diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/AbstractActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/AbstractActivity.java index cf76ac316..0f842c2a8 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/AbstractActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/AbstractActivity.java @@ -20,16 +20,10 @@ public Gson getGson() { return ((Application) getApplication()).getGson(); } - //TODO check the RunTestService boolean isTestRunning() { return ((Application) getApplication()).isTestRunning(); } - //TODO check the RunTestService - void setTestRunning(boolean testRunning) { - ((Application) getApplication()).setTestRunning(testRunning); - } - public OONIOrchestraClient getOrchestraClient() { return ((Application) getApplication()).getOrchestraClient(); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index f5c419427..638b9b881 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -85,7 +85,6 @@ public static Intent newIntent(Context context, ArrayList testSui @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setTheme(R.style.Theme_MaterialComponents_NoActionBar_App); setContentView(R.layout.activity_running); ButterKnife.bind(this); @@ -155,9 +154,8 @@ protected void onPause() { @Override protected void onDestroy() { - //TODO use service running - setTestRunning(false); super.onDestroy(); + } @Override @@ -166,17 +164,16 @@ public void onBackPressed() { } public void startService() { - //TODO use service running - setTestRunning(true); Intent serviceIntent = new Intent(this, RunTestService.class); serviceIntent.putExtra("testSuites", testSuites); ContextCompat.startForegroundService(this, serviceIntent); } - //TODO this should stop the test. Do the relative close functions in there + //TODO-SERVICE this should stop the test. Do the relative close functions in there public void stopService() { Intent serviceIntent = new Intent(this, RunTestService.class); stopService(serviceIntent); + finish(); } @Override @@ -215,8 +212,9 @@ public void onReceive(Context context, Intent intent) { log.setText(value); break; case TestAsyncTask.ERR: + //TODO-SERVICE shouldn't be thiss callback to stop Toast.makeText(context, value, Toast.LENGTH_SHORT).show(); - finish(); + stopService(); break; case TestAsyncTask.URL: progress.setIndeterminate(false); @@ -226,14 +224,13 @@ public void onReceive(Context context, Intent intent) { running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); case TestAsyncTask.END: - //TODO this can be removed if we use the onDestroy of the Service + //TODO-SERVICE this can be removed if we use the onDestroy of the Service if (background) { NotificationService.notifyTestEnded(context, testSuite); } else startActivity(MainActivity.newIntent(context, R.id.testResults)); - //TODO I don't think the activity should be the one in charge to stop the service + //TODO-SERVICE I don't think the activity should be the one in charge to stop the service stopService(); - finish(); break; } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java index 6956ec06d..8c034b65f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java @@ -1,5 +1,7 @@ package org.openobservatory.ooniprobe.common; +import android.app.ActivityManager; + import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; @@ -13,6 +15,7 @@ import org.openobservatory.ooniprobe.BuildConfig; import org.openobservatory.ooniprobe.client.OONIAPIClient; import org.openobservatory.ooniprobe.client.OONIOrchestraClient; +import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.jsonresult.TestKeys; @@ -31,7 +34,6 @@ public class Application extends android.app.Application { private PreferenceManager preferenceManager; private Gson gson; - private boolean testRunning; private OkHttpClient okHttpClient; private OONIOrchestraClient orchestraClient; private OONIAPIClient apiClient; @@ -108,16 +110,27 @@ public Gson getGson() { return gson; } - //TODO check the RunTestService public boolean isTestRunning() { - return testRunning; + return checkServiceRunning(RunTestService.class); } - //TODO check the RunTestService - public void setTestRunning(boolean testRunning) { - this.testRunning = testRunning; + /** + * Check if the service is Running https://stackoverflow.com/a/24729110 + * @param serviceClass the class of the Service + * + * @return true if the service is running otherwise false + */ + public boolean checkServiceRunning(Class serviceClass){ + ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) + { + if (serviceClass.getName().equals(service.service.getClassName())) + { + return true; + } + } + return false; } - //from https://medium.com/mindorks/detecting-when-an-android-app-is-in-foreground-or-background-7a1ff49812d7 public class AppLifecycleObserver implements LifecycleObserver { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index 643a871e0..600e20814 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -29,7 +29,7 @@ public static void initNotification(Application app){ NotificationService.setToken(app); } - //TODO check these methods + //TODO-SERVICE check these methods public static void notifyTestStarted(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Dashboard_Running_Running)); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index a4059f037..c663ee548 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -29,7 +29,7 @@ public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "alarm-receiver"; - //TODO MOVE this to RunTestJobService + //TODO-SERVICE MOVE this to RunTestJobService @Override public void onReceive(Context context, Intent intent) { Application app = ((Application)context.getApplicationContext()); @@ -51,7 +51,7 @@ public void onReceive(Context context, Intent intent) { return; } - //TODO log stuff in countly + //TODO-SERVICE log stuff in countly webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); websitesSuite.setTestList(webConnectivity); @@ -68,7 +68,7 @@ public void onReceive(Context context, Intent intent) { //Problem, the test result is shown as error until the test completes. } - //TODO used for early testing. TO REMOVE + //TODO-SERVICE used for early testing. TO REMOVE public void runWebConnectivity(Context c, Application a) { boolean submitted = false; String report_id_1 = "r1"; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index da43bd0ed..ff6b87e1d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -74,7 +74,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } - //TODO test this if it's too intrusive when app foreground + //TODO-SERVICE test this if it's too intrusive when app foreground @Override public void onDestroy() { super.onDestroy(); @@ -111,7 +111,7 @@ public void onReceive(Context context, Intent intent) { } public void stopTest(Context context){ - //TODO call interrupt test + //TODO-SERVICE call interrupt test System.out.println("stopTest is being called1"); task.interrupt(); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index a6786574f..9bf75a20e 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -155,7 +155,7 @@ protected void onProgressUpdate(String... values) { service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; case TestAsyncTask.ERR: - //TODO + //TODO-SERVICE stop the service break; } } From 6a50119c62d550f7e01b9e612869c6c48c8131a8 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 2 Nov 2020 13:13:14 +0000 Subject: [PATCH 40/66] Managing test start stop and post Execution --- app/src/main/AndroidManifest.xml | 2 +- .../ooniprobe/activity/MainActivity.java | 2 ++ .../ooniprobe/activity/RunningActivity.java | 29 ++++++------------- .../ooniprobe/common/NotificationService.java | 4 ++- .../ooniprobe/common/alarm/AlarmReceiver.java | 6 ++-- .../common/service/RunTestService.java | 15 ++++------ .../ooniprobe/test/TestAsyncTask.java | 6 ++-- 7 files changed, 25 insertions(+), 39 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 38cbf57d5..c2d00ddf0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -145,7 +145,7 @@ - + testSuites; private AbstractSuite testSuite; - private boolean background; private Integer runtime; private RunTestService service; private TestRunBroadRequestReceiver receiver; @@ -135,13 +134,14 @@ private void applyUIChanges(AbstractSuite testSuite){ @Override protected void onResume() { super.onResume(); + if (!isTestRunning()) + testEnded(this); IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity"); receiver = new TestRunBroadRequestReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); //Bind the RunTestService Intent intent= new Intent(this, RunTestService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); - background = false; } @Override @@ -149,13 +149,12 @@ protected void onPause() { super.onPause(); unbindService(this); LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); - background = true; } @Override protected void onDestroy() { super.onDestroy(); - + LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); } @Override @@ -169,13 +168,6 @@ public void startService() { ContextCompat.startForegroundService(this, serviceIntent); } - //TODO-SERVICE this should stop the test. Do the relative close functions in there - public void stopService() { - Intent serviceIntent = new Intent(this, RunTestService.class); - stopService(serviceIntent); - finish(); - } - @Override public void onServiceConnected(ComponentName cname, IBinder binder) { RunTestService.TestBinder b = (RunTestService.TestBinder) binder; @@ -212,9 +204,7 @@ public void onReceive(Context context, Intent intent) { log.setText(value); break; case TestAsyncTask.ERR: - //TODO-SERVICE shouldn't be thiss callback to stop Toast.makeText(context, value, Toast.LENGTH_SHORT).show(); - stopService(); break; case TestAsyncTask.URL: progress.setIndeterminate(false); @@ -224,18 +214,17 @@ public void onReceive(Context context, Intent intent) { running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); log.setText(getString(R.string.Dashboard_Running_Stopping_Notice)); case TestAsyncTask.END: - //TODO-SERVICE this can be removed if we use the onDestroy of the Service - if (background) { - NotificationService.notifyTestEnded(context, testSuite); - } else - startActivity(MainActivity.newIntent(context, R.id.testResults)); - //TODO-SERVICE I don't think the activity should be the one in charge to stop the service - stopService(); + testEnded(context); break; } } } + private void testEnded(Context context) { + startActivity(MainActivity.newIntent(context, R.id.testResults)); + finish(); + } + @Override public void onConfirmation(Serializable serializable, int i) { if (i == DialogInterface.BUTTON_POSITIVE) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index 600e20814..bc1796080 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -29,17 +29,19 @@ public static void initNotification(Application app){ NotificationService.setToken(app); } - //TODO-SERVICE check these methods + //TODO-SERVICE-BK remove this method public static void notifyTestStarted(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Dashboard_Running_Running)); } + //TODO-SERVICE-BK check this method public static void notifyTestError(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Modal_Error)); } + //TODO-SERVICE-BK check remove method (it's unified with RunTestService.onDestroy public static void notifyTestEnded(Context c, AbstractSuite testSuite) { setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Notification_FinishedRunning)); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java index c663ee548..0114064f7 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java @@ -29,7 +29,7 @@ public class AlarmReceiver extends BroadcastReceiver { private static final String TAG = "alarm-receiver"; - //TODO-SERVICE MOVE this to RunTestJobService + //TODO-SERVICE-BK MOVE this to RunTestJobService @Override public void onReceive(Context context, Intent intent) { Application app = ((Application)context.getApplicationContext()); @@ -51,7 +51,7 @@ public void onReceive(Context context, Intent intent) { return; } - //TODO-SERVICE log stuff in countly + //TODO-SERVICE-BK log stuff in countly webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); websitesSuite.setTestList(webConnectivity); @@ -68,7 +68,7 @@ public void onReceive(Context context, Intent intent) { //Problem, the test result is shown as error until the test completes. } - //TODO-SERVICE used for early testing. TO REMOVE + //TODO-SERVICE-BK used for early testing. TO REMOVE public void runWebConnectivity(Context c, Application a) { boolean submitted = false; String report_id_1 = "r1"; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index ff6b87e1d..e7aa7e501 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -37,7 +37,7 @@ public class RunTestService extends Service { public void onCreate() { super.onCreate(); IntentFilter filter = new IntentFilter(ACTION_INTERRUPT); - ActionReceiver receiver = new ActionReceiver(); + receiver = new ActionReceiver(); this.registerReceiver(receiver, filter); } @@ -69,20 +69,18 @@ public int onStartCommand(Intent intent, int flags, int startId) { startForeground(NOTIFICATION_ID, builder.build()); - //stopSelf(); - return START_NOT_STICKY; } - //TODO-SERVICE test this if it's too intrusive when app foreground + //TODO-SERVICE test this notification if it's too intrusive when app foreground @Override public void onDestroy() { super.onDestroy(); - builder.setContentText(getApplicationContext().getString(R.string.Notification_FinishedRunning)) + builder.mActions.clear(); + builder.setContentTitle(getApplicationContext().getString(R.string.Notification_FinishedRunning)) .setProgress(0,0,false); notificationManager.notify(1, builder.build()); - if (receiver != null) - this.unregisterReceiver(receiver); + this.unregisterReceiver(receiver); } @Override @@ -101,7 +99,6 @@ public class ActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - System.out.println("stopTest onReceive is being called1.1 " + action); if(action != null && action.equals("interrupt_test")){ stopTest(context); } @@ -111,8 +108,6 @@ public void onReceive(Context context, Intent intent) { } public void stopTest(Context context){ - //TODO-SERVICE call interrupt test - System.out.println("stopTest is being called1"); task.interrupt(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 9bf75a20e..b2d4dd984 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -30,7 +30,7 @@ public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { public static final List SUITES = Arrays.asList(new WebsitesSuite(), - new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite()); + new InstantMessagingSuite(), new CircumventionSuite()); public static final String START = "START"; public static final String PRG = "PRG"; public static final String LOG = "LOG"; @@ -154,9 +154,6 @@ protected void onProgressUpdate(String... values) { .setProgress(0, 0, true); service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; - case TestAsyncTask.ERR: - //TODO-SERVICE stop the service - break; } } @@ -164,6 +161,7 @@ protected void onProgressUpdate(String... values) { protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); sendBroadcast(END); + service.stopSelf(); } private void sendBroadcast(String... values){ From fff59120c3dbbca2bd7b019df1e19b0802fa72de Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 2 Nov 2020 13:13:21 +0000 Subject: [PATCH 41/66] Fix unexpected end of stream on Connection in android --- .../org/openobservatory/ooniprobe/common/Application.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java index 8c034b65f..f71b24e63 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/Application.java @@ -64,7 +64,10 @@ public OkHttpClient getOkHttpClient() { .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request().newBuilder().addHeader("User-Agent", "ooniprobe-android/" + BuildConfig.VERSION_NAME).build(); + Request request = chain.request().newBuilder() + .addHeader("User-Agent", "ooniprobe-android/" + BuildConfig.VERSION_NAME) + .addHeader("Connection", "Close") + .build(); return chain.proceed(request); } }) From b81b3828a56e78c9a3184d1f79766eaf2973e8e0 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 2 Nov 2020 13:33:21 +0000 Subject: [PATCH 42/66] Update TestAsyncTask.java --- .../java/org/openobservatory/ooniprobe/test/TestAsyncTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index b2d4dd984..00754dfda 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -30,7 +30,7 @@ public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { public static final List SUITES = Arrays.asList(new WebsitesSuite(), - new InstantMessagingSuite(), new CircumventionSuite()); + new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite()); public static final String START = "START"; public static final String PRG = "PRG"; public static final String LOG = "LOG"; From d463f8214f657bc0b0477e43ccc17269c9bc3705 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Tue, 3 Nov 2020 11:31:53 +0000 Subject: [PATCH 43/66] Notification final fixes --- .../common/service/RunTestService.java | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index e7aa7e501..c98180b3a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -1,6 +1,7 @@ package org.openobservatory.ooniprobe.common.service; -import android.app.Notification; +import android.app.ActivityManager; +import android.app.KeyguardManager; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; @@ -12,9 +13,9 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.activity.MainActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.NotificationService; @@ -53,10 +54,10 @@ public int onStartCommand(Intent intent, int flags, int startId) { builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentTitle(getApplication().getString(R.string.Dashboard_Running_Running)) .setContentText(getApplication().getString(R.string.Dashboard_Running_PreparingTest)) + .setAutoCancel(false) .setSmallIcon(R.drawable.notification_icon) .setContentIntent(pendingIntent) .setProgress(100, 0, false) - //.addAction(android.R.drawable.ic_media_play, "Play", pplayIntent) .build(); @@ -72,14 +73,23 @@ public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } - //TODO-SERVICE test this notification if it's too intrusive when app foreground @Override public void onDestroy() { super.onDestroy(); - builder.mActions.clear(); - builder.setContentTitle(getApplicationContext().getString(R.string.Notification_FinishedRunning)) - .setProgress(0,0,false); - notificationManager.notify(1, builder.build()); + Application app = ((Application)getApplication()); + if (shouldShowNotification(this)){ + PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), + 0, MainActivity.newIntent(getApplicationContext(), R.id.testResults), 0); + builder.mActions.clear(); + builder.setContentTitle(getApplicationContext().getString(R.string.Notification_FinishedRunning)) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .setProgress(0,0,false); + + notificationManager.notify(1, builder.build()); + } + else + notificationManager.cancel(NOTIFICATION_ID); this.unregisterReceiver(receiver); } @@ -94,6 +104,17 @@ public RunTestService getService() { } } + static boolean shouldShowNotification(Context context) { + ActivityManager.RunningAppProcessInfo myProcess = new ActivityManager.RunningAppProcessInfo(); + ActivityManager.getMyMemoryState(myProcess); + if (myProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) + return true; + + KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); + // app is in foreground, but if screen is locked show notification anyway + return km.inKeyguardRestrictedInputMode(); + } + public class ActionReceiver extends BroadcastReceiver { @Override From 57318c074785a65a981588b14ee89e0d123c77e5 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 4 Nov 2020 11:04:07 +0000 Subject: [PATCH 44/66] Adjusting services classes --- app/src/main/AndroidManifest.xml | 12 +--- .../ooniprobe/common/alarm/AlarmReceiver.java | 70 ++++--------------- .../common/service/RunTestJobService.java | 33 ++++++++- .../common/service/RunTestService.java | 4 +- .../ooniprobe/common/service/ServiceUtil.java | 29 ++++++-- .../common/service/StartServiceReceiver.java | 14 ---- .../ooniprobe/test/TestAsyncTask.java | 8 ++- 7 files changed, 79 insertions(+), 91 deletions(-) delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/StartServiceReceiver.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c2d00ddf0..a0efe8fca 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -129,23 +129,13 @@ + android:label="@string/Dashboard_Card_Run"> - - - - - - testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); //Intent i = RunningActivity.newBackgroundIntent(context, testSuites); //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); Log.d(TAG, "starting test"); - //Send notification before the test starts - NotificationService.notifyTestStarted(context, websitesSuite); - //runWebConnectivity(context, app); - //context.startActivity(i); - //TestAsyncTask task = (TestAsyncTask) new TestAsyncTask(app, websitesSuite.getResult()).execute(websitesSuite.getTestList(pm)); - //Problem, the test result is shown as error until the test completes. - } - - //TODO-SERVICE-BK used for early testing. TO REMOVE - public void runWebConnectivity(Context c, Application a) { - boolean submitted = false; - String report_id_1 = "r1"; - String report_id_2 = "r2"; - OONIMKTask task = null; - Settings settings = new Settings(c, a.getPreferenceManager()); - Gson gson = a.getGson(); - settings.name = "WebConnectivity"; - settings.inputs = Collections.singletonList("http://mail.google.com"); - settings.options.max_runtime = 10; - settings.annotations.origin = TAG; - settings.options.no_collector = false; - try { - task = Engine.startExperimentTask(settings.toExperimentSettings(gson, c)); - } catch (Exception exc) { - } - while (!task.isDone()){ - try { - String json = task.waitForNextEvent(); - Log.d(TAG, json); - EventResult event = gson.fromJson(json, EventResult.class); - switch (event.key) { - case "status.report_create": - report_id_1 = event.value.report_id; - break; - case "measurement": - JsonResult jr = gson.fromJson(event.value.json_str, JsonResult.class); - report_id_2 = jr.report_id; - break; - case "failure.report_create": - case "failure.measurement_submission": - case "failure.startup": - break; - case "status.measurement_submission": - submitted = true; - break; - default: - break; - } - } catch (Exception ignored) { - } - } + Intent serviceIntent = new Intent(context, RunTestService.class); + serviceIntent.putExtra("testSuites", testSuites); + ContextCompat.startForegroundService(context, serviceIntent); + */ } } \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java index 319fa749b..ef960968f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java @@ -3,16 +3,43 @@ import android.app.job.JobParameters; import android.app.job.JobService; import android.content.Intent; +import android.util.Log; + +import androidx.core.content.ContextCompat; + +import org.openobservatory.ooniprobe.common.Application; +import org.openobservatory.ooniprobe.common.PreferenceManager; +import org.openobservatory.ooniprobe.test.suite.AbstractSuite; +import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; +import org.openobservatory.ooniprobe.test.test.AbstractTest; +import org.openobservatory.ooniprobe.test.test.WebConnectivity; + +import java.util.ArrayList; +import java.util.Arrays; public class RunTestJobService extends JobService { private static final String TAG = "SyncService"; @Override public boolean onStartJob(JobParameters params) { - Intent service = new Intent(getApplicationContext(), RunTestService.class); + //Intent service = new Intent(getApplicationContext(), RunTestService.class); + Log.d(TAG, "is started"); + //TODO-SERVICE-BK log stuff in countly + + Application app = ((Application)getApplicationContext()); + PreferenceManager pm = app.getPreferenceManager(); + AbstractSuite websitesSuite = new WebsitesSuite(); + AbstractTest webConnectivity = new WebConnectivity(); + webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); + websitesSuite.setTestList(webConnectivity); + ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); + + Intent serviceIntent = new Intent(getApplicationContext(), RunTestService.class); + serviceIntent.putExtra("testSuites", testSuites); - getApplicationContext().startService(service); - ServiceUtil.scheduleJob(getApplicationContext()); // reschedule the job + ContextCompat.startForegroundService(this, serviceIntent); + //getApplicationContext().startService(serviceIntent); + //ServiceUtil.scheduleJob(getApplicationContext()); // reschedule the job return true; } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index c98180b3a..2a267bf35 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -45,6 +45,8 @@ public void onCreate() { @Override public int onStartCommand(Intent intent, int flags, int startId) { ArrayList testSuites = (ArrayList) intent.getSerializableExtra("testSuites"); + if (testSuites == null || testSuites.size() == 0) + return 0; Application app = ((Application)getApplication()); NotificationService.setChannel(getApplicationContext(), CHANNEL_ID, app.getString(R.string.Settings_AutomatedTesting_Label)); Intent notificationIntent = new Intent(this, RunningActivity.class); @@ -84,7 +86,7 @@ public void onDestroy() { builder.setContentTitle(getApplicationContext().getString(R.string.Notification_FinishedRunning)) .setContentIntent(pendingIntent) .setAutoCancel(true) - .setProgress(0,0,false); + .setProgress(100,100,false); notificationManager.notify(1, builder.build()); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java index 714498b5d..248aeca27 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java @@ -5,17 +5,38 @@ import android.content.ComponentName; import android.content.Context; +import org.openobservatory.ooniprobe.common.Application; +import org.openobservatory.ooniprobe.common.PreferenceManager; + public class ServiceUtil { - // schedule the start of the service every 10 - 30 seconds public static void scheduleJob(Context context) { + Application app = ((Application)context.getApplicationContext()); + PreferenceManager pm = app.getPreferenceManager(); ComponentName serviceComponent = new ComponentName(context, RunTestJobService.class); JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent); - builder.setMinimumLatency(1 * 1000); // wait at least - builder.setOverrideDeadline(3 * 1000); // maximum delay - //builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); // require unmetered network + + // require unmetered network + if (pm.testWifiOnly()) { + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); + } + else + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); + + //Settings to consider for the future //builder.setRequiresDeviceIdle(true); // device should be idle //builder.setRequiresCharging(false); // we don't care if the device is charging or not + //builder.setPersisted(true); + + //.setOverrideDeadline(timeTillFutureJob) + + //Specify that this job should be delayed by the provided amount of time. + //builder.setMinimumLatency(1 * 1000); // wait at least + + //Set deadline which is the maximum scheduling latency. + //builder.setOverrideDeadline(3 * 1000); // maximum delay + + //JobScheduler is specifically designed for inexact timing, so it can combine jobs from multiple apps, to try to reduce power consumption. JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); jobScheduler.schedule(builder.build()); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/StartServiceReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/StartServiceReceiver.java deleted file mode 100644 index f28f372d9..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/StartServiceReceiver.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.openobservatory.ooniprobe.common.service; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -public class StartServiceReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - ServiceUtil.scheduleJob(context); - } -} - diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 00754dfda..d220002d0 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -2,6 +2,7 @@ import android.content.Intent; import android.os.AsyncTask; +import android.util.Log; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -31,6 +32,7 @@ public class TestAsyncTask extends AsyncTask implements AbstractTest.TestCallback { public static final List SUITES = Arrays.asList(new WebsitesSuite(), new InstantMessagingSuite(), new CircumventionSuite(), new PerformanceSuite()); + private static final String TAG = "TestAsyncTask"; public static final String START = "START"; public static final String PRG = "PRG"; public static final String LOG = "LOG"; @@ -55,7 +57,7 @@ public TestAsyncTask(Application app, ArrayList testSuites, RunTe @Override protected Void doInBackground(Void... voids) { - if (app != null){ + if (app != null && testSuites != null){ for (int suiteIdx = 0; suiteIdx < testSuites.size(); suiteIdx++){ if (!interrupt){ currentSuite = testSuites.get(suiteIdx); @@ -108,6 +110,7 @@ private void runTest(AbstractTest ... tests){ for (int i = 0; i < tests.length; i++) { if (!interrupt) { currentTest = tests[i]; + Log.d(TAG, "run next stuite: "+ currentSuite.getName() + " test:" +currentTest.getName()); currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); } } @@ -140,16 +143,19 @@ protected void onProgressUpdate(String... values) { String value = values[1]; switch (key) { case TestAsyncTask.RUN: + Log.d(TAG, "TestAsyncTask.RUN"); service.builder.setContentText(value) .setProgress(currentSuite.getTestList(app.getPreferenceManager()).length * 100, 0,false); service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; case TestAsyncTask.PRG: + Log.d(TAG, "TestAsyncTask.PRG " + value); int prgs = Integer.parseInt(value); service.builder.setProgress(currentSuite.getTestList(app.getPreferenceManager()).length * 100, prgs,false); service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); break; case TestAsyncTask.INT: + Log.d(TAG, "TestAsyncTask.INT"); service.builder.setContentText(app.getString(R.string.Dashboard_Running_Stopping_Title)) .setProgress(0, 0, true); service.notificationManager.notify(RunTestService.NOTIFICATION_ID, service.builder.build()); From db3fad69b4b8cf68c85ddb577d71ce469d9b02f7 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 4 Nov 2020 13:27:42 +0000 Subject: [PATCH 45/66] open RunningActivity and handling testSuite --- .../ooniprobe/activity/RunningActivity.java | 40 +++---------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 1a8d9f10d..22ceb3016 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -25,7 +25,6 @@ import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.common.ReachabilityManager; -import org.openobservatory.ooniprobe.common.NotificationService; import org.openobservatory.ooniprobe.common.service.RunTestService; import org.openobservatory.ooniprobe.test.TestAsyncTask; import org.openobservatory.ooniprobe.test.suite.AbstractSuite; @@ -40,7 +39,6 @@ import localhost.toolkit.app.fragment.MessageDialogFragment; public class RunningActivity extends AbstractActivity implements ConfirmDialogFragment.OnConfirmedListener, ServiceConnection { - private static final String TEST = "test"; @BindView(R.id.running) TextView running; @BindView(R.id.name) @@ -55,8 +53,6 @@ public class RunningActivity extends AbstractActivity implements ConfirmDialogFr ImageButton close; @BindView(R.id.animation) LottieAnimationView animation; - private ArrayList testSuites; - private AbstractSuite testSuite; private Integer runtime; private RunTestService service; private TestRunBroadRequestReceiver receiver; @@ -69,25 +65,19 @@ public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { - Bundle extra = new Bundle(); - extra.putSerializable(TEST, testSuites); - return new Intent(context, RunningActivity.class).putExtra(TEST, extra); - } - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(R.style.Theme_MaterialComponents_NoActionBar_App); setContentView(R.layout.activity_running); ButterKnife.bind(this); - Bundle extra = getIntent().getBundleExtra(TEST); close.setOnClickListener(new View.OnClickListener() { @Override @@ -100,18 +90,6 @@ public void onClick(View view) { .build().show(getSupportFragmentManager(), null); } }); - - testSuites = (ArrayList) extra.getSerializable(TEST); - if (testSuites == null) { - finish(); - return; - } - startService(); - } - - private void applyUIChanges(int index){ - testSuite = testSuites.get(index); - applyUIChanges(testSuite); } private void applyUIChanges(AbstractSuite testSuite){ @@ -162,12 +140,6 @@ public void onBackPressed() { Toast.makeText(this, getString(R.string.Modal_Error_CantCloseScreen), Toast.LENGTH_SHORT).show(); } - public void startService() { - Intent serviceIntent = new Intent(this, RunTestService.class); - serviceIntent.putExtra("testSuites", testSuites); - ContextCompat.startForegroundService(this, serviceIntent); - } - @Override public void onServiceConnected(ComponentName cname, IBinder binder) { RunTestService.TestBinder b = (RunTestService.TestBinder) binder; @@ -189,7 +161,7 @@ public void onReceive(Context context, Intent intent) { String value = intent.getStringExtra("value"); switch (key) { case TestAsyncTask.START: - applyUIChanges(Integer.parseInt(value)); + applyUIChanges(service.task.currentSuite); break; case TestAsyncTask.RUN: name.setText(value); @@ -208,7 +180,7 @@ public void onReceive(Context context, Intent intent) { break; case TestAsyncTask.URL: progress.setIndeterminate(false); - runtime = testSuite.getRuntime(getPreferenceManager()); + runtime = service.task.currentSuite.getRuntime(getPreferenceManager()); break; case TestAsyncTask.INT: running.setText(getString(R.string.Dashboard_Running_Stopping_Title)); From bd7966f2648482cef586e9156eb17f2dc85071ca Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 4 Nov 2020 13:27:48 +0000 Subject: [PATCH 46/66] Unused code --- .../ooniprobe/common/NotificationService.java | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index bc1796080..a060b7af8 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -29,24 +29,6 @@ public static void initNotification(Application app){ NotificationService.setToken(app); } - //TODO-SERVICE-BK remove this method - public static void notifyTestStarted(Context c, AbstractSuite testSuite) { - setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); - sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Dashboard_Running_Running)); - } - - //TODO-SERVICE-BK check this method - public static void notifyTestError(Context c, AbstractSuite testSuite) { - setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); - sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Modal_Error)); - } - - //TODO-SERVICE-BK check remove method (it's unified with RunTestService.onDestroy - public static void notifyTestEnded(Context c, AbstractSuite testSuite) { - setChannel(c, TEST_RUN, c.getString(R.string.Settings_Notifications_OnTestCompletion)); - sendNotification(c, c.getString(R.string.General_AppName), c.getString(testSuite.getTitle()) + " " + c.getString(R.string.Notification_FinishedRunning)); - } - /* * Used for local notification, ex "test has finished running" */ From 07100d8fef519d5439a3097266e6fee5d7b28b01 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 4 Nov 2020 13:28:02 +0000 Subject: [PATCH 47/66] Test new scheduling --- .../ooniprobe/common/service/RunTestService.java | 1 - .../ooniprobe/common/service/ServiceUtil.java | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 2a267bf35..1a7b2d5e5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -78,7 +78,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { @Override public void onDestroy() { super.onDestroy(); - Application app = ((Application)getApplication()); if (shouldShowNotification(this)){ PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, MainActivity.newIntent(getApplicationContext(), R.id.testResults), 0); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java index 248aeca27..da618de03 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java @@ -11,6 +11,7 @@ public class ServiceUtil { public static void scheduleJob(Context context) { + System.out.println("SyncService scheduleJob"); Application app = ((Application)context.getApplicationContext()); PreferenceManager pm = app.getPreferenceManager(); ComponentName serviceComponent = new ComponentName(context, RunTestJobService.class); @@ -30,11 +31,21 @@ public static void scheduleJob(Context context) { //.setOverrideDeadline(timeTillFutureJob) + //job will fire after 5 seconds when the network becomes available, or no later than 5 minutes + //Specify that this job should be delayed by the provided amount of time. - //builder.setMinimumLatency(1 * 1000); // wait at least + //builder.setMinimumLatency(5 * 1000); // wait at least + //the job will be executed anyway after 5 minutes waiting + //java.lang.IllegalArgumentException: Can't call setOverrideDeadline() on a periodic job //Set deadline which is the maximum scheduling latency. - //builder.setOverrideDeadline(3 * 1000); // maximum delay + //builder.setOverrideDeadline(5 * 60 * 1000); // maximum delay + + builder.setPersisted(true); //Job scheduled to work after reboot + + /* Minimum flex for a periodic job, in milliseconds. */ + //http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/job/JobInfo.java#110 + builder.setPeriodic(30 * 60 * 1000); //JobScheduler is specifically designed for inexact timing, so it can combine jobs from multiple apps, to try to reduce power consumption. JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); From 9440c9967a924b4ac2ebcaa428869ed8da892a3c Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 5 Nov 2020 13:48:16 +0000 Subject: [PATCH 48/66] Last testing --- .../ooniprobe/common/alarm/AlarmService.java | 2 +- .../ooniprobe/common/service/ServiceUtil.java | 22 ++++++++++--------- .../ooniprobe/test/TestAsyncTask.java | 2 ++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java index b80723f7f..2150602f5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java @@ -32,7 +32,7 @@ public static void setRecurringAlarm(Context context) { AlarmManager alarms = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE); alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), - AlarmManager.INTERVAL_DAY, recurringAlarm); + AlarmManager.INTERVAL_HOUR*2, recurringAlarm); } public static void cancelRecurringAlarm(Context context) { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java index da618de03..740030f2c 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java @@ -17,16 +17,14 @@ public static void scheduleJob(Context context) { ComponentName serviceComponent = new ComponentName(context, RunTestJobService.class); JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent); - // require unmetered network - if (pm.testWifiOnly()) { - builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); - } - else - builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); + int networkConstraint = pm.testWifiOnly() ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY; + builder.setRequiredNetworkType(networkConstraint); + + //TODO options to consider for the future https://github.com/ooni/probe/issues/916#issuecomment-722268148 //Settings to consider for the future //builder.setRequiresDeviceIdle(true); // device should be idle - //builder.setRequiresCharging(false); // we don't care if the device is charging or not + //builder.setRequiresCharging(true); //builder.setPersisted(true); //.setOverrideDeadline(timeTillFutureJob) @@ -36,16 +34,20 @@ public static void scheduleJob(Context context) { //Specify that this job should be delayed by the provided amount of time. //builder.setMinimumLatency(5 * 1000); // wait at least + //https://www.coderzheaven.com/2016/11/22/how-to-create-a-simple-repeating-job-using-jobscheduler-in-android/ //the job will be executed anyway after 5 minutes waiting //java.lang.IllegalArgumentException: Can't call setOverrideDeadline() on a periodic job //Set deadline which is the maximum scheduling latency. - //builder.setOverrideDeadline(5 * 60 * 1000); // maximum delay - builder.setPersisted(true); //Job scheduled to work after reboot + //Without this option it doesn't work at all + //builder.setOverrideDeadline(1 * 60 * 1000); // maximum delay + builder.setOverrideDeadline(0); // maximum delay + //builder.setPersisted(true); //Job scheduled to work after reboot + //builder.setBackoffCriteria() /* Minimum flex for a periodic job, in milliseconds. */ //http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/job/JobInfo.java#110 - builder.setPeriodic(30 * 60 * 1000); + //builder.setPeriodic(30 * 60 * 1000); //JobScheduler is specifically designed for inexact timing, so it can combine jobs from multiple apps, to try to reduce power consumption. JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index d220002d0..7ea269c72 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -131,6 +131,7 @@ private void runTest(AbstractTest ... tests){ } @Override public final void onLog(String log) { + //TODO LOG if (!isInterrupted()) publishProgress(LOG, log); } @@ -167,6 +168,7 @@ protected void onProgressUpdate(String... values) { protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); sendBroadcast(END); + System.out.println("SyncService ended test"); service.stopSelf(); } From c80cbfb9e4ea7d2ba2f055424dacdf729d6529ef Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 5 Nov 2020 20:13:16 +0000 Subject: [PATCH 49/66] Null checking --- .../ooniprobe/activity/RunningActivity.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 22ceb3016..ec05ce94c 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -92,34 +92,44 @@ public void onClick(View view) { }); } - private void applyUIChanges(AbstractSuite testSuite){ - if (testSuite == null) + private void applyUIChanges(){ + //TODO rename in assumenotnull + if (service == null || service.task == null || + service.task.currentSuite == null || service.task.currentTest == null) { + System.out.println("RunningActivity currentSuite is null"); return; - runtime = testSuite.getRuntime(getPreferenceManager()); - getWindow().setBackgroundDrawableResource(testSuite.getColor()); - if (Build.VERSION.SDK_INT >= 21) { - getWindow().setStatusBarColor(testSuite.getColor()); } + else + System.out.println("RunningActivity currentSuite FOUND"); animation.setImageAssetsFolder("anim/"); - animation.setAnimation(testSuite.getAnim()); animation.setRepeatCount(Animation.INFINITE); animation.playAnimation(); progress.setIndeterminate(true); eta.setText(R.string.Dashboard_Running_CalculatingETA); - progress.setMax(testSuite.getTestList(getPreferenceManager()).length * 100); + + name.setText(getString(service.task.currentTest.getLabelResId())); + runtime = service.task.currentSuite.getRuntime(getPreferenceManager()); + 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(getPreferenceManager()).length * 100); } @Override protected void onResume() { super.onResume(); - if (!isTestRunning()) - testEnded(this); IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity"); receiver = new TestRunBroadRequestReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); //Bind the RunTestService Intent intent= new Intent(this, RunTestService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); + if (!isTestRunning()) + testEnded(this); + else + applyUIChanges(); } @Override @@ -144,11 +154,11 @@ public void onBackPressed() { public void onServiceConnected(ComponentName cname, IBinder binder) { RunTestService.TestBinder b = (RunTestService.TestBinder) binder; service = b.getService(); - applyUIChanges(service.task.currentSuite); - if (service.task.currentTest != null) - name.setText(getString(service.task.currentTest.getLabelResId())); + System.out.println("RunningActivity service connected"); + applyUIChanges(); } + @Override public void onServiceDisconnected(ComponentName name) { service = null; @@ -161,16 +171,18 @@ public void onReceive(Context context, Intent intent) { String value = intent.getStringExtra("value"); switch (key) { case TestAsyncTask.START: - applyUIChanges(service.task.currentSuite); + applyUIChanges(); break; case TestAsyncTask.RUN: name.setText(value); break; case TestAsyncTask.PRG: - progress.setIndeterminate(false); int prgs = Integer.parseInt(value); + progress.setIndeterminate(false); progress.setProgress(prgs); - eta.setText(getString(R.string.Dashboard_Running_Seconds, String.valueOf(Math.round(runtime - ((double) prgs) / progress.getMax() * runtime)))); + 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); From 8c30d799a1c6b8e1b04e03b5b786000138445dc3 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Thu, 5 Nov 2020 20:13:21 +0000 Subject: [PATCH 50/66] last todo --- .../java/org/openobservatory/ooniprobe/test/TestAsyncTask.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 7ea269c72..a7af18cf1 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -73,6 +73,7 @@ protected Void doInBackground(Void... voids) { } private void runTest(AbstractTest ... tests){ + //TODO the UI doesn't update because for websites currentTest is null on start try { boolean downloadUrls = false; for (AbstractTest abstractTest : tests) From a5516f9c72ab32a9872372ea87ef121a3a00ae7f Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 9 Nov 2020 13:16:24 +0000 Subject: [PATCH 51/66] Removing background service classes --- app/src/fdroid/res/xml/preferences_global.xml | 29 -------- app/src/main/AndroidManifest.xml | 19 ----- .../ooniprobe/common/PreferenceManager.java | 28 -------- .../ooniprobe/common/alarm/AlarmReceiver.java | 72 ------------------- .../ooniprobe/common/alarm/AlarmService.java | 48 ------------- .../common/alarm/OnBootReceiver.java | 22 ------ .../common/service/RunTestJobService.java | 50 ------------- .../ooniprobe/common/service/ServiceUtil.java | 56 --------------- .../fragment/PreferenceFragment.java | 51 ------------- app/src/main/res/values/untraslatable.xml | 6 -- app/src/main/res/xml/preferences_global.xml | 29 -------- 11 files changed, 410 deletions(-) delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/alarm/OnBootReceiver.java delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java delete mode 100644 app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index 6bac0da8f..92bca5a35 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -1,35 +1,6 @@ - - - - - - - - - - - - - - - - diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java index 9c67c5214..beaa5f358 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java @@ -59,34 +59,10 @@ public Integer getMaxRuntime() { } } - public Integer getMaxRuntimeAutoTest() { - if (!isMaxRuntimeAutoTestEnabled()) - return MAX_RUNTIME_DISABLED; - try { - return Integer.parseInt(sp.getString(r.getString(R.string.automated_testing_max_runtime), "90")); - } catch (Exception e) { - return 90; - } - } - public String getAutomatedTestingTime() { - try { - String local_notifications_time = sp.getString(r.getString(R.string.automated_testing_time), "05:00"); - String[] separated = local_notifications_time.split(":"); - int hours = Integer.valueOf(separated[0]); - int minutes = Integer.valueOf(separated[1]); - return String.format("%02d", hours) + ":" +String.format("%02d", minutes); - } catch (Exception e) { - return "05:00"; - } - } public boolean isMaxRuntimeEnabled(){ return sp.getBoolean(r.getString(R.string.max_runtime_enabled), true); } - public boolean isMaxRuntimeAutoTestEnabled(){ - return sp.getBoolean(r.getString(R.string.automated_testing_max_runtime_enabled), false); - } - public boolean isSendCrash() { return sp.getBoolean(r.getString(R.string.send_crash), true); } @@ -265,8 +241,4 @@ public long getAppOpenCount(){ return sp.getLong(IS_NOTIFICATION_DIALOG, 0); } - public boolean testWifiOnly() { - return sp.getBoolean(r.getString(R.string.automated_testing_wifionly), true); - } - } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java deleted file mode 100644 index 7e37e6dbe..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmReceiver.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.openobservatory.ooniprobe.common.alarm; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import androidx.core.content.ContextCompat; - -import com.google.gson.Gson; - -import org.openobservatory.engine.Engine; -import org.openobservatory.engine.OONIMKTask; -import org.openobservatory.ooniprobe.common.Application; -import org.openobservatory.ooniprobe.common.NotificationService; -import org.openobservatory.ooniprobe.common.PreferenceManager; -import org.openobservatory.ooniprobe.common.ReachabilityManager; -import org.openobservatory.ooniprobe.common.service.RunTestService; -import org.openobservatory.ooniprobe.common.service.ServiceUtil; -import org.openobservatory.ooniprobe.model.jsonresult.EventResult; -import org.openobservatory.ooniprobe.model.jsonresult.JsonResult; -import org.openobservatory.ooniprobe.model.settings.Settings; -import org.openobservatory.ooniprobe.test.TestAsyncTask; -import org.openobservatory.ooniprobe.test.suite.AbstractSuite; -import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; -import org.openobservatory.ooniprobe.test.test.AbstractTest; -import org.openobservatory.ooniprobe.test.test.WebConnectivity; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - -public class AlarmReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - System.out.println("SyncService alarm received"); - ServiceUtil.scheduleJob(context); - /* - Application app = ((Application)context.getApplicationContext()); - PreferenceManager pm = app.getPreferenceManager(); - AbstractSuite websitesSuite = new WebsitesSuite(); - AbstractTest webConnectivity = new WebConnectivity(); - - //Abort test in case the user is not connected to WiFi - if (pm.testWifiOnly() && - !ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.WIFI)) { - Log.d(TAG, "is wifi only and not wifi, aborting"); - NotificationService.notifyTestError(context, websitesSuite); - //return; - } - - if (!ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) { - Log.d(TAG, "no internet available"); - NotificationService.notifyTestError(context, websitesSuite); - //return; - } - - webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); - websitesSuite.setTestList(webConnectivity); - ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); - //Intent i = RunningActivity.newBackgroundIntent(context, testSuites); - //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Log.d(TAG, "starting test"); - - Intent serviceIntent = new Intent(context, RunTestService.class); - serviceIntent.putExtra("testSuites", testSuites); - ContextCompat.startForegroundService(context, serviceIntent); - */ - } - -} \ No newline at end of file diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java deleted file mode 100644 index 2150602f5..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/AlarmService.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.openobservatory.ooniprobe.common.alarm; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; - -import org.openobservatory.ooniprobe.common.Application; - -import java.util.Calendar; - -/** - * https://code.tutsplus.com/tutorials/android-fundamentals-scheduling-recurring-tasks--mobile-5788 - */ -public class AlarmService { - public static void setRecurringAlarm(Context context) { - cancelRecurringAlarm(context); - String time = ((Application) context).getPreferenceManager().getAutomatedTestingTime(); - String[] separated = time.split(":"); - int hours = Integer.parseInt(separated[0]); - int minutes = Integer.parseInt(separated[1]); - - Calendar updateTime = Calendar.getInstance(); - updateTime.setTimeZone(updateTime.getTimeZone()); - updateTime.set(Calendar.HOUR_OF_DAY, hours); - updateTime.set(Calendar.MINUTE, minutes); - updateTime.set(Calendar.SECOND, 0); - - Intent alarm = new Intent(context, AlarmReceiver.class); - PendingIntent recurringAlarm = PendingIntent.getBroadcast(context, - 0, alarm, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarms = (AlarmManager) context.getSystemService( - Context.ALARM_SERVICE); - alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), - AlarmManager.INTERVAL_HOUR*2, recurringAlarm); - } - - public static void cancelRecurringAlarm(Context context) { - Intent alarm = new Intent(context, AlarmReceiver.class); - PendingIntent recurringAlarm = PendingIntent.getBroadcast(context, - 0, alarm, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager alarms = (AlarmManager) context.getSystemService( - Context.ALARM_SERVICE); - if (alarms!= null) { - alarms.cancel(recurringAlarm); - } - } -} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/OnBootReceiver.java b/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/OnBootReceiver.java deleted file mode 100644 index a7d5258c8..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/alarm/OnBootReceiver.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.openobservatory.ooniprobe.common.alarm; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import org.openobservatory.ooniprobe.R; - -public class OnBootReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - if (preferences.getBoolean(context.getString(R.string.automated_testing_enabled), false)){ - AlarmService.setRecurringAlarm(context); - } - } - } - -} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java deleted file mode 100644 index ef960968f..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestJobService.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.openobservatory.ooniprobe.common.service; - -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.content.Intent; -import android.util.Log; - -import androidx.core.content.ContextCompat; - -import org.openobservatory.ooniprobe.common.Application; -import org.openobservatory.ooniprobe.common.PreferenceManager; -import org.openobservatory.ooniprobe.test.suite.AbstractSuite; -import org.openobservatory.ooniprobe.test.suite.WebsitesSuite; -import org.openobservatory.ooniprobe.test.test.AbstractTest; -import org.openobservatory.ooniprobe.test.test.WebConnectivity; - -import java.util.ArrayList; -import java.util.Arrays; - -public class RunTestJobService extends JobService { - private static final String TAG = "SyncService"; - - @Override - public boolean onStartJob(JobParameters params) { - //Intent service = new Intent(getApplicationContext(), RunTestService.class); - Log.d(TAG, "is started"); - //TODO-SERVICE-BK log stuff in countly - - Application app = ((Application)getApplicationContext()); - PreferenceManager pm = app.getPreferenceManager(); - AbstractSuite websitesSuite = new WebsitesSuite(); - AbstractTest webConnectivity = new WebConnectivity(); - webConnectivity.setMax_runtime(pm.getMaxRuntimeAutoTest()); - websitesSuite.setTestList(webConnectivity); - ArrayList testSuites = new ArrayList<>(Arrays.asList(websitesSuite)); - - Intent serviceIntent = new Intent(getApplicationContext(), RunTestService.class); - serviceIntent.putExtra("testSuites", testSuites); - - ContextCompat.startForegroundService(this, serviceIntent); - //getApplicationContext().startService(serviceIntent); - //ServiceUtil.scheduleJob(getApplicationContext()); // reschedule the job - return true; - } - - @Override - public boolean onStopJob(JobParameters params) { - return true; - } -} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java deleted file mode 100644 index 740030f2c..000000000 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/ServiceUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.openobservatory.ooniprobe.common.service; - -import android.app.job.JobInfo; -import android.app.job.JobScheduler; -import android.content.ComponentName; -import android.content.Context; - -import org.openobservatory.ooniprobe.common.Application; -import org.openobservatory.ooniprobe.common.PreferenceManager; - - -public class ServiceUtil { - public static void scheduleJob(Context context) { - System.out.println("SyncService scheduleJob"); - Application app = ((Application)context.getApplicationContext()); - PreferenceManager pm = app.getPreferenceManager(); - ComponentName serviceComponent = new ComponentName(context, RunTestJobService.class); - JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent); - - int networkConstraint = pm.testWifiOnly() ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY; - builder.setRequiredNetworkType(networkConstraint); - - //TODO options to consider for the future https://github.com/ooni/probe/issues/916#issuecomment-722268148 - - //Settings to consider for the future - //builder.setRequiresDeviceIdle(true); // device should be idle - //builder.setRequiresCharging(true); - //builder.setPersisted(true); - - //.setOverrideDeadline(timeTillFutureJob) - - //job will fire after 5 seconds when the network becomes available, or no later than 5 minutes - - //Specify that this job should be delayed by the provided amount of time. - //builder.setMinimumLatency(5 * 1000); // wait at least - - //https://www.coderzheaven.com/2016/11/22/how-to-create-a-simple-repeating-job-using-jobscheduler-in-android/ - //the job will be executed anyway after 5 minutes waiting - //java.lang.IllegalArgumentException: Can't call setOverrideDeadline() on a periodic job - //Set deadline which is the maximum scheduling latency. - - //Without this option it doesn't work at all - //builder.setOverrideDeadline(1 * 60 * 1000); // maximum delay - builder.setOverrideDeadline(0); // maximum delay - - //builder.setPersisted(true); //Job scheduled to work after reboot - //builder.setBackoffCriteria() - /* Minimum flex for a periodic job, in milliseconds. */ - //http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/app/job/JobInfo.java#110 - //builder.setPeriodic(30 * 60 * 1000); - - //JobScheduler is specifically designed for inexact timing, so it can combine jobs from multiple apps, to try to reduce power consumption. - JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); - jobScheduler.schedule(builder.build()); - } -} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java index eac9faf7d..2f7fe02e3 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/PreferenceFragment.java @@ -1,14 +1,11 @@ package org.openobservatory.ooniprobe.fragment; -import android.annotation.TargetApi; -import android.app.TimePickerDialog; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; -import android.widget.TimePicker; import android.widget.Toast; import androidx.annotation.IdRes; @@ -24,11 +21,7 @@ import org.openobservatory.ooniprobe.activity.MainActivity; import org.openobservatory.ooniprobe.activity.PreferenceActivity; import org.openobservatory.ooniprobe.common.Application; -import org.openobservatory.ooniprobe.common.alarm.AlarmService; -import java.text.NumberFormat; -import java.util.Calendar; -import java.util.Locale; import java.util.Arrays; import org.openobservatory.ooniprobe.common.CountlyManager; import org.openobservatory.ooniprobe.common.NotificationService; @@ -54,29 +47,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { this.rootKey = rootKey; } - private void showDateDialog(Preference timePreference) { - Calendar mcurrentTime = Calendar.getInstance(); - int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY); - int minute = mcurrentTime.get(Calendar.MINUTE); - TimePickerDialog mTimePicker; - mTimePicker = new TimePickerDialog(getActivity(), new TimePickerDialog.OnTimeSetListener() { - @Override - public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) { - Locale en_locale = new Locale("en","EN"); - NumberFormat nf = NumberFormat.getInstance(en_locale); - int hour = Integer.parseInt(nf.format(selectedHour)); - int minute = Integer.parseInt(nf.format(selectedMinute)); - String time = String.format(en_locale, "%02d", hour) + ":" + String.format(en_locale, "%02d", minute); - SharedPreferences.Editor editor = getPreferenceScreen().getSharedPreferences().edit(); - editor.putString(getActivity().getString(R.string.automated_testing_time), time); - editor.apply(); - timePreference.setSummary(String.format("%02d", selectedHour) + ":" + String.format("%02d", selectedMinute)); - AlarmService.setRecurringAlarm(getActivity().getApplication()); - } - }, hour, minute, true); - mTimePicker.show(); - } - @Override public void onResume() { assert getArguments() != null; @@ -85,20 +55,6 @@ public void onResume() { getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); getActivity().setTitle(getPreferenceScreen().getTitle()); - Preference timePreference = findPreference(getActivity().getString(R.string.automated_testing_time)); - if (timePreference != null){ - String time = ((Application) getActivity().getApplication()).getPreferenceManager().getAutomatedTestingTime(); - timePreference.setSummary(time); - timePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - @Override - public boolean onPreferenceClick(Preference preference) { - showDateDialog(timePreference); - return false; - } - }); - } - for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) { if (getPreferenceScreen().getPreference(i) instanceof EditTextPreference) { EditTextPreference editTextPreference = (EditTextPreference) getPreferenceScreen().getPreference(i); @@ -141,13 +97,6 @@ public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragme public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { Preference preference = findPreference(key); - if (key.equals(getString(R.string.automated_testing_enabled))) { - if (sharedPreferences.getBoolean(key, false)) - //Enabling the alarm every time the user enabled automated_testing - AlarmService.setRecurringAlarm(getActivity().getApplication()); - else - AlarmService.cancelRecurringAlarm(getActivity().getApplication()); - } if (key.equals(getString(R.string.send_crash)) || key.equals(getString(R.string.send_analytics)) || key.equals(getString(R.string.notifications_enabled))){ diff --git a/app/src/main/res/values/untraslatable.xml b/app/src/main/res/values/untraslatable.xml index 558ba82fe..9149d4cab 100644 --- a/app/src/main/res/values/untraslatable.xml +++ b/app/src/main/res/values/untraslatable.xml @@ -3,7 +3,6 @@ 30 preferences notifications - automated_testing sharing test_options privacy @@ -18,11 +17,6 @@ notifications_enabled notifications_completion notifications_news - automated_testing_enabled - automated_testing_time - automated_testing_wifionly - automated_testing_max_runtime_enabled - automated_testing_max_runtime upload_results upload_results_manual include_ip diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 89b5fe388..254577d63 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -11,35 +11,6 @@ android:title="@string/Settings_Notifications_Enabled" /> - - - - - - - Date: Mon, 9 Nov 2020 14:06:35 +0000 Subject: [PATCH 52/66] Separate runTest and downloadURLs --- .../ooniprobe/test/TestAsyncTask.java | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index a7af18cf1..619b32e1d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -73,44 +73,13 @@ protected Void doInBackground(Void... voids) { } private void runTest(AbstractTest ... tests){ - //TODO the UI doesn't update because for websites currentTest is null on start try { - boolean downloadUrls = false; - for (AbstractTest abstractTest : tests) - if (abstractTest instanceof WebConnectivity && abstractTest.getInputs() == null) { - downloadUrls = true; - break; - } - if (downloadUrls) { - String probeCC = "XX"; - try { - probeCC = Engine.resolveProbeCC( - app, - BuildConfig.SOFTWARE_NAME, - BuildConfig.VERSION_NAME, - 30 - ); - } - catch (Exception e) { - e.printStackTrace(); - ExceptionManager.logException(e); - } - Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); - if (response.isSuccessful() && response.body() != null && response.body().results != null) { - ArrayList inputs = new ArrayList<>(); - for (Url url : response.body().results) - inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); - for (AbstractTest abstractTest : tests) { - abstractTest.setInputs(inputs); - if (abstractTest.getMax_runtime() == null) - abstractTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); - } - publishProgress(URL); - } - } for (int i = 0; i < tests.length; i++) { if (!interrupt) { currentTest = tests[i]; + if (currentTest instanceof WebConnectivity && currentTest.getInputs() == null) { + downloadURLs(); + } Log.d(TAG, "run next stuite: "+ currentSuite.getName() + " test:" +currentTest.getName()); currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); } @@ -122,6 +91,32 @@ private void runTest(AbstractTest ... tests){ } } + private void downloadURLs(){ + String probeCC = "XX"; + try { + probeCC = Engine.resolveProbeCC( + app, + BuildConfig.SOFTWARE_NAME, + BuildConfig.VERSION_NAME, + 30 + ); + Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); + if (response.isSuccessful() && response.body() != null && response.body().results != null) { + ArrayList inputs = new ArrayList<>(); + for (Url url : response.body().results) + inputs.add(Url.checkExistingUrl(url.url, url.category_code, url.country_code).url); + currentTest.setInputs(inputs); + if (currentTest.getMax_runtime() == null) + currentTest.setMax_runtime(app.getPreferenceManager().getMaxRuntime()); + publishProgress(URL); + } + } + catch (Exception e) { + e.printStackTrace(); + ExceptionManager.logException(e); + } + } + @Override public void onStart(String name) { publishProgress(RUN, name); } From 90ef7a3cd4ea961eeb4a6ba014a2dc3997722ade Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Tue, 10 Nov 2020 09:51:24 +0000 Subject: [PATCH 53/66] Fix crash --- .../ooniprobe/activity/RunningActivity.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index ec05ce94c..427a07914 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -56,6 +56,7 @@ public class RunningActivity extends AbstractActivity implements ConfirmDialogFr private Integer runtime; private RunTestService service; private TestRunBroadRequestReceiver receiver; + boolean isBound = false; public static Intent newIntent(AbstractActivity context, ArrayList testSuites) { if (ReachabilityManager.getNetworkType(context).equals(ReachabilityManager.NO_INTERNET)) { @@ -93,14 +94,10 @@ public void onClick(View view) { } private void applyUIChanges(){ - //TODO rename in assumenotnull if (service == null || service.task == null || service.task.currentSuite == null || service.task.currentTest == null) { - System.out.println("RunningActivity currentSuite is null"); return; } - else - System.out.println("RunningActivity currentSuite FOUND"); animation.setImageAssetsFolder("anim/"); animation.setRepeatCount(Animation.INFINITE); animation.playAnimation(); @@ -120,22 +117,26 @@ private void applyUIChanges(){ @Override protected void onResume() { super.onResume(); + if (!isTestRunning()) { + testEnded(this); + return; + } IntentFilter filter = new IntentFilter("org.openobservatory.ooniprobe.activity.RunningActivity"); receiver = new TestRunBroadRequestReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); //Bind the RunTestService + //TODO this create a new intent if the previous was destroyed. not good Intent intent= new Intent(this, RunTestService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); - if (!isTestRunning()) - testEnded(this); - else - applyUIChanges(); } @Override protected void onPause() { super.onPause(); - unbindService(this); + if (isBound) { + unbindService(this); + isBound = false; + } LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); } @@ -154,7 +155,7 @@ public void onBackPressed() { public void onServiceConnected(ComponentName cname, IBinder binder) { RunTestService.TestBinder b = (RunTestService.TestBinder) binder; service = b.getService(); - System.out.println("RunningActivity service connected"); + isBound = true; applyUIChanges(); } From 08bdf6c6ff57cae7556953656e02d33cc2956ddb Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 16 Nov 2020 16:26:42 +0000 Subject: [PATCH 54/66] Removed comments --- .../openobservatory/ooniprobe/activity/RunningActivity.java | 3 +-- .../java/org/openobservatory/ooniprobe/test/TestAsyncTask.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 427a07914..8b80031d0 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -125,8 +125,7 @@ protected void onResume() { receiver = new TestRunBroadRequestReceiver(); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); //Bind the RunTestService - //TODO this create a new intent if the previous was destroyed. not good - Intent intent= new Intent(this, RunTestService.class); + Intent intent = new Intent(this, RunTestService.class); bindService(intent, this, Context.BIND_AUTO_CREATE); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 619b32e1d..0bb1fb75d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -127,7 +127,6 @@ private void downloadURLs(){ } @Override public final void onLog(String log) { - //TODO LOG if (!isInterrupted()) publishProgress(LOG, log); } From a69edff6a0d2910d05811826b46fa88ff342be71 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 20 Nov 2020 10:03:20 +0000 Subject: [PATCH 55/66] Update preferences_global.xml --- app/src/fdroid/res/xml/preferences_global.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/fdroid/res/xml/preferences_global.xml b/app/src/fdroid/res/xml/preferences_global.xml index c3fea5c76..c54f27eaa 100644 --- a/app/src/fdroid/res/xml/preferences_global.xml +++ b/app/src/fdroid/res/xml/preferences_global.xml @@ -200,7 +200,7 @@ android:title="@string/CategoryCode_MILX_Name" /> Date: Fri, 20 Nov 2020 10:04:19 +0000 Subject: [PATCH 56/66] Update AndroidManifest.xml --- app/src/main/AndroidManifest.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e294cce22..488751390 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,9 +2,7 @@ package="org.openobservatory.ooniprobe"> - - From 93d381510d49060c385ac93aa8f235d8ec930ed4 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 20 Nov 2020 10:06:19 +0000 Subject: [PATCH 57/66] Update MainActivity.java --- .../org/openobservatory/ooniprobe/activity/MainActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java index 15b865a0e..c0e8b0e77 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java @@ -94,7 +94,6 @@ else if (getPreferenceManager().getAppOpenCount() == PreferenceManager.NOTIFICAT @Override protected void onResume() { super.onResume(); //TODO-SERVICE show RunningActivity - //if (isTestRunning()) } @Override From e53e0978bf527552ac403cca8ab972e3ef7bfb62 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Fri, 20 Nov 2020 10:06:22 +0000 Subject: [PATCH 58/66] Update preferences_global.xml --- app/src/main/res/xml/preferences_global.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/xml/preferences_global.xml b/app/src/main/res/xml/preferences_global.xml index 26a8bce34..496712a20 100644 --- a/app/src/main/res/xml/preferences_global.xml +++ b/app/src/main/res/xml/preferences_global.xml @@ -210,7 +210,7 @@ android:title="@string/CategoryCode_MILX_Name" /> Date: Tue, 24 Nov 2020 09:22:44 +0000 Subject: [PATCH 59/66] Fixing interrupt problem --- .../ooniprobe/activity/RunningActivity.java | 1 + .../ooniprobe/test/TestAsyncTask.java | 15 +++++++-------- .../ooniprobe/test/test/AbstractTest.java | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 71d6aa6e3..b73f5c7d0 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -198,6 +198,7 @@ public void onReceive(Context context, Intent intent) { 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; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index 0bb1fb75d..aacd064f9 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -75,11 +75,11 @@ protected Void doInBackground(Void... voids) { private void runTest(AbstractTest ... tests){ try { for (int i = 0; i < tests.length; i++) { + currentTest = tests[i]; + if (currentTest instanceof WebConnectivity && currentTest.getInputs() == null) { + downloadURLs(); + } if (!interrupt) { - currentTest = tests[i]; - if (currentTest instanceof WebConnectivity && currentTest.getInputs() == null) { - downloadURLs(); - } Log.d(TAG, "run next stuite: "+ currentSuite.getName() + " test:" +currentTest.getName()); currentTest.run(app, app.getPreferenceManager(), app.getGson(), result, i, this); } @@ -163,7 +163,6 @@ protected void onProgressUpdate(String... values) { protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); sendBroadcast(END); - System.out.println("SyncService ended test"); service.stopSelf(); } @@ -181,10 +180,10 @@ public synchronized boolean isInterrupted() { } public synchronized void interrupt(){ - if(currentTest.canInterrupt()) { - interrupt = true; + if(currentTest != null && currentTest.canInterrupt()) { currentTest.interrupt(); - sendBroadcast(INT); } + interrupt = true; + sendBroadcast(INT); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java index d12764d3a..3186d5a2f 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java @@ -186,8 +186,9 @@ public boolean canInterrupt(){ } public void interrupt(){ - if(task.canInterrupt()) + if(task.canInterrupt()) { task.interrupt(); + } } @CallSuper From 7c530b41c37767569beba00b6e064408802129bc Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Tue, 24 Nov 2020 10:00:16 +0000 Subject: [PATCH 60/66] Remove vibration and sounds --- .../ooniprobe/common/NotificationService.java | 9 +++++++-- .../ooniprobe/common/service/RunTestService.java | 5 ++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java index a060b7af8..12630b1a5 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/NotificationService.java @@ -25,7 +25,7 @@ public static void initNotification(Application app){ if (!preferenceManager.isNotifications()) return; CountlyPush.init(app, BuildConfig.DEBUG? Countly.CountlyMessagingMode.TEST:Countly.CountlyMessagingMode.PRODUCTION); - NotificationService.setChannel(app, CountlyPush.CHANNEL_ID, app.getString(R.string.Settings_Notifications_Label)); + NotificationService.setChannel(app, CountlyPush.CHANNEL_ID, app.getString(R.string.Settings_Notifications_Label), true, true, true); NotificationService.setToken(app); } @@ -57,11 +57,16 @@ private static void setToken(Application a){ } // Register the channel with the system - public static void setChannel(Context c, String channelID, String channelName){ + public static void setChannel(Context c, String channelID, String channelName, + Boolean vibration, Boolean sound, Boolean lights){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager notificationManager = (NotificationManager) c.getSystemService(Context.NOTIFICATION_SERVICE); if (notificationManager != null) { NotificationChannel channel = new NotificationChannel(channelID, channelName, NotificationManager.IMPORTANCE_DEFAULT); + channel.enableVibration(vibration); + channel.enableLights(lights); + if (!sound) + channel.setSound(null, null); notificationManager.createNotificationChannel(channel); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 1a7b2d5e5..315702b90 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -2,6 +2,7 @@ import android.app.ActivityManager; import android.app.KeyguardManager; +import android.app.Notification; import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; @@ -48,7 +49,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { if (testSuites == null || testSuites.size() == 0) return 0; Application app = ((Application)getApplication()); - NotificationService.setChannel(getApplicationContext(), CHANNEL_ID, app.getString(R.string.Settings_AutomatedTesting_Label)); + NotificationService.setChannel(getApplicationContext(), CHANNEL_ID, app.getString(R.string.Settings_AutomatedTesting_Label), false, false, false); Intent notificationIntent = new Intent(this, RunningActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); @@ -62,7 +63,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { .setProgress(100, 0, false) .build(); - task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); Intent broadcastIntent = new Intent(); @@ -86,7 +86,6 @@ public void onDestroy() { .setContentIntent(pendingIntent) .setAutoCancel(true) .setProgress(100,100,false); - notificationManager.notify(1, builder.build()); } else From 6844b57a3391a3b33fd434902160937ed44cab06 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Wed, 25 Nov 2020 15:08:30 +0000 Subject: [PATCH 61/66] removing icon --- app/src/main/AndroidManifest.xml | 2 +- .../ooniprobe/common/service/RunTestService.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 488751390..a1fd4ad1d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -126,7 +126,7 @@ diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 315702b90..45af7f338 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -68,8 +68,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { Intent broadcastIntent = new Intent(); broadcastIntent.setAction(RunTestService.ACTION_INTERRUPT); PendingIntent pIntent = PendingIntent.getBroadcast(this,1, broadcastIntent,PendingIntent.FLAG_UPDATE_CURRENT); - builder.addAction(R.drawable.ooni_logo, "STOP TEST", pIntent); - + builder.addAction(0, "STOP TEST", pIntent); startForeground(NOTIFICATION_ID, builder.build()); return START_NOT_STICKY; From 568f508091056c57e2c99e030625657acef0e343 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Nov 2020 09:05:52 +0000 Subject: [PATCH 62/66] Localize string --- .../ooniprobe/common/service/RunTestService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 45af7f338..00db21e54 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -68,7 +68,7 @@ public int onStartCommand(Intent intent, int flags, int startId) { Intent broadcastIntent = new Intent(); broadcastIntent.setAction(RunTestService.ACTION_INTERRUPT); PendingIntent pIntent = PendingIntent.getBroadcast(this,1, broadcastIntent,PendingIntent.FLAG_UPDATE_CURRENT); - builder.addAction(0, "STOP TEST", pIntent); + builder.addAction(0, getApplicationContext().getString(R.string.Notification_StopTest), pIntent); startForeground(NOTIFICATION_ID, builder.build()); return START_NOT_STICKY; From 7bb15a8bce899a9170c97f7b9b684e272b0c6196 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Nov 2020 09:14:16 +0000 Subject: [PATCH 63/66] Adding comments --- .../ooniprobe/activity/RunningActivity.java | 1 + .../ooniprobe/common/service/RunTestService.java | 15 +++++++++++---- .../ooniprobe/test/TestAsyncTask.java | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index b73f5c7d0..e73b32078 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -153,6 +153,7 @@ public void onBackPressed() { @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; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java index 00db21e54..7dc7fa73b 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/service/RunTestService.java @@ -64,13 +64,20 @@ public int onStartCommand(Intent intent, int flags, int startId) { .build(); task = (TestAsyncTask) new TestAsyncTask(app, testSuites, this).execute(); - + //This intent is used to manage the stop test button in the notification Intent broadcastIntent = new Intent(); broadcastIntent.setAction(RunTestService.ACTION_INTERRUPT); PendingIntent pIntent = PendingIntent.getBroadcast(this,1, broadcastIntent,PendingIntent.FLAG_UPDATE_CURRENT); builder.addAction(0, getApplicationContext().getString(R.string.Notification_StopTest), pIntent); startForeground(NOTIFICATION_ID, builder.build()); - + /* + START_NOT_STICKY says that, after returning from onStartCreated(), + if the process is killed with no remaining start commands to deliver, + then the service will be stopped instead of restarted. + This makes a lot more sense for services that are intended to only run while executing commands sent to them. + For example, a service may be started every 15 minutes from an alarm to poll some network state. + If it gets killed while doing that work, it would be best to just let it be stopped and get started the next time the alarm fires. + */ return START_NOT_STICKY; } @@ -120,14 +127,14 @@ public class ActionReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if(action != null && action.equals("interrupt_test")){ - stopTest(context); + stopTest(); } //This is used to close the notification tray Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); context.sendBroadcast(it); } - public void stopTest(Context context){ + public void stopTest(){ task.interrupt(); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java index aacd064f9..6302d4b69 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/TestAsyncTask.java @@ -23,6 +23,7 @@ import org.openobservatory.ooniprobe.test.test.AbstractTest; import org.openobservatory.ooniprobe.test.test.WebConnectivity; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -92,6 +93,7 @@ private void runTest(AbstractTest ... tests){ } private void downloadURLs(){ + //Try/Catch to resolve probeCC only String probeCC = "XX"; try { probeCC = Engine.resolveProbeCC( @@ -100,6 +102,14 @@ private void downloadURLs(){ BuildConfig.VERSION_NAME, 30 ); + } + catch (Exception e) { + e.printStackTrace(); + ExceptionManager.logException(e); + } + + //Try/Catch for the downloader + try { Response response = app.getOrchestraClient().getUrls(probeCC, app.getPreferenceManager().getEnabledCategory()).execute(); if (response.isSuccessful() && response.body() != null && response.body().results != null) { ArrayList inputs = new ArrayList<>(); @@ -111,7 +121,7 @@ private void downloadURLs(){ publishProgress(URL); } } - catch (Exception e) { + catch (IOException e) { e.printStackTrace(); ExceptionManager.logException(e); } @@ -133,7 +143,9 @@ private void downloadURLs(){ @Override protected void onProgressUpdate(String... values) { + //Send broadcast to the RunningActivity sendBroadcast(values); + //And update the notification String key = values[0]; if (values.length <= 1) return; String value = values[1]; @@ -167,6 +179,7 @@ protected void onPostExecute(Void aVoid) { } private void sendBroadcast(String... values){ + //This Broadcast is sent to the RunningActivity (if alive) to update the UI Intent broadcastIntent = new Intent(); broadcastIntent.putExtra("key", values[0]); if (values.length > 1) From 1aff254b8e18575bdc16f7a4939ede8f4c7fe828 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Nov 2020 09:26:43 +0000 Subject: [PATCH 64/66] Update build.gradle --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 59ad0e080..ff8645205 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId 'org.openobservatory.ooniprobe' minSdkVersion 21 targetSdkVersion 29 - versionName '2.7.1' - versionCode 66 + versionName '2.8.0-beta.1' + versionCode 67 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField 'String', 'OONI_ORCHESTRATE_BASE_URL', '"https://orchestrate.ooni.io/"' buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.ooni.io/"' From ccb5d309ecaa814f204732325b7ad68a52c4965d Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Nov 2020 09:32:40 +0000 Subject: [PATCH 65/66] Update build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 81dd52a94..02739ebe5 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.1' classpath 'com.google.gms:google-services:4.3.3' } } From f98c1ed50d8abfe567b3d1cc7464870cacd9d860 Mon Sep 17 00:00:00 2001 From: Lorenzo Primiterra Date: Mon, 30 Nov 2020 09:52:34 +0000 Subject: [PATCH 66/66] Cancel notification on app open --- .../openobservatory/ooniprobe/activity/RunningActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index e73b32078..d559adacd 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -1,5 +1,6 @@ package org.openobservatory.ooniprobe.activity; +import android.app.NotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -119,6 +120,9 @@ private void applyUIChanges(){ protected void onResume() { super.onResume(); if (!isTestRunning()) { + NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); + assert notificationManager != null; + notificationManager.cancel(RunTestService.NOTIFICATION_ID); testEnded(this); return; }