Skip to content

Commit

Permalink
- updated to the latest libs and tools
Browse files Browse the repository at this point in the history
- implemented app shortcuts to quicktoggle between permissive and enforcing modes
- new icons and notification styles
- adaptive icons (including shortcuts) for 8.0+
- fixed crashes on rootless devices
- fixed crashes on 8.0+ (still, app won't work if kernel doesn't allow context switching)
- few tweaks and smaller bug-fixes.
  • Loading branch information
MrBIMC committed Oct 31, 2017
1 parent 0a038f9 commit 02a0d9d
Show file tree
Hide file tree
Showing 36 changed files with 239 additions and 56 deletions.
24 changes: 13 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.mrbimc.selinux"
minSdkVersion 17
targetSdkVersion 26
versionCode 20170724
versionName "10.0"
versionCode 20171031
versionName "11.0"
}
buildTypes {
release {
Expand All @@ -22,15 +20,19 @@ android {
}
}

ext {
supportLibVersion = "26.1.0"
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:26.0.0-beta2'
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.16'
implementation 'com.android.support:design:26.0.0-beta2'
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
implementation 'eu.chainfire:libsuperuser:1.0.0.+'
implementation 'com.yarolegovich:lovely-dialog:1.0.7'
implementation 'net.sourceforge.streamsupport:streamsupport-cfuture:1.5.5'
implementation "com.android.support:design:$supportLibVersion"
implementation "com.android.support:cardview-v7:$supportLibVersion"
implementation "eu.chainfire:libsuperuser:1.0.0.+"
implementation "com.yarolegovich:lovely-dialog:1.0.7"
implementation "net.sourceforge.streamsupport:streamsupport-cfuture:1.5.5"
}

kotlin {
Expand Down
12 changes: 9 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,31 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>

<activity
android:name=".ShortcutActivity"
android:theme="@android:style/Theme.NoDisplay"/>

<receiver
android:name=".SELinuxBroadcastReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter android:priority="1000" >
<intent-filter android:priority="999" >
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
Expand Down
25 changes: 17 additions & 8 deletions app/src/main/java/com/mrbimc/selinux/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import kotlinx.android.synthetic.main.layout_command.*
import kotlinx.android.synthetic.main.layout_context.*
import kotlinx.android.synthetic.main.layout_notifications.*
import kotlinx.android.synthetic.main.layout_selinux_state.*

import kotlinx.android.synthetic.main.layout_autostart.*

class MainActivity : AppCompatActivity() {

Expand All @@ -32,6 +32,7 @@ class MainActivity : AppCompatActivity() {
checkCommand()
checkContext()
checkNotificationSettings()
checkAutoStartSettings()
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand All @@ -58,7 +59,7 @@ class MainActivity : AppCompatActivity() {
}
}

fun checkContext() {
private fun checkContext() {
val items = resources.getStringArray(R.array.selinux_contexts)
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, items)

Expand All @@ -78,7 +79,7 @@ class MainActivity : AppCompatActivity() {
}
}

fun checkCommand() {
private fun checkCommand() {
val items = resources.getStringArray(R.array.selinux_commands)
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, items)

Expand All @@ -97,15 +98,23 @@ class MainActivity : AppCompatActivity() {
}
}

fun checkNotificationSettings() {
notificationsSwitch.isChecked = sp.getBoolean("notifications", true)
private fun checkNotificationSettings() {
notificationsSwitch.isChecked = sp.getBoolean(KEY_NOTIFICATIONS, true)

notificationsSwitch.setOnCheckedChangeListener { _, isChecked ->
sp.edit().putBoolean(KEY_NOTIFICATIONS, isChecked).apply()
}
}

fun checkSELinuxState() {
private fun checkAutoStartSettings() {
autoStartSwitch.isChecked = sp.getBoolean(KEY_AUTOSTART, true)

autoStartSwitch.setOnCheckedChangeListener { _, isChecked ->
sp.edit().putBoolean(KEY_AUTOSTART, isChecked).apply()
}
}

private fun checkSELinuxState() {

val ad = LovelyProgressDialog(this)
.setTopColorRes(R.color.colorAccent)
Expand Down Expand Up @@ -139,7 +148,7 @@ class MainActivity : AppCompatActivity() {
}
}

fun showInfoDialog(): Boolean {
private fun showInfoDialog(): Boolean {
LovelyStandardDialog(this)
.setTopColorRes(R.color.colorAccent)
.setTopTitle(getString(R.string.about_this_app))
Expand All @@ -156,7 +165,7 @@ class MainActivity : AppCompatActivity() {
return true
}

fun openGithub() {
private fun openGithub() {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/MrBIMC/SELinuxModeChanger")))
}

Expand Down
12 changes: 8 additions & 4 deletions app/src/main/java/com/mrbimc/selinux/SELinuxBroadcastReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.preference.PreferenceManager
import com.mrbimc.selinux.util.KEY_SELINUX_STATE
import com.mrbimc.selinux.util.SELinuxState
import com.mrbimc.selinux.util.setSELinuxState
import com.mrbimc.selinux.util.*

/**
* Created by Pavel Sikun on 23.07.17.
Expand All @@ -15,10 +13,16 @@ import com.mrbimc.selinux.util.setSELinuxState
class SELinuxBroadcastReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
val selinuxState = PreferenceManager.getDefaultSharedPreferences(context).getInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value)
val sp = PreferenceManager.getDefaultSharedPreferences(context)
if (!sp.getBoolean(KEY_AUTOSTART, true)) {
return
}

val selinuxState = sp.getInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value)
when (selinuxState) {
0 -> context.setSELinuxState(SELinuxState.PERMISSIVE)
1 -> context.setSELinuxState(SELinuxState.ENFORCING)
else -> context.createNotification(context.getString(R.string.no_root_access))
}
}
}
44 changes: 44 additions & 0 deletions app/src/main/java/com/mrbimc/selinux/ShortcutActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.mrbimc.selinux

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutManager
import android.os.Bundle
import com.mrbimc.selinux.util.*

/**
* Created by Pavel Sikun on 31.10.2017.
*/

class ShortcutActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
processShortcut(intent)
finish()
}

private fun processShortcut(intent: Intent) {
val uri = intent.data ?: return

val host = uri.host
reportShortcutUsed(host)

when (host) {
SHORTCUT_ENFORCING -> {
setSELinuxState(SELinuxState.ENFORCING)
}
SHORTCUT_PERMISSIVE -> {
setSELinuxState(SELinuxState.PERMISSIVE)
}
}
}

private fun reportShortcutUsed(shortcutId: String) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
val shortcutManager = getSystemService(Context.SHORTCUT_SERVICE) as ShortcutManager
shortcutManager.reportShortcutUsed(shortcutId)
}
}

}
6 changes: 5 additions & 1 deletion app/src/main/java/com/mrbimc/selinux/util/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ package com.mrbimc.selinux.util
const val KEY_COMMAND = "selinux_command"
const val KEY_CONTEXT = "selinux_context"
const val KEY_NOTIFICATIONS = "notifications"
const val KEY_SELINUX_STATE = "selinux"
const val KEY_AUTOSTART = "autostart"
const val KEY_SELINUX_STATE = "selinux"

const val SHORTCUT_ENFORCING = "enforcing"
const val SHORTCUT_PERMISSIVE = "permissive"
31 changes: 16 additions & 15 deletions app/src/main/java/com/mrbimc/selinux/util/ContextUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ import kotlinx.coroutines.experimental.launch
fun Context.getSELinuxState(callback: (SELinuxState) -> Unit) = launch(CommonPool) {
val sp = PreferenceManager.getDefaultSharedPreferences(this@getSELinuxState)
when(executeGetSELinuxState().get()) {
SELinuxState.UNKNOWN -> {
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply()
callback(SELinuxState.UNKNOWN)
}
SELinuxState.ENFORCING -> {
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.ENFORCING.value).apply()
callback(SELinuxState.ENFORCING)
Expand All @@ -35,6 +31,10 @@ fun Context.getSELinuxState(callback: (SELinuxState) -> Unit) = launch(CommonPoo
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.PERMISSIVE.value).apply()
callback(SELinuxState.PERMISSIVE)
}
else -> { // SELinuxState.UNKNOWN && black magic cases
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply()
callback(SELinuxState.UNKNOWN)
}
}
}

Expand All @@ -44,7 +44,7 @@ fun Context.setSELinuxState(state: SELinuxState, callback: (SELinuxState) -> Uni
val defaultCommand = resources.getStringArray(R.array.selinux_commands)[0]
val defaultContext = resources.getStringArray(R.array.selinux_contexts)[0]

val command = sp.getString(KEY_COMMAND, defaultCommand).replace("#STATE#", "${state.value}")
val command = sp.getString(KEY_COMMAND, defaultCommand).replace("\$STATE", "${state.value}")
val context = sp.getString(KEY_CONTEXT, defaultContext)

var commandToExecute = command
Expand All @@ -54,11 +54,6 @@ fun Context.setSELinuxState(state: SELinuxState, callback: (SELinuxState) -> Uni
}

when(executeSetSELinuxState(state, commandToExecute).get()) {
SELinuxState.UNKNOWN -> {
createNotification(getString(R.string.no_root_access))
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply()
callback(SELinuxState.UNKNOWN)
}
SELinuxState.ENFORCING -> {
createNotification(getString(R.string.selinux_set_to_enforcing))
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.ENFORCING.value).apply()
Expand All @@ -69,6 +64,11 @@ fun Context.setSELinuxState(state: SELinuxState, callback: (SELinuxState) -> Uni
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.PERMISSIVE.value).apply()
callback(SELinuxState.PERMISSIVE)
}
else -> { // SELinuxState.UNKNOWN && black magic cases
createNotification(getString(R.string.no_root_access))
sp.edit().putInt(KEY_SELINUX_STATE, SELinuxState.UNKNOWN.value).apply()
callback(SELinuxState.UNKNOWN)
}
}
}

Expand All @@ -85,13 +85,14 @@ fun Context.createNotification(message: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val contentIntent = PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java), 0)

val notificationID = 1
val notificationID = 12459
val channelID = KEY_NOTIFICATIONS

val notification = NotificationCompat.Builder(this, channelID)
.setSmallIcon(R.mipmap.ic_launcher)
.setSmallIcon(R.drawable.security)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setContentText(message)
.setContentTitle(message)
.setContentText(getString(R.string.tap_for_details))
.setContentIntent(contentIntent)
.setAutoCancel(false)
.build()
Expand All @@ -104,9 +105,9 @@ fun Context.createNotificationChannel() {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val id = KEY_NOTIFICATIONS
val name = getString(R.string.channel_name)
val importance = NotificationManager.IMPORTANCE_UNSPECIFIED

val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(id, name, importance)

channel.enableLights(true)
channel.lightColor = Color.GREEN
channel.enableVibration(false)
Expand Down
22 changes: 14 additions & 8 deletions app/src/main/java/com/mrbimc/selinux/util/ShellUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ private val shell by lazy { Shell.Builder()
fun executeGetSELinuxState(): CompletableFuture<SELinuxState> {
val future = CompletableFuture<SELinuxState>()

shell.addCommand("/system/bin/getenforce", 1) { _, _, output: MutableList<String> ->
val outputString = output.joinToString()
val isEnforcing = outputString.toLowerCase().contains("enforcing")
future.complete(if (isEnforcing) SELinuxState.ENFORCING else SELinuxState.PERMISSIVE)
if (Shell.SU.available()) {
future.complete(if (Shell.SU.isSELinuxEnforcing()) SELinuxState.ENFORCING else SELinuxState.PERMISSIVE)
}
else {
future.complete(SELinuxState.UNKNOWN)
}

return future
Expand All @@ -29,10 +30,15 @@ fun executeGetSELinuxState(): CompletableFuture<SELinuxState> {
fun executeSetSELinuxState(state: SELinuxState, command: String): CompletableFuture<SELinuxState> {
val future = CompletableFuture<SELinuxState>()

shell.addCommand(command, 1) { _, _, output: MutableList<String> ->
val outputString = output.joinToString()
val isError = outputString.trim().isNotEmpty()
future.complete(if (isError) SELinuxState.UNKNOWN else state)
if (Shell.SU.available()) {
shell.addCommand(command, 1) { _, _, output: MutableList<String> ->
val outputString = output.joinToString()
val isError = outputString.trim().isNotEmpty()
future.complete(if (isError) SELinuxState.UNKNOWN else state)
}
}
else {
future.complete(SELinuxState.UNKNOWN)
}

return future
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/lock_open_outline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- drawable/lock_open_outline.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportWidth="48"
android:viewportHeight="48">
<group android:translateX="12" android:translateY="12">
<path android:fillColor="#000" android:pathData="M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10A2,2 0 0,1 6,8H15V6A3,3 0 0,0 12,3A3,3 0 0,0 9,6H7A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,17A2,2 0 0,1 10,15A2,2 0 0,1 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17Z" />
</group>
</vector>
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/lock_outline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- drawable/lock_outline.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp"
android:width="108dp"
android:viewportWidth="48"
android:viewportHeight="48">
<group android:translateX="12" android:translateY="12">
<path android:fillColor="#000" android:pathData="M12,17C10.89,17 10,16.1 10,15C10,13.89 10.89,13 12,13A2,2 0 0,1 14,15A2,2 0 0,1 12,17M18,20V10H6V20H18M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V10C4,8.89 4.89,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z" />
</group>
</vector>
Loading

0 comments on commit 02a0d9d

Please sign in to comment.