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.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.content.res.Resources;
  import android.net.wifi.ScanResult;
  import android.util.Log;
  
  import com.android.internal.R;
  import com.android.internal.notification.SystemNotificationChannels;
  
  /**
   * Helper to create notifications for {@link OpenNetworkNotifier}.
   */
  public class ConnectToNetworkNotificationBuilder {
  
      /** Intent when user dismissed the "Connect to Network" notification. */
      public static final String ACTION_USER_DISMISSED_NOTIFICATION =
              "com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION";
  
      /** Intent when user tapped action button to connect to recommended network. */
      public static final String ACTION_CONNECT_TO_NETWORK =
              "com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK";
  
      /** Intent when user tapped action button to open Wi-Fi Settings. */
      public static final String ACTION_PICK_WIFI_NETWORK =
              "com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK";
  
      /** Intent when user tapped "Failed to connect" notification to open Wi-Fi Settings. */
      public static final String ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE =
              "com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE";
  
      /** Extra data added to the Intent to specify the registering network notifier. */
      public static final String AVAILABLE_NETWORK_NOTIFIER_TAG =
              "com.android.server.wifi.ConnectToNetworkNotification.AVAILABLE_NETWORK_NOTIFIER_TAG";
  
      private Context mContext;
      private Resources mResources;
      private FrameworkFacade mFrameworkFacade;
  
      public ConnectToNetworkNotificationBuilder(
              Context context,
              FrameworkFacade framework) {
          mContext = context;
          mResources = context.getResources();
          mFrameworkFacade = framework;
      }
  
      /**
       * Creates the connect to network notification that alerts users of a recommended connectable
       * network.
       *
       * There are two actions - "Options" link to the Wi-Fi picker activity, and "Connect" prompts
       * the connection to the recommended network.
       *
       * @param notifierTag Unique tag of calling network notifier
       * @param network The network to be recommended
       */
      public Notification createConnectToAvailableNetworkNotification(String notifierTag,
              ScanResult network) {
          CharSequence title;
          switch (notifierTag) {
              case OpenNetworkNotifier.TAG:
                  title = mContext.getText(R.string.wifi_available_title);
                  break;
              case CarrierNetworkNotifier.TAG:
                  title = mContext.getText(R.string.wifi_available_carrier_network_title);
                  break;
              default:
                  Log.wtf("ConnectToNetworkNotificationBuilder", "Unknown network notifier."
                          + notifierTag);
                  return null;
          }
          Notification.Action connectAction = new Notification.Action.Builder(null /* icon */,
                  mResources.getText(R.string.wifi_available_action_connect),
                  getPrivateBroadcast(ACTION_CONNECT_TO_NETWORK, notifierTag)).build();
          Notification.Action allNetworksAction = new Notification.Action.Builder(null /* icon */,
                  mResources.getText(R.string.wifi_available_action_all_networks),
                  getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag)).build();
          return createNotificationBuilder(title, network.SSID, notifierTag)
                  .setContentIntent(getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK, notifierTag))
                  .addAction(connectAction)
                  .addAction(allNetworksAction)
                  .build();
      }
  
      /**
       * Creates the notification that indicates the controller is attempting to connect to the
       * recommended network.
       *
       * @param notifierTag Unique tag of the calling network notifier
       * @param network The network to be recommended
       */
      public Notification createNetworkConnectingNotification(String notifierTag,
              ScanResult network) {
          return createNotificationBuilder(
                  mContext.getText(R.string.wifi_available_title_connecting), network.SSID,
                          notifierTag)
                  .setProgress(0 /* max */, 0 /* progress */, true /* indeterminate */)
                  .build();
      }
  
      /**
       * Creates the notification that indicates the controller successfully connected to the
       * recommended network.
       *
       * @param notifierTag Unique tag of the calling network notifier
       * @param network The network to be recommended
       */
      public Notification createNetworkConnectedNotification(String notifierTag, ScanResult network) {
          return createNotificationBuilder(
                  mContext.getText(R.string.wifi_available_title_connected), network.SSID,
                          notifierTag)
                  .build();
      }
  
      /**
       * Creates the notification that indicates the controller failed to connect to the recommended
       * network. Tapping this notification opens the wifi picker.
       *
       * @param notifierTag Unique tag of the calling network notifier
       */
      public Notification createNetworkFailedNotification(String notifierTag) {
          return createNotificationBuilder(
                  mContext.getText(R.string.wifi_available_title_failed_to_connect),
                  mContext.getText(R.string.wifi_available_content_failed_to_connect), notifierTag)
                  .setContentIntent(
                          getPrivateBroadcast(ACTION_PICK_WIFI_NETWORK_AFTER_CONNECT_FAILURE,
                                  notifierTag))
                  .setAutoCancel(true)
                  .build();
      }
  
      private int getNotifierRequestCode(String notifierTag) {
          switch (notifierTag) {
              case OpenNetworkNotifier.TAG:
                  return 1;
              case CarrierNetworkNotifier.TAG:
                  return 2;
          }
          return 0;
      }
  
      private Notification.Builder createNotificationBuilder(
              CharSequence title, CharSequence content, String extraData) {
          return mFrameworkFacade.makeNotificationBuilder(mContext,
                  SystemNotificationChannels.NETWORK_AVAILABLE)
                  .setSmallIcon(R.drawable.stat_notify_wifi_in_range)
                  .setTicker(title)
                  .setContentTitle(title)
                  .setContentText(content)
                  .setDeleteIntent(getPrivateBroadcast(ACTION_USER_DISMISSED_NOTIFICATION, extraData))
                  .setShowWhen(false)
                  .setLocalOnly(true)
                  .setColor(mResources.getColor(R.color.system_notification_accent_color,
                          mContext.getTheme()));
      }
  
      private PendingIntent getPrivateBroadcast(String action, String extraData) {
          Intent intent = new Intent(action).setPackage("android");
          int requestCode = 0;  // Makes the different kinds of notifications distinguishable
          if (extraData != null) {
              intent.putExtra(AVAILABLE_NETWORK_NOTIFIER_TAG, extraData);
              requestCode = getNotifierRequestCode(extraData);
          }
          return mFrameworkFacade.getBroadcast(mContext, requestCode, intent,
                  PendingIntent.FLAG_UPDATE_CURRENT);
      }
  }
  