Skip to content

Commit

Permalink
Merge pull request #415 from SwissCovid/feature/summer-sleep
Browse files Browse the repository at this point in the history
Feature/summer sleep
  • Loading branch information
simonroesch authored Mar 16, 2022
2 parents 935b3df + c6bdca7 commit f6d5abd
Show file tree
Hide file tree
Showing 25 changed files with 761 additions and 8 deletions.
25 changes: 20 additions & 5 deletions app/src/main/java/ch/admin/bag/dp3t/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker
import ch.admin.bag.dp3t.checkin.utils.CrowdNotifierReminderHelper
import ch.admin.bag.dp3t.checkin.utils.ErrorDialog
import ch.admin.bag.dp3t.checkin.utils.NotificationHelper
import ch.admin.bag.dp3t.hibernate.HibernatingInfoFragment
import ch.admin.bag.dp3t.inform.InformActivity
import ch.admin.bag.dp3t.networking.ConfigWorker.Companion.scheduleConfigWorkerIfOutdated
import ch.admin.bag.dp3t.onboarding.OnboardingActivityArgs
Expand Down Expand Up @@ -62,7 +63,9 @@ class MainActivity : FragmentActivity() {
private val crowdNotifierViewModel: CrowdNotifierViewModel by viewModels()

private val onboardingLauncher = registerForActivityResult(OnboardingActivityResultContract()) {
if (it != null) {
if (secureStorage.isHibernating) {
showHibernateFragment()
} else if (it != null) {
onOnboardingFinished(it.onboardingType, it.activityResult, it.instantAppUrl)
} else {
finish()
Expand All @@ -78,7 +81,14 @@ class MainActivity : FragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
secureStorage.forceUpdateLiveData.observe(this, {
val isInHibernatingState = secureStorage.isHibernating
if (isInHibernatingState) {
if (savedInstanceState == null) {
showHibernateFragment()
}
return
}
secureStorage.forceUpdateLiveData.observe(this) {

val forceUpdate = it && secureStorage.doForceUpdate

Expand All @@ -96,7 +106,7 @@ class MainActivity : FragmentActivity() {
}
forceUpdateDialog.show()
}
})
}
scheduleConfigWorkerIfOutdated(this)
CrowdNotifierKeyLoadWorker.startKeyLoadWorker(this)
CrowdNotifierKeyLoadWorker.cleanUpOldData(this)
Expand All @@ -111,7 +121,6 @@ class MainActivity : FragmentActivity() {
lastShownUpdateBoardingVersion < UPDATE_BOARDING_VERSION -> OnboardingType.UPDATE_BOARDING
else -> null
}

if (onboardingType == null) {
showHomeFragment()
} else {
Expand Down Expand Up @@ -174,7 +183,7 @@ class MainActivity : FragmentActivity() {

override fun onResume() {
super.onResume()
if (secureStorage.onboardingCompleted) checkIntentForActions()
if (secureStorage.onboardingCompleted && !secureStorage.isHibernating) checkIntentForActions()
LocalBroadcastManager.getInstance(this)
.registerReceiver(autoCheckoutBroadcastReceiver, IntentFilter(CrowdNotifierReminderHelper.ACTION_DID_AUTO_CHECKOUT))
}
Expand Down Expand Up @@ -285,6 +294,12 @@ class MainActivity : FragmentActivity() {
startActivity(intent)
}

private fun showHibernateFragment() {
supportFragmentManager.beginTransaction()
.add(R.id.main_fragment_container, HibernatingInfoFragment.newInstance())
.commit()
}

private fun showHomeFragment() {
supportFragmentManager.beginTransaction()
.add(R.id.main_fragment_container, TabbarHostFragment.newInstance())
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/ch/admin/bag/dp3t/MainApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ public void onCreate() {
Logger.init(getApplicationContext(), LogLevel.DEBUG);
CertificatePinning.initDebug(this);
}
SecureStorage secureStorage = SecureStorage.getInstance(this);

// DP3T SDK is not initialized if app is in Hibernating Mode to prevent it from showing any notifications to the user
if (secureStorage.isHibernating()) return;

registerReceiver(contactUpdateReceiver, DP3T.getUpdateIntentFilter());

initDP3T(this);

SecureStorage secureStorage = SecureStorage.getInstance(this);
int appVersionCode = BuildConfig.VERSION_CODE;
if (secureStorage.getLastKnownAppVersionCode() != appVersionCode) {
secureStorage.setLastKnownAppVersionCode(appVersionCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public static void startKeyLoadWorker(Context context) {
workManager.enqueueUniquePeriodicWork(WORK_TAG, ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest);
}

public static void stop(Context context) {
WorkManager.getInstance(context).cancelAllWorkByTag(WORK_TAG);
}


public CrowdNotifierKeyLoadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ch.admin.bag.dp3t.hibernate

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import ch.admin.bag.dp3t.R
import ch.admin.bag.dp3t.TabbarHostFragment
import ch.admin.bag.dp3t.databinding.FragmentHibernatingInfoBinding
import ch.admin.bag.dp3t.html.HtmlFragment
import ch.admin.bag.dp3t.storage.SecureStorage
import ch.admin.bag.dp3t.util.AssetUtil
import ch.admin.bag.dp3t.util.UrlUtil

class HibernatingInfoFragment : Fragment() {

companion object {
@JvmStatic
fun newInstance() = HibernatingInfoFragment()
}

private val viewModel: HibernatingViewModel by viewModels()

private val secureStorage by lazy { SecureStorage.getInstance(requireContext()) }

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return FragmentHibernatingInfoBinding.inflate(inflater).apply {

toolbar.setOnMenuItemClickListener {
showImpressum()
true
}

val infoBoxModel = secureStorage.hibernatingInfoboxCollection?.getInfoBox(resources.getString(R.string.language_key))

viewModel.isHibernatingModeEnabled.observe(viewLifecycleOwner) { isHibernatingModeEnabled ->
if (!isHibernatingModeEnabled) {
showHomeFragment()
}
}

infoBoxModel?.let {
title.text = it.title
text.text = it.msg
linkGroup.isVisible = it.urlTitle != null
linkText.text = it.urlTitle
linkGroup.setOnClickListener { v -> UrlUtil.openUrl(requireContext(), it.url) }
}

}.root
}

private fun showHomeFragment() {
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.main_fragment_container, TabbarHostFragment.newInstance())
.commit()
}

private fun showImpressum() {
val htmlFragment = HtmlFragment.newInstance(
R.string.menu_impressum, AssetUtil.getImpressumBaseUrl(context),
AssetUtil.getImpressumHtml(context)
)
requireActivity().supportFragmentManager.beginTransaction()
.setCustomAnimations(
R.anim.slide_enter,
R.anim.slide_exit,
R.anim.slide_pop_enter,
R.anim.slide_pop_exit
)
.replace(R.id.main_fragment_container, htmlFragment)
.addToBackStack(HtmlFragment::class.java.canonicalName)
.commit()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ch.admin.bag.dp3t.hibernate

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import ch.admin.bag.dp3t.MainApplication
import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker
import ch.admin.bag.dp3t.networking.ConfigWorker
import ch.admin.bag.dp3t.networking.FakeWorker
import ch.admin.bag.dp3t.storage.SecureStorage
import ch.admin.bag.dp3t.util.NotificationRepeatWorker
import kotlinx.coroutines.launch
import org.dpppt.android.sdk.DP3T
import org.dpppt.android.sdk.internal.logger.Logger

class HibernatingViewModel(application: Application) : AndroidViewModel(application) {

companion object {
private val TAG = "HibernatingViewModel"

}

private val isHibernatingModeEnabledMutable = MutableLiveData<Boolean>()
val isHibernatingModeEnabled: LiveData<Boolean> = isHibernatingModeEnabledMutable

init {
loadConfig()
}


private fun loadConfig() {
viewModelScope.launch {
try {
ConfigWorker.loadConfig(getApplication())
if (SecureStorage.getInstance(getApplication()).isHibernating) {
isHibernatingModeEnabledMutable.value = true
} else {
MainApplication.initDP3T(getApplication())
FakeWorker.safeStartFakeWorker(getApplication())
CrowdNotifierKeyLoadWorker.startKeyLoadWorker(getApplication())
NotificationRepeatWorker.startWorker(getApplication())
ConfigWorker.scheduleConfigWorkerIfOutdated(getApplication())
isHibernatingModeEnabledMutable.value = false
}
} catch (e: Exception) {
Logger.e(TAG, "config request failed", e)
}
}
}
}
23 changes: 22 additions & 1 deletion app/src/main/java/ch/admin/bag/dp3t/networking/ConfigWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import androidx.work.*
import ch.admin.bag.dp3t.BuildConfig
import ch.admin.bag.dp3t.MainActivity
import ch.admin.bag.dp3t.R
import ch.admin.bag.dp3t.checkin.networking.CrowdNotifierKeyLoadWorker
import ch.admin.bag.dp3t.debug.DebugFragment
import ch.admin.bag.dp3t.networking.errors.ResponseError
import ch.admin.bag.dp3t.onboarding.OnboardingSlidePageAdapter.Companion.CHECKIN_UPDATE_BOARDING_VERSION
import ch.admin.bag.dp3t.storage.SecureStorage
import ch.admin.bag.dp3t.util.NotificationRepeatWorker
import ch.admin.bag.dp3t.util.NotificationUtil
import org.dpppt.android.sdk.DP3T
import org.dpppt.android.sdk.backend.SignatureException
Expand Down Expand Up @@ -63,8 +65,12 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine
}
}

fun stop(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(FakeWorker.WORK_TAG)
}

@Throws(IOException::class, ResponseError::class, SignatureException::class)
private suspend fun loadConfig(context: Context) {
suspend fun loadConfig(context: Context) {
val configRepository = ConfigRepository(context)
val config = configRepository.getConfig(context)

Expand All @@ -77,6 +83,7 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine

val secureStorage = SecureStorage.getInstance(context)
secureStorage.doForceUpdate = config.doForceUpdate

secureStorage.setWhatToDoPositiveTestTexts(config.whatToDoPositiveTestTexts)

if (config.infoBox != null) {
Expand Down Expand Up @@ -111,6 +118,20 @@ class ConfigWorker(context: Context, workerParams: WorkerParameters) : Coroutine
showCheckInUpdateNotification(context);
}
}

secureStorage.isHibernating = config.isDeactivate
secureStorage.hibernatingInfoboxCollection = config.deactivationMessage
if (config.isDeactivate) {
activateHibernationState(context)
}
}

private fun activateHibernationState(context: Context) {
DP3T.stop(context)
FakeWorker.stop(context)
CrowdNotifierKeyLoadWorker.stop(context)
NotificationRepeatWorker.stop(context)
this.stop(context)
}

private fun showNotification(context: Context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class ConfigResponseModel {

private VaccinationBookingInfoCollection vaccinationBookingInfo;
private boolean showVaccinationInfo;
private boolean deactivate;
private InfoBoxModelCollection deactivationMessage;

public boolean getDoForceUpdate() {
return forceUpdate;
Expand Down Expand Up @@ -71,4 +73,12 @@ public boolean isShowVaccinationInfo() {
return showVaccinationInfo;
}

public boolean isDeactivate() {
return deactivate;
}

public InfoBoxModelCollection getDeactivationMessage() {
return deactivationMessage;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import android.animation.Animator
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import ch.admin.bag.dp3t.R
import ch.admin.bag.dp3t.hibernate.HibernatingViewModel
import org.dpppt.android.sdk.DP3T

private const val SHOW_SPLASHBOARDING_MILLIS = 3000
Expand All @@ -32,10 +34,18 @@ class OnboardingActivity : FragmentActivity() {
private lateinit var viewPager: ViewPager2
private lateinit var pagerAdapter: FragmentStateAdapter

private val hibernatingViewModel by viewModels<HibernatingViewModel>()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_onboarding)

hibernatingViewModel.isHibernatingModeEnabled.observe(this) { isHibernatingModeEnabled ->
if (isHibernatingModeEnabled) {
finish()
}
}

splashboarding = findViewById(R.id.splashboarding)
viewPager = findViewById(R.id.pager)

Expand Down
20 changes: 19 additions & 1 deletion app/src/main/java/ch/admin/bag/dp3t/storage/SecureStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public class SecureStorage {
"KEY_POSITIVE_REPORT_OLDEST_SHARED_KEY_OR_CHECKIN";
private static final String KEY_EXPOSURE_NOTIFICATIONS_ACTIVE_BEFORE_ENTERING_COVIDCODE =
"KEY_EXPOSURE_NOTIFICATIONS_ACTIVE_BEFORE_ENTERING_COVIDCODE";
private static final String KEY_IS_IN_HIBERNATING_STATE = "KEY_IS_IN_HIBERNATING_STATE";
private static final String KEY_HIBERNATING_INFOBOX_MODEL = "KEY_HIBERNATING_INFOBOX_MODEL";


private static SecureStorage instance;
Expand Down Expand Up @@ -165,6 +167,22 @@ public void setOnboardingCompleted(boolean completed) {
prefs.edit().putBoolean(KEY_ONBOARDING_COMPLETED, completed).apply();
}

public boolean isHibernating() {
return prefs.getBoolean(KEY_IS_IN_HIBERNATING_STATE, false);
}

public void setHibernating(boolean isHibernating) {
prefs.edit().putBoolean(KEY_IS_IN_HIBERNATING_STATE, isHibernating).apply();
}

public void setHibernatingInfoboxCollection(InfoBoxModelCollection infoBoxModelCollection) {
prefs.edit().putString(KEY_HIBERNATING_INFOBOX_MODEL, gson.toJson(infoBoxModelCollection)).apply();
}

public InfoBoxModelCollection getHibernatingInfoboxCollection() {
return gson.fromJson(prefs.getString(KEY_HIBERNATING_INFOBOX_MODEL, "null"), InfoBoxModelCollection.class);
}

public boolean getOnlyPartialOnboardingCompleted() {
return prefs.getBoolean(KEY_ONLY_PARTIAL_ONBOARDING_DONE, false);
}
Expand Down Expand Up @@ -339,7 +357,7 @@ public void setShowVaccinationInfo(boolean showVaccinationInfo) {
prefs.edit().putBoolean(KEY_SHOW_VACCINATION_INFO, showVaccinationInfo).apply();
}

public boolean getShowVaccinationInfo(){
public boolean getShowVaccinationInfo() {
return prefs.getBoolean(KEY_SHOW_VACCINATION_INFO, false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public static void startWorker(Context context) {
WorkManager.getInstance(context).enqueueUniqueWork(WORK_TAG, ExistingWorkPolicy.REPLACE, notificationWorker);
}

public static void stop(Context context) {
WorkManager.getInstance(context).cancelAllWorkByTag(WORK_TAG);
}

public NotificationRepeatWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
Expand Down
Loading

0 comments on commit f6d5abd

Please sign in to comment.