1 /* 2 * Copyright (C) 2019 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.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.res.Resources; 25 import android.net.wifi.WifiConfiguration; 26 import android.net.wifi.WifiContext; 27 import android.os.Handler; 28 import android.os.Process; 29 import android.text.TextUtils; 30 import android.util.Log; 31 32 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 33 import com.android.wifi.resources.R; 34 35 /** 36 * This class may be used to launch notifications when wifi connections fail. 37 */ 38 public class ConnectionFailureNotifier { 39 private static final String TAG = "ConnectionFailureNotifier"; 40 41 private final WifiContext mContext; 42 private final FrameworkFacade mFrameworkFacade; 43 private final WifiConfigManager mWifiConfigManager; 44 private final WifiConnectivityManager mWifiConnectivityManager; 45 private final WifiNotificationManager mNotificationManager; 46 private final WifiDialogManager mWifiDialogManager; 47 private final Handler mHandler; 48 private final ConnectionFailureNotificationBuilder mConnectionFailureNotificationBuilder; 49 ConnectionFailureNotifier( WifiContext context, FrameworkFacade framework, WifiConfigManager wifiConfigManager, WifiConnectivityManager wifiConnectivityManager, Handler handler, WifiNotificationManager notificationManager, ConnectionFailureNotificationBuilder connectionFailureNotificationBuilder, WifiDialogManager wifiDialogManager)50 public ConnectionFailureNotifier( 51 WifiContext context, 52 FrameworkFacade framework, 53 WifiConfigManager wifiConfigManager, 54 WifiConnectivityManager wifiConnectivityManager, 55 Handler handler, 56 WifiNotificationManager notificationManager, 57 ConnectionFailureNotificationBuilder connectionFailureNotificationBuilder, 58 WifiDialogManager wifiDialogManager) { 59 mContext = context; 60 mFrameworkFacade = framework; 61 mWifiConfigManager = wifiConfigManager; 62 mWifiConnectivityManager = wifiConnectivityManager; 63 mNotificationManager = notificationManager; 64 mWifiDialogManager = wifiDialogManager; 65 mHandler = handler; 66 mConnectionFailureNotificationBuilder = connectionFailureNotificationBuilder; 67 68 IntentFilter filter = new IntentFilter(); 69 filter.addAction(ConnectionFailureNotificationBuilder 70 .ACTION_SHOW_SET_RANDOMIZATION_DETAILS); 71 mContext.registerReceiver( 72 new BroadcastReceiver() { 73 @Override 74 public void onReceive(Context context, Intent intent) { 75 String action = intent.getAction(); 76 if (TextUtils.equals(action, ConnectionFailureNotificationBuilder 77 .ACTION_SHOW_SET_RANDOMIZATION_DETAILS)) { 78 int networkId = intent.getIntExtra( 79 ConnectionFailureNotificationBuilder 80 .RANDOMIZATION_SETTINGS_NETWORK_ID, 81 WifiConfiguration.INVALID_NETWORK_ID); 82 String ssidAndSecurityType = intent.getStringExtra( 83 ConnectionFailureNotificationBuilder 84 .RANDOMIZATION_SETTINGS_NETWORK_SSID); 85 showRandomizationSettingsDialog(networkId, ssidAndSecurityType); 86 } 87 } 88 }, filter); 89 } 90 91 /** 92 * Shows a notification which will bring up a dialog which offers the user an option to disable 93 * MAC randomization on |networkdId|. 94 * @param networkId 95 */ showFailedToConnectDueToNoRandomizedMacSupportNotification(int networkId)96 public void showFailedToConnectDueToNoRandomizedMacSupportNotification(int networkId) { 97 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); 98 if (config == null) { 99 return; 100 } 101 Notification notification = mConnectionFailureNotificationBuilder 102 .buildNoMacRandomizationSupportNotification(config); 103 mNotificationManager.notify(SystemMessage.NOTE_NETWORK_NO_MAC_RANDOMIZATION_SUPPORT, 104 notification); 105 } 106 107 /** 108 * Class to show a AlertDialog which notifies the user of a network not being privacy 109 * compliant and then suggests an action. 110 */ showRandomizationSettingsDialog(int networkId, String ssidAndSecurityType)111 private void showRandomizationSettingsDialog(int networkId, String ssidAndSecurityType) { 112 Resources res = mContext.getResources(); 113 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId); 114 // Make sure the networkId is still pointing to the correct WifiConfiguration since 115 // there might be a large time gap between when the notification shows and when 116 // it's tapped. 117 if (config == null || !TextUtils.equals(ssidAndSecurityType, 118 config.getSsidAndSecurityTypeString())) { 119 String message = res.getString( 120 R.string.wifi_disable_mac_randomization_dialog_network_not_found); 121 mFrameworkFacade.showToast(mContext, message); 122 return; 123 } 124 125 mWifiDialogManager.createSimpleDialog( 126 res.getString(R.string.wifi_disable_mac_randomization_dialog_title), 127 res.getString(R.string.wifi_disable_mac_randomization_dialog_message, config.SSID), 128 res.getString(R.string.wifi_disable_mac_randomization_dialog_confirm_text), 129 res.getString(android.R.string.cancel), 130 null /* neutralButtonText */, 131 new WifiDialogManager.SimpleDialogCallback() { 132 @Override 133 public void onPositiveButtonClicked() { 134 config.macRandomizationSetting = 135 WifiConfiguration.RANDOMIZATION_NONE; 136 mWifiConfigManager.addOrUpdateNetwork(config, Process.SYSTEM_UID); 137 WifiConfiguration updatedConfig = 138 mWifiConfigManager.getConfiguredNetwork(config.networkId); 139 if (updatedConfig.macRandomizationSetting 140 == WifiConfiguration.RANDOMIZATION_NONE) { 141 String message = mContext.getResources().getString( 142 R.string.wifi_disable_mac_randomization_dialog_success); 143 mFrameworkFacade.showToast(mContext, message); 144 mWifiConfigManager.enableNetwork(updatedConfig.networkId, true, 145 Process.SYSTEM_UID, null); 146 mWifiConnectivityManager.forceConnectivityScan( 147 ClientModeImpl.WIFI_WORK_SOURCE); 148 } else { 149 // Shouldn't ever fail, but here for completeness 150 String message = mContext.getResources().getString( 151 R.string.wifi_disable_mac_randomization_dialog_failure); 152 mFrameworkFacade.showToast(mContext, message); 153 Log.e(TAG, "Failed to modify mac randomization setting"); 154 } 155 } 156 157 @Override 158 public void onNegativeButtonClicked() { 159 // Do nothing. 160 } 161 162 @Override 163 public void onNeutralButtonClicked() { 164 // Not used. 165 } 166 167 @Override 168 public void onCancelled() { 169 // Do nothing. 170 } 171 }, 172 new WifiThreadRunner(mHandler)).launchDialog(); 173 } 174 } 175