Merge "Notify VPN status from SystemUI as notifications"
This commit is contained in:
committed by
Android (Google) Code Review
commit
94590a89b3
@@ -30,6 +30,7 @@
|
||||
<item>com.android.systemui.volume.VolumeUI</item>
|
||||
<item>com.android.systemui.statusbar.tv.TvStatusBar</item>
|
||||
<item>com.android.systemui.statusbar.tv.TvNotificationPanel</item>
|
||||
<item>com.android.systemui.statusbar.tv.VpnStatusObserver</item>
|
||||
<item>com.android.systemui.usb.StorageNotification</item>
|
||||
<item>com.android.systemui.power.PowerUI</item>
|
||||
<item>com.android.systemui.media.RingtonePlayer</item>
|
||||
|
||||
@@ -20,4 +20,10 @@
|
||||
<!-- Title and subtitle for AudioRecordingIndicator -->
|
||||
<string name="mic_active">Microphone Active</string>
|
||||
<string name="app_accessed_mic">%1$s accessed your microphone</string>
|
||||
|
||||
<string name="notification_vpn_connected">VPN is connected</string>
|
||||
<string name="notification_vpn_disconnected">VPN is disconnected</string>
|
||||
<!-- Disclosure text in the connected notification that indicates that the device is connected to a VPN. The placeholder is the VPN name. [CHAR LIMIT=40] -->
|
||||
<string name="notification_disclosure_vpn_text">Via <xliff:g id="vpn_app" example="Foo VPN App">%1$s</xliff:g></string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:JvmName("VpnStatusObserver")
|
||||
|
||||
package com.android.systemui.statusbar.tv
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import com.android.internal.messages.nano.SystemMessageProto
|
||||
import com.android.internal.net.VpnConfig
|
||||
import com.android.systemui.Dependency
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SystemUI
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.statusbar.policy.SecurityController
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Observes if a vpn connection is active and displays a notification to the user
|
||||
*/
|
||||
@SysUISingleton
|
||||
class VpnStatusObserver @Inject constructor(context: Context) : SystemUI(context),
|
||||
SecurityController.SecurityControllerCallback {
|
||||
|
||||
private var vpnConnected = false
|
||||
private val securityController: SecurityController =
|
||||
Dependency.get(SecurityController::class.java)
|
||||
private val notificationManager = NotificationManager.from(context)
|
||||
private val notificationChannel = createNotificationChannel()
|
||||
private val vpnConnectedNotificationBuilder = createVpnConnectedNotificationBuilder()
|
||||
private val vpnDisconnectedNotification = createVpnDisconnectedNotification()
|
||||
|
||||
private val vpnIconId: Int
|
||||
get() = if (securityController.isVpnBranded) {
|
||||
R.drawable.stat_sys_branded_vpn
|
||||
} else {
|
||||
R.drawable.stat_sys_vpn_ic
|
||||
}
|
||||
|
||||
private val vpnName: String?
|
||||
get() = securityController.primaryVpnName ?: securityController.workProfileVpnName
|
||||
|
||||
override fun start() {
|
||||
// register callback to vpn state changes
|
||||
securityController.addCallback(this)
|
||||
}
|
||||
|
||||
override fun onStateChanged() {
|
||||
securityController.isVpnEnabled.let { newVpnConnected ->
|
||||
if (vpnConnected != newVpnConnected) {
|
||||
if (newVpnConnected) {
|
||||
notifyVpnConnected()
|
||||
} else {
|
||||
notifyVpnDisconnected()
|
||||
}
|
||||
vpnConnected = newVpnConnected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyVpnConnected() = notificationManager.notify(
|
||||
NOTIFICATION_TAG,
|
||||
SystemMessageProto.SystemMessage.NOTE_VPN_STATUS,
|
||||
createVpnConnectedNotification()
|
||||
)
|
||||
|
||||
private fun notifyVpnDisconnected() = notificationManager.run {
|
||||
// remove existing connected notification
|
||||
cancel(NOTIFICATION_TAG, SystemMessageProto.SystemMessage.NOTE_VPN_STATUS)
|
||||
// show the disconnected notification only for a short while
|
||||
notify(NOTIFICATION_TAG, SystemMessageProto.SystemMessage.NOTE_VPN_DISCONNECTED,
|
||||
vpnDisconnectedNotification)
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() =
|
||||
NotificationChannel(
|
||||
NOTIFICATION_CHANNEL_TV_VPN,
|
||||
NOTIFICATION_CHANNEL_TV_VPN,
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
).also {
|
||||
notificationManager.createNotificationChannel(it)
|
||||
}
|
||||
|
||||
private fun createVpnConnectedNotification() =
|
||||
vpnConnectedNotificationBuilder
|
||||
.apply {
|
||||
vpnName?.let {
|
||||
setContentText(
|
||||
mContext.getString(
|
||||
R.string.notification_disclosure_vpn_text, it
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
||||
private fun createVpnConnectedNotificationBuilder() =
|
||||
Notification.Builder(mContext, NOTIFICATION_CHANNEL_TV_VPN)
|
||||
.setSmallIcon(vpnIconId)
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.extend(Notification.TvExtender())
|
||||
.setOngoing(true)
|
||||
.setContentTitle(mContext.getString(R.string.notification_vpn_connected))
|
||||
.setContentIntent(VpnConfig.getIntentForStatusPanel(mContext))
|
||||
|
||||
private fun createVpnDisconnectedNotification() =
|
||||
Notification.Builder(mContext, NOTIFICATION_CHANNEL_TV_VPN)
|
||||
.setSmallIcon(vpnIconId)
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setCategory(Notification.CATEGORY_SYSTEM)
|
||||
.extend(Notification.TvExtender())
|
||||
.setTimeoutAfter(VPN_DISCONNECTED_NOTIFICATION_TIMEOUT_MS)
|
||||
.setContentTitle(mContext.getString(R.string.notification_vpn_disconnected))
|
||||
.build()
|
||||
|
||||
companion object {
|
||||
const val NOTIFICATION_CHANNEL_TV_VPN = "VPN Status"
|
||||
val NOTIFICATION_TAG: String = VpnStatusObserver::class.java.simpleName
|
||||
|
||||
private const val TAG = "TvVpnNotification"
|
||||
private const val VPN_DISCONNECTED_NOTIFICATION_TIMEOUT_MS = 5_000L
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user