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