1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.statusbar.policy
18 
19 import android.app.Notification
20 import android.app.NotificationChannel
21 import android.app.NotificationManager
22 import android.app.PendingIntent
23 import android.content.Context
24 import android.content.Intent
25 import android.net.Uri
26 import com.android.systemui.R
27 import com.android.systemui.util.concurrency.DelayableExecutor
28 import javax.inject.Inject
29 
30 /**
31  * Listens for important battery states and sends non-dismissible system notifications if there is a
32  * problem
33  */
34 class BatteryStateNotifier @Inject constructor(
35     val controller: BatteryController,
36     val noMan: NotificationManager,
37     val delayableExecutor: DelayableExecutor,
38     val context: Context
39 ) : BatteryController.BatteryStateChangeCallback {
40     var stateUnknown = false
41 
42     fun startListening() {
43         controller.addCallback(this)
44     }
45 
46     fun stopListening() {
47         controller.removeCallback(this)
48     }
49 
50     override fun onBatteryUnknownStateChanged(isUnknown: Boolean) {
51         stateUnknown = isUnknown
52         if (stateUnknown) {
53             val channel = NotificationChannel("battery_status", "Battery status",
54                     NotificationManager.IMPORTANCE_DEFAULT)
55             noMan.createNotificationChannel(channel)
56 
57             val intent = Intent(Intent.ACTION_VIEW,
58                     Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl)))
59             val pi = PendingIntent.getActivity(context, 0, intent,
60                     PendingIntent.FLAG_IMMUTABLE)
61 
62             val builder = Notification.Builder(context, channel.id)
63                     .setAutoCancel(false)
64                     .setContentTitle(
65                             context.getString(R.string.battery_state_unknown_notification_title))
66                     .setContentText(
67                             context.getString(R.string.battery_state_unknown_notification_text))
68                     .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
69                     .setContentIntent(pi)
70                     .setAutoCancel(true)
71                     .setOngoing(true)
72 
73             noMan.notify(TAG, ID, builder.build())
74         } else {
75             scheduleNotificationCancel()
76         }
77     }
78 
79     private fun scheduleNotificationCancel() {
80         val r = {
81             if (!stateUnknown) {
82                 noMan.cancel(ID)
83             }
84         }
85         delayableExecutor.executeDelayed(r, DELAY_MILLIS)
86     }
87 }
88 
89 private const val TAG = "BatteryStateNotifier"
90 private const val ID = 666
91 private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
92