1 /*
2  * Copyright (C) 2015 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 package com.android.car;
17 
18 import android.app.Notification;
19 import android.app.NotificationChannel;
20 import android.app.NotificationManager;
21 import android.content.Context;
22 import android.os.Build;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.GuardedBy;
26 
27 import java.util.HashSet;
28 import java.util.Set;
29 
30 /**
31  * Class used to notify user about CAN bus failure.
32  */
33 final class CanBusErrorNotifier {
34     private static final String TAG = CarLog.TAG_CAN_BUS + ".NOTIFIER";
35     private static final int NOTIFICATION_ID = 1;
36     private static final boolean IS_RELEASE_BUILD = "user".equals(Build.TYPE);
37 
38     private final Context mContext;
39     private final NotificationManager mNotificationManager;
40 
41     // Contains a set of objects that reported failure. The notification will be hidden only when
42     // this set is empty (all reported objects are in love and peace with the vehicle).
43     @GuardedBy("this")
44     private final Set<Object> mReportedObjects = new HashSet<>();
45 
CanBusErrorNotifier(Context context)46     CanBusErrorNotifier(Context context) {
47         mNotificationManager = (NotificationManager) context.getSystemService(
48                 Context.NOTIFICATION_SERVICE);
49         mContext = context;
50     }
51 
removeFailureReport(Object sender)52     public void removeFailureReport(Object sender) {
53         setCanBusFailure(false, sender);
54     }
55 
reportFailure(Object sender)56     public void reportFailure(Object sender) {
57         setCanBusFailure(true, sender);
58     }
59 
setCanBusFailure(boolean failed, Object sender)60     private void setCanBusFailure(boolean failed, Object sender) {
61         boolean shouldShowNotification;
62         synchronized (this) {
63             boolean changed = failed
64                     ? mReportedObjects.add(sender) : mReportedObjects.remove(sender);
65 
66             if (!changed) {
67                 return;
68             }
69 
70             shouldShowNotification = !mReportedObjects.isEmpty();
71         }
72 
73         if (Log.isLoggable(TAG, Log.INFO)) {
74             Log.i(TAG, "Changing CAN bus failure state to " + shouldShowNotification);
75         }
76 
77         if (shouldShowNotification) {
78             showNotification();
79         } else {
80             hideNotification();
81         }
82     }
83 
showNotification()84     private void showNotification() {
85         if (IS_RELEASE_BUILD) {
86             // TODO: for user, we should show message to take car to the dealer. bug:32096297
87             return;
88         }
89         Notification notification =
90                 new Notification.Builder(mContext, NotificationChannel.DEFAULT_CHANNEL_ID)
91                         .setContentTitle(mContext.getString(R.string.car_can_bus_failure))
92                         .setContentText(mContext.getString(R.string.car_can_bus_failure_desc))
93                         .setSmallIcon(R.drawable.car_ic_error)
94                         .setOngoing(true)
95                         .build();
96         mNotificationManager.notify(TAG, NOTIFICATION_ID, notification);
97     }
98 
hideNotification()99     private void hideNotification() {
100         if (IS_RELEASE_BUILD) {
101             // TODO: for user, we should show message to take car to the dealer. bug:32096297
102             return;
103         }
104         mNotificationManager.cancel(TAG, NOTIFICATION_ID);
105     }
106 }
107