Skip to content

Commit

Permalink
feat: media session as scope provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Mufanc committed May 23, 2024
1 parent 6af7956 commit 08a8d69
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 25 deletions.
11 changes: 11 additions & 0 deletions api-stub/src/main/java/android/app/ActivityThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package android.app;

public class ActivityThread {
public static ActivityThread currentActivityThread() {
throw new RuntimeException("STUB");
}

public ContextImpl getSystemContext() {
throw new RuntimeException("STUB");
}
}
7 changes: 7 additions & 0 deletions api-stub/src/main/java/android/app/ContextImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package android.app;

import android.content.Context;

public abstract class ContextImpl extends Context {

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ object AppLockService : IAppLockService.Stub() {
)
}

fun client(): IAppLockService {
fun client(): IAppLockService? {
return client
}

Expand Down
34 changes: 29 additions & 5 deletions app/src/main/java/xyz/mufanc/applock/core/ModuleMain.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package xyz.mufanc.applock.core

import android.os.Handler
import android.os.Looper
import androidx.annotation.Keep
import io.github.libxposed.api.XposedInterface
import io.github.libxposed.api.XposedModule
Expand All @@ -13,6 +15,7 @@ import xyz.mufanc.applock.core.util.GraftClassLoader
import xyz.mufanc.applock.core.util.Log
import xyz.mufanc.applock.util.Configs
import xyz.mufanc.autox.annotation.XposedEntry
import kotlin.concurrent.thread

@Keep
@XposedEntry(["system"])
Expand All @@ -37,12 +40,33 @@ class ModuleMain(
GraftClassLoader.init(param.classLoader)

ProcessRecordUtil.init()
AppLockService.init(ixp)
ScopeManager.init(ixp)
ProcessGuard.install(ixp)

if (Configs.isDebug) {
KillProcessMonitor.init(ixp)
Log.d(TAG, "waiting for system...")

runOnSystemReady {
AppLockService.init(ixp)
ScopeManager.init(ixp)
ProcessGuard.install(ixp)

if (Configs.isDebug) {
KillProcessMonitor.init(ixp)
}
}
}

private fun runOnSystemReady(block: () -> Unit) {
thread {
try {
while (Looper.getMainLooper() == null) {
Thread.sleep(1000)
}

Handler(Looper.getMainLooper()).post {
block()
}
} catch (err: Throwable) {
Log.e(TAG, "", err)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object ScopeManager {
Log.i(TAG, "initializing scope provider: ${klass.simpleName}")
provider.init(ixp)
} catch (err: Throwable) {
Log.e(TAG, "failed to initialize scope provider: ${klass.simpleName}")
Log.e(TAG, "failed to initialize scope provider: ${klass.simpleName}", err)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package xyz.mufanc.applock.core.scope.provider

import android.media.session.MediaSessionManager
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener
import android.app.ActivityThread
import io.github.libxposed.api.XposedInterface
import xyz.mufanc.applock.core.util.Log

@Suppress("Unused")
data object MediaSessionProvider : ScopeProvider() {

private const val TAG = "MediaSessionProvider"

private val manager: MediaSessionManager by lazy {
ActivityThread.currentActivityThread()
.systemContext
.getSystemService(MediaSessionManager::class.java)
}

private val listener = OnActiveSessionsChangedListener { controllers ->
if (controllers != null) {
emit(controllers.map { it.packageName }.toSet())
}
}

override fun isAvailable(): Boolean = true

override fun init(ixp: XposedInterface) {
manager.addOnActiveSessionsChangedListener(listener, null)
Log.d(TAG, "initialized")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceGroup
import androidx.preference.forEach
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import xyz.mufanc.applock.R
import xyz.mufanc.applock.ui.util.ThemeManager
import xyz.mufanc.applock.ui.widgets.LicenseListDialog
Expand Down Expand Up @@ -60,7 +58,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
true
}
"scope_providers" -> {
ScopeProviderSelectorDialog(requireActivity()).show()
ScopeProviderSelectorDialog(requireActivity())?.show()
true
}
else -> super.onPreferenceTreeClick(preference)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
Expand All @@ -26,8 +27,10 @@ class ScopeProviderSelectorDialog private constructor(

private val disabledProviders = RemotePrefs.disabledProviders.asLiveData()

operator fun invoke(activity: Activity): ScopeProviderSelectorDialog {
val availableProviders = AppLockService.client().availableProviders.toSet()
operator fun invoke(activity: Activity): ScopeProviderSelectorDialog? {
val service = AppLockService.client() ?: return null
val availableProviders = service.availableProviders.toSet()

Log.d(TAG, "available providers: $availableProviders")
Log.d(TAG, "disabled providers: ${disabledProviders.value?.all?.keys}")

Expand All @@ -52,18 +55,22 @@ class ScopeProviderSelectorDialog private constructor(
.create()


activity.registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityDestroyed(activity: Activity) {
dialog.dismiss()
}

override fun onActivityCreated(activity: Activity, bundle: Bundle?) = Unit
override fun onActivityStarted(activity: Activity) = Unit
override fun onActivityResumed(activity: Activity) = Unit
override fun onActivityPaused(activity: Activity) = Unit
override fun onActivityStopped(activity: Activity) = Unit
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) = Unit
})
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
activity.registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityDestroyed(activity: Activity) {
dialog.dismiss()
}

override fun onActivityCreated(activity: Activity, bundle: Bundle?) = Unit
override fun onActivityStarted(activity: Activity) = Unit
override fun onActivityResumed(activity: Activity) = Unit
override fun onActivityPaused(activity: Activity) = Unit
override fun onActivityStopped(activity: Activity) = Unit
override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) = Unit
})
} else {
// Todo:
}

return ScopeProviderSelectorDialog(dialog)
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

<string-array name="scope_providers">
<item>PreferenceScopeProvider</item>
<item>MediaScopeProvider</item>
<item>MediaSessionProvider</item>
</string-array>

<string-array name="scope_provider_names">
Expand Down

0 comments on commit 08a8d69

Please sign in to comment.