diff --git a/tools/chatgui-android/router-tests/src/main/kotlin/android/app/HostNotifications.kt b/tools/chatgui-android/router-tests/src/main/kotlin/android/app/HostNotifications.kt index 84ee808c0..7286888dc 100644 --- a/tools/chatgui-android/router-tests/src/main/kotlin/android/app/HostNotifications.kt +++ b/tools/chatgui-android/router-tests/src/main/kotlin/android/app/HostNotifications.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.net.Uri class Notification { + companion object { const val VISIBILITY_PUBLIC = 1 } data class Action(val title: String, val intent: PendingIntent) var channelId = "" var title = "" @@ -17,10 +18,14 @@ class Notification { var contentIntent: PendingIntent? = null var fullScreenIntent: PendingIntent? = null var bigText: String? = null + var visibility = 0; var foregroundBehavior = 0; var showWhen = false; var chronometer = false; var whenMs = 0L + var person: androidx.core.app.Person? = null + var hangup: PendingIntent? = null val actions = mutableListOf() } class NotificationChannel(val id: String, val name: String, val importance: Int) { + var lockscreenVisibility = 0 var description = "" var vibration = true var silent = false @@ -30,7 +35,7 @@ class NotificationChannel(val id: String, val name: String, val importance: Int) /** Host OS boundaries: отказы канала, разрешений и публикации независимы. */ class NotificationManager { - companion object { const val IMPORTANCE_HIGH = 4; const val IMPORTANCE_LOW = 2 } + companion object { const val IMPORTANCE_HIGH = 4; const val IMPORTANCE_LOW = 2; const val IMPORTANCE_DEFAULT = 3 } var failures = emptySet() var notificationsEnabled = true var fullScreenAllowed = true @@ -45,6 +50,10 @@ class NotificationManager { check("channel" !in failures) { "channel unavailable" } channels[channel.id] = channel } + fun getNotificationChannel(id: String): NotificationChannel? { + check("channel query" !in failures) { "channel query unavailable" } + return channels[id] + } fun canUseFullScreenIntent(): Boolean { fullScreenQueries++ check("full screen" !in failures) { "full-screen service unavailable" } @@ -94,6 +103,7 @@ class PendingIntent private constructor(val kind: String, val requestCode: Int, } fun getActivity(context: Context, requestCode: Int, intent: Intent, flags: Int) = obtain("activity", requestCode, intent, flags) fun getBroadcast(context: Context, requestCode: Int, intent: Intent, flags: Int) = obtain("broadcast", requestCode, intent, flags) + fun getService(context: Context, requestCode: Int, intent: Intent, flags: Int) = obtain("service", requestCode, intent, flags) } private var intent = Intent(intent) var failCancel = false diff --git a/tools/chatgui-android/router-tests/src/main/kotlin/android/app/Service.kt b/tools/chatgui-android/router-tests/src/main/kotlin/android/app/Service.kt index 93ccd3fff..36bba8ac1 100644 --- a/tools/chatgui-android/router-tests/src/main/kotlin/android/app/Service.kt +++ b/tools/chatgui-android/router-tests/src/main/kotlin/android/app/Service.kt @@ -13,6 +13,9 @@ open class Service : Context() { var failForeground = false var failForegroundAfter = false var stops = 0 + var foregroundStops = 0 + var failForegroundStop = false + var failStopSelf = false var destroys = 0 open fun onCreate() {} open fun onStartCommand(intent: Intent?, flags: Int, startId: Int) = START_NOT_STICKY @@ -25,7 +28,11 @@ open class Service : Context() { requireNotNull(notificationManager).notify(id, notification) check(!failForegroundAfter) { "foreground promotion failed after effect" } } - fun stopForeground(flags: Int) { if (flags == STOP_FOREGROUND_REMOVE && foregroundId != 0) notificationManager?.cancel(foregroundId) } - fun stopSelf() { stops++ } - fun stopSelf(startId: Int) { stops++ } + fun stopForeground(flags: Int) { + foregroundStops++ + check(!failForegroundStop) { "foreground removal unavailable" } + if (flags == STOP_FOREGROUND_REMOVE && foregroundId != 0) notificationManager?.cancel(foregroundId) + } + fun stopSelf() { stops++; check(!failStopSelf) { "service stop unavailable" } } + fun stopSelf(startId: Int) { stopSelf() } } diff --git a/tools/chatgui-android/router-tests/src/main/kotlin/androidx/core/app/HostNotifications.kt b/tools/chatgui-android/router-tests/src/main/kotlin/androidx/core/app/HostNotifications.kt index a839e0f37..ccb98fa83 100644 --- a/tools/chatgui-android/router-tests/src/main/kotlin/androidx/core/app/HostNotifications.kt +++ b/tools/chatgui-android/router-tests/src/main/kotlin/androidx/core/app/HostNotifications.kt @@ -8,11 +8,16 @@ import android.content.Context object NotificationCompat { const val CATEGORY_CALL = "call" const val PRIORITY_MAX = 2 + const val VISIBILITY_PUBLIC = 1 + const val FOREGROUND_SERVICE_IMMEDIATE = 1 var failBuild = false class BigTextStyle { var text = "" fun bigText(value: String) = apply { text = value } } + class CallStyle(val person: Person, val hangup: PendingIntent) { + companion object { fun forOngoingCall(person: Person, hangup: PendingIntent) = CallStyle(person, hangup) } + } class Builder(context: Context, channelId: String) { private val notification = Notification().apply { this.channelId = channelId } fun setSmallIcon(value: Int) = this @@ -26,11 +31,27 @@ object NotificationCompat { fun setContentIntent(value: PendingIntent) = apply { notification.contentIntent = value } fun setFullScreenIntent(value: PendingIntent, priority: Boolean) = apply { check(priority); notification.fullScreenIntent = value } fun setStyle(value: BigTextStyle) = apply { notification.bigText = value.text } + fun setStyle(value: CallStyle) = apply { notification.person = value.person; notification.hangup = value.hangup } + fun setVisibility(value: Int) = apply { notification.visibility = value } + fun setForegroundServiceBehavior(value: Int) = apply { notification.foregroundBehavior = value } + fun addPerson(value: Person) = this + fun setShowWhen(value: Boolean) = apply { notification.showWhen = value } + fun setUsesChronometer(value: Boolean) = apply { notification.chronometer = value } + fun setWhen(value: Long) = apply { notification.whenMs = value } fun addAction(icon: Int, title: String, intent: PendingIntent) = apply { notification.actions.add(Notification.Action(title, intent)) } fun build(): Notification { check(!failBuild) { "notification build unavailable" }; return notification } } } +class Person private constructor(val name: String, val key: String) { + class Builder { + private var name = ""; private var key = "" + fun setName(value: String) = apply { name = value } + fun setKey(value: String) = apply { key = value } + fun build() = Person(name, key) + } +} + class NotificationManagerCompat private constructor(private val context: Context) { companion object { fun from(context: Context) = NotificationManagerCompat(context) } private val manager get() = requireNotNull(context.notificationManager) { "notification manager unavailable" }