1 /* 2 * Copyright (C) 2017 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.server.wifi; 18 19 import android.app.Notification; 20 import android.app.PendingIntent; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.res.Resources; 24 import android.net.wifi.ScanResult; 25 import android.util.Log; 26 27 import com.android.internal.R; 28 import com.android.internal.notification.SystemNotificationChannels; 29 30 /** 31 * Helper to create notifications for {@link OpenNetworkNotifier}. 32 */ 33 public class ConnectToNetworkNotificationBuilder { 34 35 /** Intent when user dismissed the "Connect to Network" notification. */ 36 public static final String ACTION_USER_DISMISSED_NOTIFICATION = 37 "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION"; 38 39 /** Intent when user tapped action button to connect to recommended network. */ 40 public static final String ACTION_CONNECT_TO_NETWORK = 41 "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK"; 42 43 /** Intent when user tapped action button to open Wi-Fi Settings. */ 44 public static final String ACTION_PICK_WIFI_NETWORK = 45 "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK"; 46 47 /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */ 48 public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE = 49 "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE"; 50 51 /** Extra data added to the Intent to specify the registering network notifier. */ 52 public static final String AVAILABLE_NETWORK_NOTIFIER_TAG = 53 "com.android.server.wifi.ConnectToNetworkNotification.AVAILABLE_NETWORK_NOTIFIER_TAG"; 54 55 private Context mContext; 56 private Resources mResources; 57 private FrameworkFacade mFrameworkFacade; 58 ConnectToNetworkNotificationBuilder( Context context, FrameworkFacade framework)59 public ConnectToNetworkNotificationBuilder( 60 Context context, 61 FrameworkFacade framework) { 62 mContext = context; 63 mResources = context.getResources(); 64 mFrameworkFacade = framework; 65 } 66 67 /** 68 * Creates the connect to network notification that alerts users of a recommended connectable 69 * network. 70 * 71 * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts 72 * the connection to the recommended network. 73 * 74 * @param notifierTag Unique tag of calling network notifier 75 * @param network The network to be recommended 76 */ createConnectToAvailableNetworkNotification(String notifierTag, ScanResult network)77 public Notification createConnectToAvailableNetworkNotification(String notifierTag, 78 ScanResult network) { 79 CharSequence title; 80 switch (notifierTag) { 81 case OpenNetworkNotifier.TAG: 82 title = mContext.getText(R.string.wifi_available_title); 83 break; 84 case CarrierNetworkNotifier.TAG: 85 title = mContext.getText(R.string.wifi_available_carrier_network_title); 86 break; 87 default: 88 Log.wtf("ConnectToNetworkNotificationBuilder", "Unknown network notifier." 89 + notifierTag); 90 return null; 91 } 92 Notification.Action connectAction = new Notification.Action.Builder(null /* icon */, 93 mResources.getText(R.string.wifi_available_action_connect), 94 getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK, notifierTag)).build(); 95 Notification.Action allNetworksAction = new Notification.Action.Builder(null /* icon */, 96 mResources.getText(R.string.wifi_available_action_all_networks), 97 getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)).build(); 98 return createNotificationBuilder(title, network.SSID, notifierTag) 99 .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)) 100 .addAction(connectAction) 101 .addAction(allNetworksAction) 102 .build(); 103 } 104 105 /** 106 * Creates the notification that indicates the controller is attempting to connect to the 107 * recommended network. 108 * 109 * @param notifierTag Unique tag of the calling network notifier 110 * @param network The network to be recommended 111 */ createNetworkConnectingNotification(String notifierTag, ScanResult network)112 public Notification createNetworkConnectingNotification(String notifierTag, 113 ScanResult network) { 114 return createNotificationBuilder( 115 mContext.getText(R.string.wifi_available_title_connecting), network.SSID, 116 notifierTag) 117 .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */) 118 .build(); 119 } 120 121 /** 122 * Creates the notification that indicates the controller successfully connected to the 123 * recommended network. 124 * 125 * @param notifierTag Unique tag of the calling network notifier 126 * @param network The network to be recommended 127 */ createNetworkConnectedNotification(String notifierTag, ScanResult network)128 public Notification createNetworkConnectedNotification(String notifierTag, ScanResult network) { 129 return createNotificationBuilder( 130 mContext.getText(R.string.wifi_available_title_connected), network.SSID, 131 notifierTag) 132 .build(); 133 } 134 135 /** 136 * Creates the notification that indicates the controller failed to connect to the recommended 137 * network. Tapping this notification opens the wifi picker. 138 * 139 * @param notifierTag Unique tag of the calling network notifier 140 */ createNetworkFailedNotification(String notifierTag)141 public Notification createNetworkFailedNotification(String notifierTag) { 142 return createNotificationBuilder( 143 mContext.getText(R.string.wifi_available_title_failed_to_connect), 144 mContext.getText(R.string.wifi_available_content_failed_to_connect), notifierTag) 145 .setContentIntent( 146 getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE, 147 notifierTag)) 148 .setAutoCancel(true) 149 .build(); 150 } 151 getNotifierRequestCode(String notifierTag)152 private int getNotifierRequestCode(String notifierTag) { 153 switch (notifierTag) { 154 case OpenNetworkNotifier.TAG: 155 return 1; 156 case CarrierNetworkNotifier.TAG: 157 return 2; 158 } 159 return 0; 160 } 161 createNotificationBuilder( CharSequence title, CharSequence content, String extraData)162 private Notification.Builder createNotificationBuilder( 163 CharSequence title, CharSequence content, String extraData) { 164 return mFrameworkFacade.makeNotificationBuilder(mContext, 165 SystemNotificationChannels.NETWORK_AVAILABLE) 166 .setSmallIcon(R.drawable.stat_notify_wifi_in_range) 167 .setTicker(title) 168 .setContentTitle(title) 169 .setContentText(content) 170 .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION, extraData)) 171 .setShowWhen(false) 172 .setLocalOnly(true) 173 .setColor(mResources.getColor(R.color.system_notification_accent_color, 174 mContext.getTheme())); 175 } 176 getPrivateBroadcast(String action, String extraData)177 private PendingIntent getPrivateBroadcast(String action, String extraData) { 178 Intent intent = new Intent(action).setPackage("android"); 179 int requestCode = 0; // Makes the different kinds of notifications distinguishable 180 if (extraData != null) { 181 intent.putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, extraData); 182 requestCode = getNotifierRequestCode(extraData); 183 } 184 return mFrameworkFacade.getBroadcast(mContext, requestCode, intent, 185 PendingIntent.FLAG_UPDATE_CURRENT); 186 } 187 } 188