Allow disabling locking with the device owner permission

This commit is contained in:
Jonas Lochmann 2019-08-19 00:00:00 +00:00
parent 24710aa21e
commit 3fbf598eb5
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
10 changed files with 250 additions and 11 deletions

View file

@ -223,4 +223,39 @@ abstract class ConfigDao {
fun getEnableAlternativeDurationSelectionAsync() = getValueOfKeyAsync(ConfigurationItemType.EnableAlternativeDurationSelection).map { it == "1" }
fun setEnableAlternativeDurationSelectionSync(enable: Boolean) = updateValueSync(ConfigurationItemType.EnableAlternativeDurationSelection, if (enable) "1" else "0")
fun getExperimentalFlagsLive(): LiveData<Long> {
return getValueOfKeyAsync(ConfigurationItemType.ExperimentalFlags).map {
if (it == null) {
0
} else {
it.toLong(16)
}
}
}
private fun getExperimentalFlagsSync(): Long {
val v = getValueOfKeySync(ConfigurationItemType.ExperimentalFlags)
if (v == null) {
return 0
} else {
return v.toLong(16)
}
}
fun isExperimentalFlagsSetAsync(flags: Long) = getExperimentalFlagsLive().map {
(it and flags) == flags
}.ignoreUnchanged()
fun isExperimentalFlagsSetSync(flags: Long) = (getExperimentalFlagsSync() and flags) == flags
fun setExperimentalFlag(flags: Long, enable: Boolean) {
updateValueSync(
ConfigurationItemType.ExperimentalFlags,
if (enable)
(getShownHintsSync() or flags).toString(16)
else
(getShownHintsSync() and (flags.inv())).toString(16)
)
}
}

View file

@ -91,7 +91,8 @@ enum class ConfigurationItemType {
CustomServerUrl,
ForegroundAppQueryRange,
EnableBackgroundSync,
EnableAlternativeDurationSelection
EnableAlternativeDurationSelection,
ExperimentalFlags
}
object ConfigurationItemTypeUtil {
@ -110,6 +111,7 @@ object ConfigurationItemTypeUtil {
private const val FOREGROUND_APP_QUERY_RANGE = 14
private const val ENABLE_BACKGROUND_SYNC = 15
private const val ENABLE_ALTERNATIVE_DURATION_SELECTION = 16
private const val EXPERIMENTAL_FLAGS = 17
val TYPES = listOf(
ConfigurationItemType.OwnDeviceId,
@ -126,7 +128,8 @@ object ConfigurationItemTypeUtil {
ConfigurationItemType.CustomServerUrl,
ConfigurationItemType.ForegroundAppQueryRange,
ConfigurationItemType.EnableBackgroundSync,
ConfigurationItemType.EnableAlternativeDurationSelection
ConfigurationItemType.EnableAlternativeDurationSelection,
ConfigurationItemType.ExperimentalFlags
)
fun serialize(value: ConfigurationItemType) = when(value) {
@ -145,6 +148,7 @@ object ConfigurationItemTypeUtil {
ConfigurationItemType.ForegroundAppQueryRange -> FOREGROUND_APP_QUERY_RANGE
ConfigurationItemType.EnableBackgroundSync -> ENABLE_BACKGROUND_SYNC
ConfigurationItemType.EnableAlternativeDurationSelection -> ENABLE_ALTERNATIVE_DURATION_SELECTION
ConfigurationItemType.ExperimentalFlags -> EXPERIMENTAL_FLAGS
}
fun parse(value: Int) = when(value) {
@ -163,6 +167,7 @@ object ConfigurationItemTypeUtil {
FOREGROUND_APP_QUERY_RANGE -> ConfigurationItemType.ForegroundAppQueryRange
ENABLE_BACKGROUND_SYNC -> ConfigurationItemType.EnableBackgroundSync
ENABLE_ALTERNATIVE_DURATION_SELECTION -> ConfigurationItemType.EnableAlternativeDurationSelection
EXPERIMENTAL_FLAGS -> ConfigurationItemType.ExperimentalFlags
else -> throw IllegalArgumentException()
}
}
@ -183,3 +188,7 @@ object HintsToShow {
const val CONTACTS_INTRO = 16L
const val TIMELIMIT_RULE_MUSTREAD = 32L
}
object ExperimentalFlags {
const val DISABLE_BLOCK_ON_MANIPULATION = 1L
}

View file

@ -20,6 +20,7 @@ import android.os.Build
import io.timelimit.android.async.Threads
import io.timelimit.android.coroutines.executeAndWait
import io.timelimit.android.coroutines.runAsync
import io.timelimit.android.data.model.ExperimentalFlags
import io.timelimit.android.data.transaction
import io.timelimit.android.ui.MainActivity
import io.timelimit.android.ui.manipulation.UnlockAfterManipulationActivity
@ -40,17 +41,19 @@ class ManipulationLogic(val appLogic: AppLogic) {
}
fun lockDeviceSync() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (appLogic.platformIntegration.setLockTaskPackages(listOf(appLogic.context.packageName))) {
appLogic.database.config().setWasDeviceLockedSync(true)
if (!appLogic.database.config().isExperimentalFlagsSetSync(ExperimentalFlags.DISABLE_BLOCK_ON_MANIPULATION)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (appLogic.platformIntegration.setLockTaskPackages(listOf(appLogic.context.packageName))) {
appLogic.database.config().setWasDeviceLockedSync(true)
showManipulationScreen()
}
} else {
if (lockDeviceSync("12timelimit34")) {
appLogic.database.config().setWasDeviceLockedSync(true)
showManipulationScreen()
}
} else {
if (lockDeviceSync("12timelimit34")) {
appLogic.database.config().setWasDeviceLockedSync(true)
showManipulationScreen()
showManipulationScreen()
}
}
}
}

View file

@ -0,0 +1,102 @@
/*
* TimeLimit Copyright <C> 2019 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.timelimit.android.ui.diagnose
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import androidx.lifecycle.Observer
import io.timelimit.android.BuildConfig
import io.timelimit.android.R
import io.timelimit.android.async.Threads
import io.timelimit.android.data.model.ExperimentalFlags
import io.timelimit.android.databinding.DiagnoseExperimentalFlagFragmentBinding
import io.timelimit.android.livedata.liveDataFromValue
import io.timelimit.android.logic.DefaultAppLogic
import io.timelimit.android.ui.main.ActivityViewModelHolder
import io.timelimit.android.ui.main.AuthenticationFab
class DiagnoseExperimentalFlagFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val activity: ActivityViewModelHolder = activity as ActivityViewModelHolder
val database = DefaultAppLogic.with(context!!).database
val auth = activity.getActivityViewModel()
val binding = DiagnoseExperimentalFlagFragmentBinding.inflate(inflater, container, false)
AuthenticationFab.manageAuthenticationFab(
fab = binding.fab,
shouldHighlight = auth.shouldHighlightAuthenticationButton,
authenticatedUser = auth.authenticatedUser,
doesSupportAuth = liveDataFromValue(true),
fragment = this
)
binding.fab.setOnClickListener { activity.showAuthenticationScreen() }
val flags = DiagnoseExperimentalFlagItem.items
val checkboxes = flags.map {
CheckBox(context).apply {
setText(it.label)
isEnabled = it.enable
}
}
checkboxes.forEach { binding.container.addView(it) }
database.config().getExperimentalFlagsLive().observe(this, Observer { setFlags ->
flags.forEachIndexed { index, flag ->
val checkbox = checkboxes[index]
val isFlagSet = (setFlags and flag.flag) == flag.flag
checkbox.setOnCheckedChangeListener { _, _ -> }
checkbox.isChecked = isFlagSet
checkbox.setOnCheckedChangeListener { _, didCheck ->
if (didCheck != isFlagSet) {
if (auth.requestAuthenticationOrReturnTrue()) {
Threads.database.execute {
database.config().setExperimentalFlag(flag.flag, didCheck)
}
} else {
checkbox.isChecked = isFlagSet
}
}
}
}
})
return binding.root
}
}
data class DiagnoseExperimentalFlagItem(
val label: Int,
val flag: Long,
val enable: Boolean
) {
companion object {
val items = listOf(
DiagnoseExperimentalFlagItem(
label = R.string.diagnose_exf_lom,
flag = ExperimentalFlags.DISABLE_BLOCK_ON_MANIPULATION,
enable = !BuildConfig.storeCompilant
)
)
}
}

View file

@ -58,6 +58,13 @@ class DiagnoseMainFragment : Fragment() {
)
}
binding.diagnoseExfButton.setOnClickListener {
navigation.safeNavigate(
DiagnoseMainFragmentDirections.actionDiagnoseMainFragmentToDiagnoseExperimentalFlagFragment(),
R.id.diagnoseMainFragment
)
}
return binding.root
}
}

View file

@ -0,0 +1,59 @@
<!--
TimeLimit Copyright <C> 2019 Jonas Lochmann
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="io.timelimit.android.ui.diagnose.DiagnoseExperimentalFlagFragment">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_margin="8dp"
app:cardUseCompatPadding="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:textAppearance="?android:textAppearanceLarge"
android:text="@string/diagnose_exf_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
app:fabSize="normal"
android:src="@drawable/ic_lock_open_white_24dp"
android:layout_margin="16dp"
android:layout_gravity="end|bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View file

@ -50,6 +50,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/diagnose_exf_button"
android:text="@string/diagnose_exf_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>

View file

@ -332,6 +332,13 @@
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
<action
android:id="@+id/action_diagnoseMainFragment_to_diagnoseExperimentalFlagFragment"
app:destination="@id/diagnoseExperimentalFlagFragment"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
</fragment>
<fragment
android:id="@+id/diagnoseClockFragment"
@ -403,4 +410,9 @@
android:name="parentUserId"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/diagnoseExperimentalFlagFragment"
android:name="io.timelimit.android.ui.diagnose.DiagnoseExperimentalFlagFragment"
android:label="diagnose_experimental_flag_fragment"
tools:layout="@layout/diagnose_experimental_flag_fragment" />
</navigation>

View file

@ -51,4 +51,7 @@
<string name="diagnose_fga_title">Erkennung der aktiven App</string>
<string name="diagnose_fga_query_range">Abfragezeitraum</string>
<string name="diagnose_fga_query_range_min">Minimal (Standard)</string>
<string name="diagnose_exf_title">Experimentelle Parameter</string>
<string name="diagnose_exf_lom">Sperrung nach Manipulationen deaktivieren</string>
</resources>

View file

@ -51,4 +51,7 @@
<string name="diagnose_fga_title">Foreground-App-Detection</string>
<string name="diagnose_fga_query_range">Requested time range</string>
<string name="diagnose_fga_query_range_min">Minimum (Default)</string>
<string name="diagnose_exf_title">Experimental flags</string>
<string name="diagnose_exf_lom">Disable locking after manipulations</string>
</resources>