diff --git a/README.en.md b/README.en.md
index a735c58..6179280 100644
--- a/README.en.md
+++ b/README.en.md
@@ -68,7 +68,7 @@ only if installing Shizuku using ADB
### Install Pixel IMS application
1. As for now, there are two ways to obtain the application. Choose you favourite way and install the application.
- Via [Play Store](https://play.google.com/store/apps/details?id=dev.bluehouse.enablevolte)
- - From [Github Releases](https://github.com/kyujin-cho/pixel-volte-patch/releases/download/1.2.7/dev.bluehouse.enablevolte.apk), by downloading APK file
+ - From [Github Releases](https://github.com/kyujin-cho/pixel-volte-patch/releases/download/1.2.8/dev.bluehouse.enablevolte.apk), by downloading APK file
2. Start installed application.
3. Tap "Allow all the time" when seeing prompt asking for Shizuku permission.
![image-5](https://github.com/kyujin-cho/pixel-volte-patch/raw/main/assets/Screenshot_20230208-235239.png)
diff --git a/README.md b/README.md
index 0b054f5..d7cb69a 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ English version available [here](https://github.com/kyujin-cho/pixel-volte-patch
### Pixel IMS 어플리케이션 설치
1. 현재 다음 두 가지 방법으로 Pixel IMS 앱을 설치할 수 있습니다.
- - [Github Releases](https://github.com/kyujin-cho/pixel-volte-patch/releases/download/1.2.7/dev.bluehouse.enablevolte.apk) 에서 APK 다운로드 후 설치
+ - [Github Releases](https://github.com/kyujin-cho/pixel-volte-patch/releases/download/1.2.8/dev.bluehouse.enablevolte.apk) 에서 APK 다운로드 후 설치
- [Play Store](https://play.google.com/store/apps/details?id=dev.bluehouse.enablevolte) 에서 다운로드
2. 설치한 어플리케이션을 실행합니다.
3. 다음과 같이 Shizuku 권한을 묻는 팝업 창이 뜰 경우 "모든 경우에 허용" 을 선택합니다.
diff --git a/app/build.gradle b/app/build.gradle
index 8ab5374..c8b229a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,8 +11,8 @@ android {
applicationId "dev.bluehouse.enablevolte"
minSdk 29
targetSdk 33
- versionCode 12
- versionName "1.2.7"
+ versionCode 13
+ versionName "1.2.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 63993e8..b6efb38 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,7 +11,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.EnableVoLTE"
- tools:targetApi="31"
+ tools:targetApi="33"
android:localeConfig="@xml/locales_config">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Tile.STATE_ACTIVE
+ false -> Tile.STATE_INACTIVE
+ null -> Tile.STATE_UNAVAILABLE
+ }
+ qsTile.subtitle = getString(
+ when (imsActivated) {
+ true -> R.string.registered
+ false -> R.string.unregistered
+ null -> R.string.unknown
+ },
+ )
+ qsTile.updateTile()
+ }
+
+ override fun onStartListening() {
+ super.onStartListening()
+ this.refreshStatus()
+ }
+
+ override fun onClick() {
+ super.onClick()
+ moder?.restartIMSRegistration()
+ this.refreshStatus()
+ }
+}
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt b/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
index 70a4f78..b07e846 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/Moder.kt
@@ -77,6 +77,11 @@ open class Moder {
}
class CarrierModer(private val context: Context) : Moder() {
+ fun getActiveSubscriptionInfoForSimSlotIndex(index: Int): SubscriptionInfo? {
+ val sub = this.loadCachedInterface { sub }
+ return sub.getActiveSubscriptionInfoForSimSlotIndex(index, null, null)
+ }
+
val subscriptions: List
get() {
val sub = this.loadCachedInterface { sub }
@@ -260,6 +265,9 @@ class SubscriptionModer(val subscriptionId: Int) : Moder() {
return config.get(key)
}
+ val simSlotIndex: Int
+ get() = this.loadCachedInterface { sub }.getSlotIndex(subscriptionId)
+
val isVoLteConfigEnabled: Boolean
get() = this.getBooleanValue(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL)
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/Utils.kt b/app/src/main/java/dev/bluehouse/enablevolte/Utils.kt
index cee7991..359dd5d 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/Utils.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/Utils.kt
@@ -33,7 +33,7 @@ fun checkShizukuPermission(code: Int): ShizukuStatus {
}
val SubscriptionInfo.uniqueName: String
- get() = "${this.subscriptionId} - ${this.displayName}"
+ get() = "${this.displayName} (SIM ${this.simSlotIndex + 1})"
fun getLatestAppVersion(handler: (String) -> Unit) {
"https://api.github.com/repos/kyujin-cho/pixel-volte-patch/releases"
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/VoLTEConfigToggleQSTileService.kt b/app/src/main/java/dev/bluehouse/enablevolte/VoLTEConfigToggleQSTileService.kt
new file mode 100644
index 0000000..ac333e6
--- /dev/null
+++ b/app/src/main/java/dev/bluehouse/enablevolte/VoLTEConfigToggleQSTileService.kt
@@ -0,0 +1,90 @@
+package dev.bluehouse.enablevolte
+
+import android.service.quicksettings.Tile
+import android.service.quicksettings.TileService
+import android.telephony.CarrierConfigManager
+import org.lsposed.hiddenapibypass.HiddenApiBypass
+import java.lang.IllegalStateException
+
+class SIM1VoLTEConfigToggleQSTileService : VoLTEConfigToggleQSTileService(0)
+class SIM2VoLTEConfigToggleQSTileService : VoLTEConfigToggleQSTileService(1)
+
+open class VoLTEConfigToggleQSTileService(private val simSlotIndex: Int) : TileService() {
+ private val TAG = "SIM${simSlotIndex}VoLTEConfigToggleQSTileService"
+
+ init {
+ HiddenApiBypass.addHiddenApiExemptions("L")
+ HiddenApiBypass.addHiddenApiExemptions("I")
+ }
+
+ private val moder: SubscriptionModer? get() {
+ val carrierModer = CarrierModer(this.applicationContext)
+
+ try {
+ if (checkShizukuPermission(0) == ShizukuStatus.GRANTED && carrierModer.deviceSupportsIMS) {
+ carrierModer.subscriptions
+ val sub = carrierModer.getActiveSubscriptionInfoForSimSlotIndex(this.simSlotIndex)
+ ?: return null
+ return SubscriptionModer(sub.subscriptionId)
+ }
+ } catch (_: IllegalStateException) {}
+ return null
+ }
+
+ private val volteEnabled: Boolean? get() {
+ /*
+ * true: VoLTE enabled
+ * false: VoLTE disabled
+ * null: cannot determine status (Shizuku not running or permission not granted, SIM slot not active, ...)
+ */
+ val moder = this.moder ?: return null
+ try {
+ return moder.isVoLteConfigEnabled
+ } catch (_: IllegalStateException) {}
+ return null
+ }
+
+ override fun onTileAdded() {
+ super.onTileAdded()
+ if (this.volteEnabled == null) {
+ qsTile.state = Tile.STATE_UNAVAILABLE
+ }
+ }
+
+ override fun onStartListening() {
+ super.onStartListening()
+ qsTile.state = when (this.volteEnabled) {
+ true -> Tile.STATE_ACTIVE
+ false -> Tile.STATE_INACTIVE
+ null -> Tile.STATE_UNAVAILABLE
+ }
+ qsTile.subtitle = getString(
+ when (this.volteEnabled) {
+ true -> R.string.enabled
+ false -> R.string.disabled
+ null -> R.string.unknown
+ },
+ )
+ qsTile.updateTile()
+ }
+
+ private fun toggleVoLTEStatus() {
+ val moder = this.moder ?: return
+ val volteEnabled = this.volteEnabled ?: return
+ moder.updateCarrierConfig(CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL, !volteEnabled)
+ moder.restartIMSRegistration()
+ qsTile.state = if (volteEnabled) Tile.STATE_INACTIVE else Tile.STATE_ACTIVE
+ qsTile.subtitle = getString(if (volteEnabled) R.string.disabled else R.string.enabled)
+ qsTile.updateTile()
+ }
+
+ // Called when the user taps on your tile in an active or inactive state.
+ override fun onClick() {
+ super.onClick()
+ if (isLocked) {
+ unlockAndRun { toggleVoLTEStatus() }
+ } else {
+ toggleVoLTEStatus()
+ }
+ }
+}
diff --git a/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt b/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
index ce3ae1e..baed722 100644
--- a/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
+++ b/app/src/main/java/dev/bluehouse/enablevolte/pages/Config.kt
@@ -1,6 +1,10 @@
package dev.bluehouse.enablevolte.pages
+import android.app.StatusBarManager
+import android.content.ComponentName
+import android.graphics.drawable.Icon
import android.os.Build
+import android.os.Build.VERSION
import android.telephony.CarrierConfigManager
import android.util.Log
import android.widget.Toast
@@ -71,6 +75,8 @@ fun Config(navController: NavController, subId: Int) {
var reversedConfigurableItems by rememberSaveable { mutableStateOf