Bump minSdk to 23

This commit is contained in:
topjohnwu 2023-03-17 04:24:16 -07:00
parent 33fb4653f0
commit af054e4e31
17 changed files with 98 additions and 208 deletions

View File

@ -14,7 +14,6 @@ import com.google.android.material.snackbar.Snackbar
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.widget.Pre23CardViewBackgroundColorFixLayoutInflaterListener
import rikka.insets.WindowInsetsHelper
import rikka.layoutinflater.view.LayoutInflaterFactory
@ -35,11 +34,6 @@ abstract class UIActivity<Binding : ViewDataBinding> : BaseActivity(), ViewModel
override fun onCreate(savedInstanceState: Bundle?) {
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
.addOnViewCreatedListener(WindowInsetsHelper.LISTENER)
.apply {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
this.addOnViewCreatedListener(Pre23CardViewBackgroundColorFixLayoutInflaterListener.getInstance())
}
}
super.onCreate(savedInstanceState)

View File

@ -7,7 +7,7 @@ import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.model.UpdateInfo
import com.topjohnwu.magisk.core.repository.NetworkService
import com.topjohnwu.magisk.core.utils.net.NetworkObserver
import com.topjohnwu.magisk.core.utils.NetworkObserver
import com.topjohnwu.magisk.ktx.getProperty
import com.topjohnwu.superuser.ShellUtils.fastCmd

View File

@ -1,6 +1,8 @@
package com.topjohnwu.magisk.core.base
import android.Manifest.permission.*
import android.Manifest.permission.POST_NOTIFICATIONS
import android.Manifest.permission.REQUEST_INSTALL_PACKAGES
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
@ -53,9 +55,7 @@ abstract class BaseActivity : AppCompatActivity() {
val realCallingPackage: String? get() {
callingPackage?.let { return it }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
mReferrerField.get(this)?.let { return it as String }
}
mReferrerField.get(this)?.let { return it as String }
return null
}

View File

@ -0,0 +1,70 @@
package com.topjohnwu.magisk.core.utils
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.PowerManager
import androidx.collection.ArraySet
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.ktx.registerRuntimeReceiver
typealias ConnectionCallback = (Boolean) -> Unit
class NetworkObserver(
context: Context,
private val callback: ConnectionCallback
) {
private val manager = context.getSystemService<ConnectivityManager>()!!
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
private val activeList = ArraySet<Network>()
override fun onAvailable(network: Network) {
activeList.add(network)
callback(true)
}
override fun onLost(network: Network) {
activeList.remove(network)
callback(!activeList.isEmpty())
}
}
private val receiver = object : BroadcastReceiver() {
private fun Context.isIdleMode(): Boolean {
val pwm = getSystemService<PowerManager>() ?: return true
val isIgnoringOptimizations = pwm.isIgnoringBatteryOptimizations(packageName)
return pwm.isDeviceIdleMode && !isIgnoringOptimizations
}
override fun onReceive(context: Context, intent: Intent) {
if (context.isIdleMode()) {
callback(false)
} else {
getCurrentState()
}
}
}
init {
val builder = NetworkRequest.Builder()
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
manager.registerNetworkCallback(builder.build(), networkCallback)
val filter = IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)
context.applicationContext.registerRuntimeReceiver(receiver, filter)
}
fun getCurrentState() {
callback(manager.getNetworkCapabilities(manager.activeNetwork)
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false)
}
companion object {
fun observe(context: Context, callback: ConnectionCallback): NetworkObserver {
return NetworkObserver(context, callback).apply { getCurrentState() }
}
}
}

View File

@ -1,51 +0,0 @@
package com.topjohnwu.magisk.core.utils.net
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import androidx.collection.ArraySet
open class LollipopNetworkObserver(
context: Context,
callback: ConnectionCallback
): NetworkObserver(context, callback) {
private val networkCallback = NetCallback()
init {
val builder = NetworkRequest.Builder()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
} else {
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
manager.registerNetworkCallback(builder.build(), networkCallback)
}
@Suppress("DEPRECATION")
override fun getCurrentState() {
callback(manager.activeNetworkInfo?.isConnected ?: false)
}
override fun stopObserving() {
manager.unregisterNetworkCallback(networkCallback)
}
private inner class NetCallback : ConnectivityManager.NetworkCallback() {
private val activeList = ArraySet<Network>()
override fun onAvailable(network: Network) {
activeList.add(network)
callback(true)
}
override fun onLost(network: Network) {
activeList.remove(network)
callback(!activeList.isEmpty())
}
}
}

View File

@ -1,52 +0,0 @@
package com.topjohnwu.magisk.core.utils.net
import android.annotation.TargetApi
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.NetworkCapabilities
import android.os.PowerManager
import androidx.core.content.getSystemService
import com.topjohnwu.magisk.ktx.registerRuntimeReceiver
@TargetApi(23)
class MarshmallowNetworkObserver(
context: Context,
callback: ConnectionCallback
): LollipopNetworkObserver(context, callback) {
private val receiver = IdleBroadcastReceiver()
init {
val filter = IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)
app.registerRuntimeReceiver(receiver, filter)
}
override fun stopObserving() {
super.stopObserving()
app.unregisterReceiver(receiver)
}
override fun getCurrentState() {
callback(manager.getNetworkCapabilities(manager.activeNetwork)
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false)
}
private inner class IdleBroadcastReceiver: BroadcastReceiver() {
private fun Context.isIdleMode(): Boolean {
val pwm = getSystemService<PowerManager>() ?: return true
val isIgnoringOptimizations = pwm.isIgnoringBatteryOptimizations(packageName)
return pwm.isDeviceIdleMode && !isIgnoringOptimizations
}
override fun onReceive(context: Context, intent: Intent) {
if (context.isIdleMode()) {
callback(false)
} else {
getCurrentState()
}
}
}
}

View File

@ -1,29 +0,0 @@
package com.topjohnwu.magisk.core.utils.net
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import androidx.core.content.getSystemService
typealias ConnectionCallback = (Boolean) -> Unit
abstract class NetworkObserver(
context: Context,
protected val callback: ConnectionCallback
) {
protected val app: Context = context.applicationContext
protected val manager = context.getSystemService<ConnectivityManager>()!!
protected abstract fun stopObserving()
protected abstract fun getCurrentState()
companion object {
fun observe(context: Context, callback: ConnectionCallback): NetworkObserver {
val observer: NetworkObserver = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
MarshmallowNetworkObserver(context, callback)
else LollipopNetworkObserver(context, callback)
return observer.apply { getCurrentState() }
}
}
}

View File

@ -53,8 +53,7 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
AppSettings,
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath
))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 &&
Info.env.isActive && Const.USER_ID == 0) {
if (Info.env.isActive && Const.USER_ID == 0) {
if (hidden) list.add(Restore) else list.add(Hide)
}
@ -76,10 +75,6 @@ class SettingsViewModel : BaseViewModel(), BaseSettingsItem.Handler {
Tapjack, Biometrics, AccessMode, MultiuserMode, MountNamespaceMode,
AutomaticResponse, RequestTimeout, SUNotification
))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Biometric is only available on 6.0+
list.remove(Biometrics)
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// Re-authenticate is not feasible on 8.0+
list.add(Reauthenticate)

View File

@ -42,7 +42,6 @@ object Shortcuts {
IconCompat.createWithBitmap(getBitmap(id))
}
@RequiresApi(api = 23)
private fun Context.getIcon(id: Int) = getIconCompat(id).toIcon(this)
@RequiresApi(api = 25)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/splash_background" />
<item
android:width="250dp"
android:height="250dp"
android:gravity="center"
android:drawable="@drawable/ic_magisk" />
</layer-list>

View File

@ -2,11 +2,10 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/splash_background" />
<item
android:width="250dp"
android:height="250dp"
android:gravity="center"
android:drawable="@drawable/ic_magisk" />
<item>
<bitmap
android:src="@drawable/logo"
android:gravity="center"/>
</item>
</layer-list>
</layer-list>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V23.Theme.Foundation.Light" parent="Base.V21.Theme.Foundation.Light">
<item name="android:statusBarColor">#40bdbdbd</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V23.Theme.Foundation.Light" />
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_magisk_padded</item>
</style>
</resources>

View File

@ -7,7 +7,7 @@
<item name="android:windowLightNavigationBar">true</item>
</style>
<style name="Base.V27.Theme.Foundation" parent="Base.V21.Theme.Foundation">
<style name="Base.V27.Theme.Foundation" parent="Base.V23.Theme.Foundation">
<item name="android:navigationBarDividerColor">@android:color/transparent</item>
</style>

View File

@ -1,15 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V21.Theme.Foundation.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<style name="Base.V23.Theme.Foundation.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowBackground">?colorSurface</item>
<item name="android:windowContentOverlay">@null</item>
<item name="dialogTheme">@style/ThemeOverlay.Foundation.Dialog</item>
<item name="android:statusBarColor">#38000000</item>
<item name="android:statusBarColor">#40bdbdbd</item>
<item name="android:navigationBarColor">#38000000</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="Base.V21.Theme.Foundation" parent="Theme.MaterialComponents.NoActionBar">
<style name="Base.V23.Theme.Foundation" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowBackground">?colorSurface</item>
<item name="android:windowContentOverlay">@null</item>
<item name="dialogTheme">@style/ThemeOverlay.Foundation.Dialog</item>
@ -17,19 +18,20 @@
<item name="android:navigationBarColor">#60000000</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V21.Theme.Foundation.Light" />
<style name="Theme.Foundation.Light" parent="Base.V23.Theme.Foundation.Light" />
<style name="Theme.Foundation" parent="Base.V21.Theme.Foundation" />
<style name="Theme.Foundation" parent="Base.V23.Theme.Foundation" />
<style name="Theme.Splash" parent="Theme.SplashScreen">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="windowSplashScreenBackground">@color/splash_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_magisk_padded</item>
</style>
<style name="Base.V21.ThemeOverlay.Foundation.Dialog" parent="ThemeOverlay.MaterialComponents.Dialog">
<style name="Base.V23.ThemeOverlay.Foundation.Dialog" parent="ThemeOverlay.MaterialComponents.Dialog">
<item name="android:windowMinWidthMajor">@dimen/abc_dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@dimen/abc_dialog_min_width_minor</item>
</style>
<style name="ThemeOverlay.Foundation.Dialog" parent="Base.V21.ThemeOverlay.Foundation.Dialog" />
<style name="ThemeOverlay.Foundation.Dialog" parent="Base.V23.ThemeOverlay.Foundation.Dialog" />
</resources>

View File

@ -74,7 +74,7 @@ fun Project.setupCommon() {
ndkPath = "$sdkDirectory/ndk/magisk"
defaultConfig {
minSdk = 21
minSdk = 23
targetSdk = 33
}

View File

@ -145,29 +145,19 @@ static void exec_cmd(const char *action, vector<Extra> &data,
return;
}
// Then try start activity with package name
strscpy(target, info->mgr_pkg.data(), sizeof(target));
vector<const char *> args{ START_ACTIVITY };
for (auto &e : data) {
e.add_intent(args);
}
args.push_back(nullptr);
exec_t exec {
.err = true,
.fd = -1,
.fd = -2,
.pre_exec = [] { setenv("CLASSPATH", "/system/framework/am.jar", 1); },
.fork = fork_dont_care,
.argv = args.data()
};
// Then try start activity without package name
strscpy(target, info->mgr_pkg.data(), sizeof(target));
exec_command_sync(exec);
if (check_no_error(exec.fd))
return;
// Finally, fallback to start activity with component name
args[4] = "-n";
ssprintf(target, sizeof(target), "%s/com.topjohnwu.magisk.ui.surequest.SuRequestActivity", info->mgr_pkg.data());
exec.fd = -2;
exec.fork = fork_dont_care;
exec_command(exec);
}