| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wifi; |
| |
| import android.app.Notification; |
| import android.app.PendingIntent; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.content.res.Resources; |
| import android.graphics.drawable.Icon; |
| import android.net.wifi.WifiConfiguration; |
| import android.provider.Settings; |
| import android.service.notification.StatusBarNotification; |
| import android.telephony.SubscriptionManager; |
| import android.text.TextUtils; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; |
| |
| /** |
| * This class may be used to launch notifications when EAP failure occurs. |
| */ |
| public class EapFailureNotifier { |
| private static final String TAG = "EapFailureNotifier"; |
| private static final String ERROR_MESSAGE_OVERLAY_PREFIX = "wifi_eap_error_message_code_"; |
| |
| private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000; |
| private final WifiContext mContext; |
| private final WifiNotificationManager mNotificationManager; |
| private final FrameworkFacade mFrameworkFacade; |
| private final WifiCarrierInfoManager mWifiCarrierInfoManager; |
| |
| // Unique ID associated with the notification. |
| public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_EAP_FAILURE; |
| private String mCurrentShownSsid; |
| |
| public EapFailureNotifier(WifiContext context, FrameworkFacade frameworkFacade, |
| WifiCarrierInfoManager wifiCarrierInfoManager, |
| WifiNotificationManager wifiNotificationManager) { |
| mContext = context; |
| mFrameworkFacade = frameworkFacade; |
| mWifiCarrierInfoManager = wifiCarrierInfoManager; |
| mNotificationManager = wifiNotificationManager; |
| } |
| |
| /** |
| * Invoked when EAP failure occurs. |
| * |
| * @param errorCode error code which delivers from supplicant |
| * @param showNotification whether to display the notification |
| * @return true if the receiving error code is found in wifi resource |
| */ |
| public boolean onEapFailure(int errorCode, WifiConfiguration config, boolean showNotification) { |
| Resources res = getResourcesForSubId(mContext, |
| mWifiCarrierInfoManager.getBestMatchSubscriptionId(config)); |
| if (res == null) return false; |
| int resourceId = res.getIdentifier(ERROR_MESSAGE_OVERLAY_PREFIX + errorCode, |
| "string", mContext.getWifiOverlayApkPkgName()); |
| |
| if (resourceId == 0) return false; |
| String errorMessage = res.getString(resourceId, config.SSID); |
| if (TextUtils.isEmpty(errorMessage)) return false; |
| StatusBarNotification[] activeNotifications = mNotificationManager.getActiveNotifications(); |
| for (StatusBarNotification activeNotification : activeNotifications) { |
| if ((activeNotification.getId() == NOTIFICATION_ID) |
| && TextUtils.equals(config.SSID, mCurrentShownSsid)) { |
| return true; |
| } |
| } |
| |
| if (showNotification) { |
| showNotification(errorMessage, config.SSID); |
| } |
| return true; |
| } |
| |
| /** |
| * Display eap error notification which defined by carrier. |
| * |
| * @param ssid Error Message which defined by carrier |
| */ |
| private void showNotification(String errorMessage, String ssid) { |
| String settingsPackage = mFrameworkFacade.getSettingsPackageName(mContext); |
| if (settingsPackage == null) return; |
| Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS) |
| .setPackage(settingsPackage); |
| Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext, |
| WifiService.NOTIFICATION_NETWORK_ALERTS) |
| .setAutoCancel(true) |
| .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS) |
| .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(), |
| com.android.wifi.resources.R.drawable.stat_notify_wifi_in_range)) |
| .setContentTitle(mContext.getString( |
| com.android.wifi.resources.R.string.wifi_available_title_failed_to_connect)) |
| .setContentText(errorMessage) |
| .setStyle(new Notification.BigTextStyle().bigText(errorMessage)) |
| .setContentIntent(mFrameworkFacade.getActivity( |
| mContext, 0, intent, |
| PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) |
| .setColor(mContext.getResources().getColor( |
| android.R.color.system_notification_accent_color)); |
| mNotificationManager.notify(NOTIFICATION_ID, |
| builder.build()); |
| mCurrentShownSsid = ssid; |
| } |
| |
| /** |
| * Returns the resources from the given context for the MCC/MNC |
| * associated with the subscription. |
| */ |
| private Resources getResourcesForSubId(WifiContext context, int subId) { |
| Context resourceContext = null; |
| try { |
| resourceContext = context.createPackageContext( |
| context.getWifiOverlayApkPkgName(), 0); |
| } catch (PackageManager.NameNotFoundException ex) { |
| return null; |
| } |
| |
| return SubscriptionManager.getResourcesForSubId(resourceContext, subId); |
| } |
| |
| /** |
| * Allow tests to modify mCurrentShownSsid |
| */ |
| @VisibleForTesting |
| void setCurrentShownSsid(String currentShownSsid) { |
| mCurrentShownSsid = currentShownSsid; |
| } |
| } |