1 /* 2 * Copyright (C) 2018 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.notification.template; 17 18 import android.annotation.ColorInt; 19 import android.app.Notification; 20 import android.car.userlib.CarUserManagerHelper; 21 import android.content.Context; 22 import android.content.pm.ApplicationInfo; 23 import android.content.pm.PackageManager; 24 import android.content.res.TypedArray; 25 import android.graphics.drawable.Drawable; 26 import android.os.Bundle; 27 import android.service.notification.StatusBarNotification; 28 import android.text.TextUtils; 29 import android.util.AttributeSet; 30 import android.util.Log; 31 import android.view.View; 32 import android.widget.DateTimeView; 33 import android.widget.ImageView; 34 import android.widget.LinearLayout; 35 import android.widget.TextView; 36 37 import androidx.annotation.Nullable; 38 39 import com.android.car.notification.R; 40 41 /** 42 * Notification header view that contains the issuer app icon and name, and extra information. 43 */ 44 public class CarNotificationHeaderView extends LinearLayout { 45 46 private static final String TAG = "car_notification_header"; 47 48 private final PackageManager mPackageManager; 49 private final CarUserManagerHelper mCarUserManagerHelper; 50 private final int mDefaultTextColor; 51 private final String mSeparatorText; 52 53 private boolean mIsHeadsUp; 54 private ImageView mIconView; 55 private TextView mHeaderTextView; 56 private DateTimeView mTimeView; 57 CarNotificationHeaderView(Context context)58 public CarNotificationHeaderView(Context context) { 59 super(context); 60 } 61 CarNotificationHeaderView(Context context, AttributeSet attrs)62 public CarNotificationHeaderView(Context context, AttributeSet attrs) { 63 super(context, attrs); 64 init(attrs); 65 } 66 CarNotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr)67 public CarNotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr) { 68 super(context, attrs, defStyleAttr); 69 init(attrs); 70 } 71 CarNotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)72 public CarNotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr, 73 int defStyleRes) { 74 super(context, attrs, defStyleAttr, defStyleRes); 75 init(attrs); 76 } 77 78 { 79 mPackageManager = getContext().getPackageManager(); 80 mCarUserManagerHelper = new CarUserManagerHelper(getContext()); 81 mDefaultTextColor = getContext().getColor(R.color.primary_text_color); 82 mSeparatorText = getContext().getString(R.string.header_text_separator); getContext()83 inflate(getContext(), R.layout.car_notification_header_view, this); 84 } 85 init(AttributeSet attrs)86 private void init(AttributeSet attrs) { 87 TypedArray attributes = 88 getContext().obtainStyledAttributes(attrs, R.styleable.CarNotificationHeaderView); 89 mIsHeadsUp = 90 attributes.getBoolean(R.styleable.CarNotificationHeaderView_isHeadsUp, 91 /* defValue= */ false); 92 attributes.recycle(); 93 } 94 95 @Override onFinishInflate()96 protected void onFinishInflate() { 97 super.onFinishInflate(); 98 mIconView = findViewById(R.id.app_icon); 99 mHeaderTextView = findViewById(R.id.header_text); 100 mTimeView = findViewById(R.id.time); 101 mTimeView.setShowRelativeTime(true); 102 } 103 104 /** 105 * Binds the notification header that contains the issuer app icon and name. 106 * 107 * @param statusBarNotification the notification to be bound. 108 * @param isInGroup whether this notification is part of a grouped notification. 109 */ bind(StatusBarNotification statusBarNotification, boolean isInGroup)110 public void bind(StatusBarNotification statusBarNotification, boolean isInGroup) { 111 if (isInGroup) { 112 // if the notification is part of a group, individual headers are not shown 113 // instead, there is a header for the entire group in the group notification template 114 return; 115 } 116 117 Notification notification = statusBarNotification.getNotification(); 118 119 Context packageContext = statusBarNotification.getPackageContext(getContext()); 120 121 // app icon 122 mIconView.setVisibility(View.VISIBLE); 123 Drawable drawable = notification.getSmallIcon().loadDrawable(packageContext); 124 mIconView.setImageDrawable(drawable); 125 126 StringBuilder stringBuilder = new StringBuilder(); 127 128 // app name 129 mHeaderTextView.setVisibility(View.VISIBLE); 130 131 if (mIsHeadsUp) { 132 mHeaderTextView.setText(loadHeaderAppName(statusBarNotification.getPackageName())); 133 mTimeView.setVisibility(View.GONE); 134 return; 135 } 136 137 stringBuilder.append(loadHeaderAppName(statusBarNotification.getPackageName())); 138 Bundle extras = notification.extras; 139 140 // optional field: sub text 141 if (!TextUtils.isEmpty(extras.getCharSequence(Notification.EXTRA_SUB_TEXT))) { 142 stringBuilder.append(mSeparatorText); 143 stringBuilder.append(extras.getCharSequence(Notification.EXTRA_SUB_TEXT)); 144 } 145 146 // optional field: content info 147 if (!TextUtils.isEmpty(extras.getCharSequence(Notification.EXTRA_INFO_TEXT))) { 148 stringBuilder.append(mSeparatorText); 149 stringBuilder.append(extras.getCharSequence(Notification.EXTRA_INFO_TEXT)); 150 } 151 152 // optional field: time 153 if (notification.showsTime()) { 154 stringBuilder.append(mSeparatorText); 155 mTimeView.setVisibility(View.VISIBLE); 156 mTimeView.setTime(notification.when); 157 } 158 159 mHeaderTextView.setText(stringBuilder); 160 } 161 162 /** 163 * Sets the color for the small icon. 164 */ setSmallIconColor(@olorInt int color)165 public void setSmallIconColor(@ColorInt int color) { 166 mIconView.setColorFilter(color); 167 } 168 169 /** 170 * Sets the header text color. 171 */ setHeaderTextColor(@olorInt int color)172 public void setHeaderTextColor(@ColorInt int color) { 173 mHeaderTextView.setTextColor(color); 174 } 175 176 /** 177 * Sets the text color for the time field. 178 */ setTimeTextColor(@olorInt int color)179 public void setTimeTextColor(@ColorInt int color) { 180 mTimeView.setTextColor(color); 181 } 182 183 /** 184 * Resets the notification header empty. 185 */ reset()186 public void reset() { 187 mIconView.setVisibility(View.GONE); 188 mIconView.setImageDrawable(null); 189 setSmallIconColor(mDefaultTextColor); 190 191 mHeaderTextView.setVisibility(View.GONE); 192 mHeaderTextView.setText(null); 193 setHeaderTextColor(mDefaultTextColor); 194 195 mTimeView.setVisibility(View.GONE); 196 mTimeView.setTime(0); 197 setTimeTextColor(mDefaultTextColor); 198 } 199 200 /** 201 * Fetches the application label given the package name. 202 * 203 * @param packageName The package name of the application. 204 * @return application label. Returns {@code null} when application name is not found. 205 */ 206 @Nullable loadHeaderAppName(String packageName)207 private String loadHeaderAppName(String packageName) { 208 ApplicationInfo info; 209 try { 210 info = mPackageManager.getApplicationInfoAsUser(packageName.trim(), /* flags= */ 0, 211 mCarUserManagerHelper.getCurrentForegroundUserId()); 212 } catch (PackageManager.NameNotFoundException e) { 213 Log.e(TAG, "Error fetching app name in car notification header" + e); 214 return null; 215 } 216 return String.valueOf(mPackageManager.getApplicationLabel(info)); 217 } 218 } 219