content: /*
   * Copyright (C) 2017 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.NotificationManager;
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.provider.Settings;
  
  import com.android.internal.annotations.VisibleForTesting;
  import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
  import com.android.internal.notification.SystemNotificationChannels;
  import com.android.server.wifi.util.NativeUtil;
  
  /**
   * Responsible for notifying user for wrong password errors.
   */
  public class WrongPasswordNotifier {
      // Number of milliseconds to wait before automatically dismiss the notification.
      private static final long CANCEL_TIMEOUT_MILLISECONDS = 5 * 60 * 1000;
  
      // Unique ID associated with the notification.
      @VisibleForTesting
      public static final int NOTIFICATION_ID = SystemMessage.NOTE_WIFI_WRONG_PASSWORD;
  
      // Flag indicating if a wrong password error is detected for the current connection.
      private boolean mWrongPasswordDetected;
  
      private final Context mContext;
      private final NotificationManager mNotificationManager;
      private final FrameworkFacade mFrameworkFacade;
  
      public WrongPasswordNotifier(Context context, FrameworkFacade frameworkFacade) {
          mContext = context;
          mFrameworkFacade = frameworkFacade;
          mNotificationManager =
                  (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
      }
  
      /**
       * Invoked when a wrong password error for a Wi-Fi network is detected.
       *
       * @param ssid The SSID of the Wi-Fi network
       */
      public void onWrongPasswordError(String ssid) {
          showNotification(ssid);
          mWrongPasswordDetected = true;
      }
  
      /**
       * Invoked when attempting a new Wi-Fi network connection.
       */
      public void onNewConnectionAttempt() {
          if (mWrongPasswordDetected) {
              dismissNotification();
              mWrongPasswordDetected = false;
          }
      }
  
      /**
       * Display wrong password notification for a given Wi-Fi network (specified by its SSID).
       *
       * @param ssid SSID of the Wi-FI network
       */
      private void showNotification(String ssid) {
          Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
          intent.putExtra("wifi_start_connect_ssid", NativeUtil.removeEnclosingQuotes(ssid));
          Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
                  SystemNotificationChannels.NETWORK_ALERTS)
                  .setAutoCancel(true)
                  .setTimeoutAfter(CANCEL_TIMEOUT_MILLISECONDS)
                  // TODO(zqiu): consider creating a new icon.
                  .setSmallIcon(com.android.internal.R.drawable.stat_notify_wifi_in_range)
                  .setContentTitle(mContext.getString(
                          com.android.internal.R.string.wifi_available_title_failed_to_connect))
                  .setContentText(ssid)
                  .setContentIntent(mFrameworkFacade.getActivity(
                          mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT))
                  .setColor(mContext.getResources().getColor(
                          com.android.internal.R.color.system_notification_accent_color));
          mNotificationManager.notify(NOTIFICATION_ID, builder.build());
      }
  
      /**
       * Dismiss the notification that was generated by {@link #showNotification}. The notification
       * might have already been dismissed, either by user or timeout. We'll attempt to dismiss it
       * regardless if it is been dismissed or not, to reduce code complexity.
       */
      private void dismissNotification() {
          // Notification might have already been dismissed, either by user or timeout. It is
          // still okay to cancel it if already dismissed.
          mNotificationManager.cancel(null, NOTIFICATION_ID);
      }
  }
  