1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.util; 16 17 import android.app.NotificationChannel; 18 import android.app.NotificationManager; 19 import android.content.Context; 20 import android.content.pm.PackageManager; 21 import android.media.AudioAttributes; 22 import android.net.Uri; 23 import android.provider.Settings; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.systemui.CoreStartable; 27 import com.android.systemui.res.R; 28 import com.android.wm.shell.pip.tv.TvPipNotificationController; 29 30 import java.util.Arrays; 31 32 import javax.inject.Inject; 33 34 // NOT Singleton. Started per-user. 35 /** */ 36 public class NotificationChannels implements CoreStartable { 37 public static String ALERTS = "ALR"; 38 public static String SCREENSHOTS_HEADSUP = "SCN_HEADSUP"; 39 // Deprecated. Please use or create a more specific channel that users will better understand 40 @Deprecated 41 static String GENERAL = "GEN"; 42 public static String STORAGE = "DSK"; 43 public static String BATTERY = "BAT"; 44 public static String TVPIP = TvPipNotificationController.NOTIFICATION_CHANNEL; // "TVPIP" 45 public static String HINTS = "HNT"; 46 public static String INSTANT = "INS"; 47 public static String SETUP = "STP"; 48 49 private final Context mContext; 50 51 @Inject NotificationChannels(Context context)52 public NotificationChannels(Context context) { 53 mContext = context; 54 } 55 createAll(Context context)56 public static void createAll(Context context) { 57 final NotificationManager nm = context.getSystemService(NotificationManager.class); 58 final NotificationChannel batteryChannel = new NotificationChannel(BATTERY, 59 context.getString(R.string.notification_channel_battery), 60 NotificationManager.IMPORTANCE_MAX); 61 final String soundPath = Settings.Global.getString(context.getContentResolver(), 62 Settings.Global.LOW_BATTERY_SOUND); 63 batteryChannel.setSound(Uri.parse("file://" + soundPath), new AudioAttributes.Builder() 64 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 65 .setUsage(AudioAttributes.USAGE_NOTIFICATION_EVENT) 66 .build()); 67 batteryChannel.setBlockable(true); 68 69 final NotificationChannel alerts = new NotificationChannel( 70 ALERTS, 71 context.getString(R.string.notification_channel_alerts), 72 NotificationManager.IMPORTANCE_HIGH); 73 74 final NotificationChannel instant = new NotificationChannel( 75 INSTANT, 76 context.getString(R.string.notification_channel_instant), 77 NotificationManager.IMPORTANCE_MIN); 78 79 final NotificationChannel setup = new NotificationChannel( 80 SETUP, 81 context.getString(R.string.notification_channel_setup), 82 NotificationManager.IMPORTANCE_DEFAULT); 83 setup.setSound(null, null); 84 85 final NotificationChannel storage = new NotificationChannel( 86 STORAGE, 87 context.getString(R.string.notification_channel_storage), 88 isTv(context) 89 ? NotificationManager.IMPORTANCE_DEFAULT 90 : NotificationManager.IMPORTANCE_LOW); 91 92 final NotificationChannel hint = new NotificationChannel( 93 HINTS, 94 context.getString(R.string.notification_channel_hints), 95 NotificationManager.IMPORTANCE_DEFAULT); 96 // No need to bypass DND. 97 98 nm.createNotificationChannels(Arrays.asList( 99 alerts, 100 instant, 101 setup, 102 storage, 103 createScreenshotChannel( 104 context.getString(R.string.notification_channel_screenshot)), 105 batteryChannel, 106 hint 107 )); 108 109 if (isTv(context)) { 110 // TV specific notification channel for TV PIP controls. 111 // Importance should be {@link NotificationManager#IMPORTANCE_MAX} to have the highest 112 // priority, so it can be shown in all times. 113 nm.createNotificationChannel(new NotificationChannel( 114 TVPIP, 115 context.getString(com.android.wm.shell.R.string.notification_channel_tv_pip), 116 NotificationManager.IMPORTANCE_MAX)); 117 } 118 } 119 120 /** 121 * Set up screenshot channel, respecting any previously committed user settings on legacy 122 * channel. 123 * @return 124 */ createScreenshotChannel( String name)125 @VisibleForTesting static NotificationChannel createScreenshotChannel( 126 String name) { 127 NotificationChannel screenshotChannel = new NotificationChannel(SCREENSHOTS_HEADSUP, 128 name, NotificationManager.IMPORTANCE_HIGH); // pop on screen 129 130 screenshotChannel.setSound(null, // silent 131 new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()); 132 screenshotChannel.setBlockable(true); 133 134 return screenshotChannel; 135 } 136 137 @Override start()138 public void start() { 139 createAll(mContext); 140 cleanUp(); 141 } 142 cleanUp()143 private void cleanUp() { 144 mContext.getSystemService(NotificationManager.class).deleteNotificationChannel(GENERAL); 145 } 146 isTv(Context context)147 private static boolean isTv(Context context) { 148 PackageManager packageManager = context.getPackageManager(); 149 return packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK); 150 } 151 } 152