120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen/* 220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Copyright (C) 2017 The Android Open Source Project 320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Licensed under the Apache License, Version 2.0 (the "License"); 520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * you may not use this file except in compliance with the License. 620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * You may obtain a copy of the License at 720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * http://www.apache.org/licenses/LICENSE-2.0 920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 1020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Unless required by applicable law or agreed to in writing, software 1120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * distributed under the License is distributed on an "AS IS" BASIS, 1220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * See the License for the specific language governing permissions and 1420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * limitations under the License. 1520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 1620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 1720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenpackage com.android.server.wifi; 1820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 1920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.app.Notification; 2020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.app.PendingIntent; 2120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.Context; 2220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.Intent; 2320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.content.res.Resources; 2420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport android.net.wifi.ScanResult; 25664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadehimport android.util.Log; 2620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 2720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport com.android.internal.R; 2820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenimport com.android.internal.notification.SystemNotificationChannels; 2920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 3020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen/** 3120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Helper to create notifications for {@link OpenNetworkNotifier}. 3220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 3320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chenpublic class ConnectToNetworkNotificationBuilder { 3420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 3520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** Intent when user dismissed the "Connect to Network" notification. */ 3620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen public static final String ACTION_USER_DISMISSED_NOTIFICATION = 3720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION"; 3820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 3920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** Intent when user tapped action button to connect to recommended network. */ 4020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen public static final String ACTION_CONNECT_TO_NETWORK = 4120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK"; 4220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 4320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** Intent when user tapped action button to open Wi-Fi Settings. */ 4420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen public static final String ACTION_PICK_WIFI_NETWORK = 4520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK"; 4620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 4720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */ 4820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE = 4920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE"; 5020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 51664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh /** Extra data added to the Intent to specify the registering network notifier. */ 52664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh public static final String AVAILABLE_NETWORK_NOTIFIER_TAG = 53664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh "com.android.server.wifi.ConnectToNetworkNotification.AVAILABLE_NETWORK_NOTIFIER_TAG"; 54664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh 5520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen private Context mContext; 5620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen private Resources mResources; 5720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen private FrameworkFacade mFrameworkFacade; 5820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 5920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen public ConnectToNetworkNotificationBuilder( 6020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen Context context, 6120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen FrameworkFacade framework) { 6220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen mContext = context; 6320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen mResources = context.getResources(); 6420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen mFrameworkFacade = framework; 6520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 6620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 6720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** 6820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Creates the connect to network notification that alerts users of a recommended connectable 6920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * network. 7020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 71b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts 72b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen * the connection to the recommended network. 73b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen * 74664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh * @param notifierTag Unique tag of calling network notifier 75b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen * @param network The network to be recommended 7620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 77664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh public Notification createConnectToAvailableNetworkNotification(String notifierTag, 78664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh ScanResult network) { 79664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh CharSequence title; 80664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh switch (notifierTag) { 81664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh case OpenNetworkNotifier.TAG: 82664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh title = mContext.getText(R.string.wifi_available_title); 83664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh break; 84664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh case CarrierNetworkNotifier.TAG: 85664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh title = mContext.getText(R.string.wifi_available_carrier_network_title); 86664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh break; 87664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh default: 88664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh Log.wtf("ConnectToNetworkNotificationBuilder", "Unknown network notifier." 89664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh + notifierTag); 90664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh return null; 91664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh } 92664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh Notification.Action connectAction = new Notification.Action.Builder(null /* icon */, 93b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen mResources.getText(R.string.wifi_available_action_connect), 9478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK, notifierTag)).build(); 95664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh Notification.Action allNetworksAction = new Notification.Action.Builder(null /* icon */, 96b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen mResources.getText(R.string.wifi_available_action_all_networks), 9778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)).build(); 9878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh return createNotificationBuilder(title, network.SSID, notifierTag) 9992c1165b80f0b74421c8d8871fcce1d7d123ac57Mehdi Alizadeh .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)) 10078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh .addAction(connectAction) 10178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh .addAction(allNetworksAction) 10278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh .build(); 10320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 10420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 10520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** 10620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Creates the notification that indicates the controller is attempting to connect to the 10720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * recommended network. 10820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 10978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh * @param notifierTag Unique tag of the calling network notifier 11020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * @param network The network to be recommended 11120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 11278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh public Notification createNetworkConnectingNotification(String notifierTag, 11378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh ScanResult network) { 11420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen return createNotificationBuilder( 11578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh mContext.getText(R.string.wifi_available_title_connecting), network.SSID, 11678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh notifierTag) 11720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */) 11820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .build(); 11920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 12020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 12120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** 12220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Creates the notification that indicates the controller successfully connected to the 12320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * recommended network. 12420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * 12578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh * @param notifierTag Unique tag of the calling network notifier 12620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * @param network The network to be recommended 12720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 12878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh public Notification createNetworkConnectedNotification(String notifierTag, ScanResult network) { 12920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen return createNotificationBuilder( 13078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh mContext.getText(R.string.wifi_available_title_connected), network.SSID, 13178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh notifierTag) 13220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .build(); 13320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 13420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 13520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen /** 13620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * Creates the notification that indicates the controller failed to connect to the recommended 13720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen * network. Tapping this notification opens the wifi picker. 13878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh * 13978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh * @param notifierTag Unique tag of the calling network notifier 14020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen */ 14178e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh public Notification createNetworkFailedNotification(String notifierTag) { 14220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen return createNotificationBuilder( 14320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen mContext.getText(R.string.wifi_available_title_failed_to_connect), 14478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh mContext.getText(R.string.wifi_available_content_failed_to_connect), notifierTag) 14520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setContentIntent( 14678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE, 14778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh notifierTag)) 148b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen .setAutoCancel(true) 14920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .build(); 15020361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 15120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 15278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh private int getNotifierRequestCode(String notifierTag) { 15378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh switch (notifierTag) { 15478e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh case OpenNetworkNotifier.TAG: 15578e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh return 1; 15678e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh case CarrierNetworkNotifier.TAG: 15778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh return 2; 15878e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh } 15978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh return 0; 160664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh } 161664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh 162664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh private Notification.Builder createNotificationBuilder( 16378e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh CharSequence title, CharSequence content, String extraData) { 16420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen return mFrameworkFacade.makeNotificationBuilder(mContext, 16520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen SystemNotificationChannels.NETWORK_AVAILABLE) 16620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setSmallIcon(R.drawable.stat_notify_wifi_in_range) 16720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setTicker(title) 16820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setContentTitle(title) 16920361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setContentText(content) 17078e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION, extraData)) 17120361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setShowWhen(false) 17220361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setLocalOnly(true) 17320361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen .setColor(mResources.getColor(R.color.system_notification_accent_color, 17420361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen mContext.getTheme())); 17520361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 17620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen 17778e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh private PendingIntent getPrivateBroadcast(String action, String extraData) { 17820361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen Intent intent = new Intent(action).setPackage("android"); 17978e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh int requestCode = 0; // Makes the different kinds of notifications distinguishable 180664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh if (extraData != null) { 181664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh intent.putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, extraData); 18278e05c6b675715b1c54e434db75550823f0df004Mehdi Alizadeh requestCode = getNotifierRequestCode(extraData); 183664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh } 184664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh return mFrameworkFacade.getBroadcast(mContext, requestCode, intent, 185664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh PendingIntent.FLAG_UPDATE_CURRENT); 18620361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen } 18720361dcf2d45262685c8dec334c11f0b2c987702Stephen Chen} 188