Skip to content

Commit 8dabb6a

Browse files
committed
refactor: A11yRuleEngine
1 parent d94ea61 commit 8dabb6a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1380
-1583
lines changed

app/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ plugins {
5151
alias(libs.plugins.kotlin.parcelize)
5252
alias(libs.plugins.kotlin.serialization)
5353
alias(libs.plugins.kotlin.compose)
54+
alias(libs.plugins.kotlinx.atomicfu)
5455
alias(libs.plugins.google.ksp)
5556
}
5657

@@ -246,6 +247,8 @@ dependencies {
246247
implementation(libs.google.accompanist.drawablepainter)
247248

248249
implementation(libs.kotlinx.serialization.json)
250+
// https://github.com/Kotlin/kotlinx-atomicfu/issues/145
251+
implementation(libs.kotlinx.atomicfu)
249252

250253
implementation(libs.utilcodex)
251254
implementation(libs.activityResultLauncher)

app/src/main/AndroidManifest.xml

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,7 @@
6565
<action android:name="android.intent.action.MAIN" />
6666
<category android:name="android.intent.category.LAUNCHER" />
6767
</intent-filter>
68-
<intent-filter>
69-
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
70-
</intent-filter>
7168
</activity>
72-
7369
<activity
7470
android:name=".OpenSchemeActivity"
7571
android:exported="true"
@@ -83,7 +79,6 @@
8379
<data android:scheme="gkd" />
8480
</intent-filter>
8581
</activity>
86-
8782
<activity
8883
android:name=".OpenFileActivity"
8984
android:exported="true"
@@ -99,6 +94,14 @@
9994
<data android:mimeType="application/x-zip-compressed" />
10095
</intent-filter>
10196
</activity>
97+
<activity
98+
android:name=".OpenTileActivity"
99+
android:exported="true"
100+
android:theme="@style/TransparentTheme">
101+
<intent-filter>
102+
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
103+
</intent-filter>
104+
</activity>
102105

103106
<provider
104107
android:name="rikka.shizuku.ShizukuProvider"
@@ -107,7 +110,6 @@
107110
android:exported="true"
108111
android:multiprocess="false"
109112
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />
110-
111113
<provider
112114
android:name="androidx.core.content.FileProvider"
113115
android:authorities="${applicationId}.provider"
@@ -168,13 +170,25 @@
168170
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
169171
android:value="Display a text card for users to show current activity info" />
170172
</service>
173+
<service
174+
android:name=".service.SnapshotActionService"
175+
android:exported="true"
176+
android:foregroundServiceType="specialUse"
177+
tools:ignore="ExportedService">
178+
<property
179+
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
180+
android:value="Provide an interface for third-party applications to actively invoke snapshot capturing." />
181+
</service>
182+
171183
<service
172184
android:name=".service.GkdTileService"
173185
android:exported="true"
174186
android:icon="@drawable/ic_status"
175187
android:label="@string/app_name"
176188
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
177-
189+
<meta-data
190+
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
191+
android:value="true" />
178192
<intent-filter>
179193
<action android:name="android.service.quicksettings.action.QS_TILE" />
180194
</intent-filter>
@@ -195,6 +209,9 @@
195209
android:icon="@drawable/ic_http"
196210
android:label="@string/http_server"
197211
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
212+
<meta-data
213+
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
214+
android:value="true" />
198215
<intent-filter>
199216
<action android:name="android.service.quicksettings.action.QS_TILE" />
200217
</intent-filter>
@@ -205,6 +222,9 @@
205222
android:icon="@drawable/ic_radio_button"
206223
android:label="@string/snapshot_button"
207224
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
225+
<meta-data
226+
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
227+
android:value="true" />
208228
<intent-filter>
209229
<action android:name="android.service.quicksettings.action.QS_TILE" />
210230
</intent-filter>
@@ -215,6 +235,9 @@
215235
android:icon="@drawable/ic_flash_on"
216236
android:label="@string/rule_match"
217237
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
238+
<meta-data
239+
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
240+
android:value="true" />
218241
<intent-filter>
219242
<action android:name="android.service.quicksettings.action.QS_TILE" />
220243
</intent-filter>
@@ -225,21 +248,14 @@
225248
android:icon="@drawable/ic_layers"
226249
android:label="@string/record_activity"
227250
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
251+
<meta-data
252+
android:name="android.service.quicksettings.TOGGLEABLE_TILE"
253+
android:value="true" />
228254
<intent-filter>
229255
<action android:name="android.service.quicksettings.action.QS_TILE" />
230256
</intent-filter>
231257
</service>
232258

233-
<service
234-
android:name=".service.SnapshotActionService"
235-
android:exported="true"
236-
android:foregroundServiceType="specialUse"
237-
tools:ignore="ExportedService">
238-
<property
239-
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
240-
android:value="Provide an interface for third-party applications to actively invoke snapshot capturing." />
241-
</service>
242-
243259
<!-- remove useless -->
244260
<activity
245261
android:name="com.blankj.utilcode.util.UtilsTransActivity4MainProcess"

app/src/main/kotlin/li/songe/gkd/App.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import android.content.Context
77
import android.content.pm.ApplicationInfo
88
import android.content.pm.PackageManager
99
import android.os.Build
10+
import android.provider.Settings
1011
import com.blankj.utilcode.util.LogUtils
1112
import com.blankj.utilcode.util.Utils
1213
import kotlinx.coroutines.MainScope
1314
import kotlinx.serialization.Serializable
1415
import li.songe.gkd.data.selfAppInfo
1516
import li.songe.gkd.notif.initChannel
17+
import li.songe.gkd.service.StatusService
1618
import li.songe.gkd.service.clearHttpSubs
1719
import li.songe.gkd.shizuku.initShizuku
1820
import li.songe.gkd.store.initStore
@@ -41,6 +43,9 @@ private fun getMetaString(key: String): String {
4143
return applicationInfo.metaData.getString(key) ?: error("Missing meta-data: $key")
4244
}
4345

46+
// https://github.com/aosp-mirror/platform_frameworks_base/blob/android16-release/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java#L41
47+
private const val ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':'
48+
4449
@Serializable
4550
data class AppMeta(
4651
val channel: String = getMetaString("channel"),
@@ -75,6 +80,24 @@ class App : Application() {
7580
}
7681
}
7782

83+
fun getSecureString(name: String): String? = Settings.Secure.getString(contentResolver, name)
84+
fun putSecureString(name: String, value: String?): Boolean {
85+
return Settings.Secure.putString(contentResolver, name, value)
86+
}
87+
88+
fun getSecureA11yServices(): MutableSet<String> {
89+
return (getSecureString(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) ?: "").split(
90+
ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR
91+
).toHashSet()
92+
}
93+
94+
fun putSecureA11yServices(services: Set<String>) {
95+
putSecureString(
96+
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
97+
services.joinToString(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR.toString())
98+
)
99+
}
100+
78101
val startTime = System.currentTimeMillis()
79102

80103
val activityManager by lazy { app.getSystemService(ACTIVITY_SERVICE) as ActivityManager }
@@ -103,5 +126,6 @@ class App : Application() {
103126
initSubsState()
104127
clearHttpSubs()
105128
syncFixState()
129+
StatusService.autoStart()
106130
}
107131
}

app/src/main/kotlin/li/songe/gkd/MainActivity.kt

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ import kotlinx.coroutines.flow.updateAndGet
6363
import kotlinx.coroutines.launch
6464
import kotlinx.coroutines.sync.Mutex
6565
import kotlinx.coroutines.sync.withLock
66+
import li.songe.gkd.a11y.topActivityFlow
67+
import li.songe.gkd.a11y.updateImeAppId
68+
import li.songe.gkd.a11y.updateLauncherAppId
69+
import li.songe.gkd.a11y.updateTopActivity
6670
import li.songe.gkd.permission.AuthDialog
6771
import li.songe.gkd.permission.updatePermissionState
6872
import li.songe.gkd.service.A11yService
@@ -71,8 +75,6 @@ import li.songe.gkd.service.HttpService
7175
import li.songe.gkd.service.ScreenshotService
7276
import li.songe.gkd.service.StatusService
7377
import li.songe.gkd.service.fixRestartService
74-
import li.songe.gkd.service.updateDefaultInputAppId
75-
import li.songe.gkd.service.updateLauncherAppId
7678
import li.songe.gkd.store.storeFlow
7779
import li.songe.gkd.ui.component.BuildDialog
7880
import li.songe.gkd.ui.component.ShareDataDialog
@@ -95,6 +97,7 @@ import li.songe.gkd.util.openUri
9597
import li.songe.gkd.util.shizukuAppId
9698
import li.songe.gkd.util.throttle
9799
import li.songe.gkd.util.toast
100+
import kotlin.concurrent.Volatile
98101
import kotlin.reflect.KClass
99102
import kotlin.reflect.jvm.jvmName
100103

@@ -160,7 +163,6 @@ class MainActivity : ComponentActivity() {
160163
mainVm
161164
launcher
162165
pickContentLauncher
163-
StatusService.autoStart()
164166
lifecycleScope.launch {
165167
storeFlow.mapState(lifecycleScope) { s -> s.excludeFromRecents }.collect {
166168
app.activityManager.appTasks.forEach { task ->
@@ -214,7 +216,10 @@ class MainActivity : ComponentActivity() {
214216

215217
override fun onStart() {
216218
super.onStart()
217-
activityVisibleFlow.update { it + 1 }
219+
activityVisibleState++
220+
if (topActivityFlow.value.appId != META.appId) {
221+
updateTopActivity(META.appId, MainActivity::class.jvmName)
222+
}
218223
}
219224

220225
var isFirstResume = true
@@ -229,7 +234,7 @@ class MainActivity : ComponentActivity() {
229234

230235
override fun onStop() {
231236
super.onStop()
232-
activityVisibleFlow.update { it - 1 }
237+
activityVisibleState--
233238
}
234239

235240
private var lastBackPressedTime = 0L
@@ -246,16 +251,19 @@ class MainActivity : ComponentActivity() {
246251
}
247252
}
248253

249-
private val activityVisibleFlow by lazy { MutableStateFlow(0) }
250-
fun isActivityVisible() = activityVisibleFlow.value > 0
254+
@Volatile
255+
private var activityVisibleState = 0
256+
fun isActivityVisible() = activityVisibleState > 0
257+
258+
val activityNavSourceName by lazy { META.appId + ".activity.nav.source" }
251259

252260
fun Activity.navToMainActivity() {
253-
val intent = this.intent?.cloneFilter()
254261
if (intent != null) {
255-
intent.component = MainActivity::class.componentName
256-
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
257-
intent.putExtra("source", this::class.qualifiedName)
258-
startActivity(intent)
262+
val navIntent = Intent(intent)
263+
navIntent.component = MainActivity::class.componentName
264+
navIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
265+
navIntent.putExtra(activityNavSourceName, this::class.jvmName)
266+
startActivity(navIntent)
259267
}
260268
finish()
261269
}
@@ -286,7 +294,7 @@ fun syncFixState() {
286294
// 每次切换页面更新记录桌面 appId
287295
updateLauncherAppId()
288296

289-
updateDefaultInputAppId()
297+
updateImeAppId()
290298

291299
// 由于某些机型的进程存在 安装缓存/崩溃缓存 导致服务状态可能不正确, 在此保证每次界面切换都能重新刷新状态
292300
updateServiceRunning()

0 commit comments

Comments
 (0)