Home | History | Annotate | Download | only in app
      1 package com.android.hotspot2.app;
      2 
      3 import android.app.IntentService;
      4 import android.content.BroadcastReceiver;
      5 import android.content.Context;
      6 import android.content.Intent;
      7 import android.content.IntentFilter;
      8 import android.net.wifi.WifiConfiguration;
      9 import android.net.wifi.WifiInfo;
     10 import android.net.wifi.WifiManager;
     11 import android.os.Bundle;
     12 import android.os.IBinder;
     13 import android.util.Log;
     14 
     15 import com.android.anqp.OSUProvider;
     16 import com.android.hotspot2.PasspointMatch;
     17 import com.android.hotspot2.osu.OSUManager;
     18 
     19 import java.io.IOException;
     20 import java.util.List;
     21 
     22 /**
     23  * This is the Hotspot 2.0 release 2 OSU background service that is continuously running and caches
     24  * OSU information.
     25  *
     26  * The OSU App is made up of two services; FlowService and OSUService.
     27  *
     28  * OSUService is a long running light weight service, kept alive throughout the lifetime of the
     29  * operating system by being bound from the framework (in WifiManager in stage
     30  * PHASE_THIRD_PARTY_APPS_CAN_START), and is responsible for continuously caching OSU information
     31  * and notifying the UI when OSUs are available.
     32  *
     33  * FlowService is only started on demand from OSUService and is responsible for handling actual
     34  * provisioning and remediation flows, and requires a fairly significant memory footprint.
     35  *
     36  * FlowService is defined to run in its own process through the definition
     37  *      <service android:name=".flow.FlowService" android:process=":osuflow">
     38  * in the AndroidManifest.
     39  * This is done as a means to keep total app memory footprint low (pss < 10M) and only start the
     40  * FlowService on demand and make it available for "garbage collection" by the OS when not in use.
     41  */
     42 public class OSUService extends IntentService {
     43     public static final String REMEDIATION_DONE_ACTION = "com.android.hotspot2.REMEDIATION_DONE";
     44     public static final String REMEDIATION_FQDN_EXTRA = "com.android.hotspot2.REMEDIATION_FQDN";
     45     public static final String REMEDIATION_POLICY_EXTRA = "com.android.hotspot2.REMEDIATION_POLICY";
     46 
     47     private static final String[] INTENTS = {
     48             WifiManager.SCAN_RESULTS_AVAILABLE_ACTION,
     49             // TODO(b/32883320): use updated intent definitions.
     50             //WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION,
     51             //WifiManager.PASSPOINT_ICON_RECEIVED_ACTION,
     52             WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION,
     53             WifiManager.WIFI_STATE_CHANGED_ACTION,
     54             WifiManager.NETWORK_STATE_CHANGED_ACTION,
     55             REMEDIATION_DONE_ACTION
     56     };
     57 
     58     private OSUManager mOsuManager;
     59     private final LocalServiceBinder mLocalServiceBinder;
     60 
     61     public OSUService() {
     62         super("OSUService");
     63         mLocalServiceBinder = new LocalServiceBinder(this);
     64     }
     65 
     66     /*
     67     public final class OSUAccessorImpl extends IOSUAccessor.Stub {
     68         public List<OSUData> getOsuData() {
     69             List<OSUInfo> infos = getOsuInfos();
     70             List<OSUData> data = new ArrayList<>(infos.size());
     71             for (OSUInfo osuInfo : infos) {
     72                 data.add(new OSUData(osuInfo));
     73             }
     74             return data;
     75         }
     76 
     77         public void selectOsu(int id) {
     78             OSUService.this.selectOsu(id);
     79         }
     80     }
     81     */
     82 
     83     @Override
     84     public int onStartCommand(Intent intent, int flags, int startId) {
     85         onHandleIntent(intent);
     86         return START_STICKY;
     87     }
     88 
     89     @Override
     90     public IBinder onBind(Intent intent) {
     91         BroadcastReceiver receiver = new BroadcastReceiver() {
     92             @Override
     93             public void onReceive(Context context, Intent intent) {
     94                 handleIntent(intent.getAction(), intent);
     95             }
     96         };
     97         for (String intentString : INTENTS) {
     98             registerReceiver(receiver, new IntentFilter(intentString));
     99         }
    100         return mLocalServiceBinder;
    101     }
    102 
    103     @Override
    104     protected void onHandleIntent(Intent intent) {
    105         if (intent == null) {
    106             Log.d(OSUManager.TAG, "Null intent!");
    107             return;
    108         }
    109         //handleIntent(intent.getStringExtra(MainActivity.ACTION_KEY), intent);
    110     }
    111 
    112     private void handleIntent(String action, Intent intent) {
    113         WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    114         Bundle bundle = intent.getExtras();
    115         if (mOsuManager == null) {
    116             mOsuManager = new OSUManager(this);
    117         }
    118         Log.d(OSUManager.TAG, "Got intent " + intent.getAction());
    119 
    120         switch (action) {
    121             case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
    122                 mOsuManager.pushScanResults(wifiManager.getScanResults());
    123                 break;
    124             // TODO(b/32883320): use updated intent definitions.
    125             /*
    126             case WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION:
    127                 long bssid = bundle.getLong(WifiManager.EXTRA_PASSPOINT_WNM_BSSID);
    128                 String url = bundle.getString(WifiManager.EXTRA_PASSPOINT_WNM_URL);
    129 
    130                 try {
    131                     if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_METHOD)) {
    132                         int method = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_METHOD);
    133                         if (method != OSUProvider.OSUMethod.SoapXml.ordinal()) {
    134                             Log.w(OSUManager.TAG, "Unsupported remediation method: " + method);
    135                             return;
    136                         }
    137                         PasspointMatch match = null;
    138                         if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH)) {
    139                             int ordinal =
    140                                     bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH);
    141                             if (ordinal >= 0 && ordinal < PasspointMatch.values().length) {
    142                                 match = PasspointMatch.values()[ordinal];
    143                             }
    144                         }
    145                         mOsuManager.wnmRemediate(bssid, url, match);
    146                     } else if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_ESS)) {
    147                         boolean ess = bundle.getBoolean(WifiManager.EXTRA_PASSPOINT_WNM_ESS);
    148                         int delay = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_DELAY);
    149                         mOsuManager.deauth(bssid, ess, delay, url);
    150                     } else {
    151                         Log.w(OSUManager.TAG, "Unknown WNM event");
    152                     }
    153                 } catch (IOException e) {
    154                     Log.w(OSUManager.TAG, "Remediation event failed to parse: " + e);
    155                 }
    156                 break;
    157             case WifiManager.PASSPOINT_ICON_RECEIVED_ACTION:
    158                 mOsuManager.notifyIconReceived(
    159                         bundle.getLong(WifiManager.EXTRA_PASSPOINT_ICON_BSSID),
    160                         bundle.getString(WifiManager.EXTRA_PASSPOINT_ICON_FILE),
    161                         bundle.getByteArray(WifiManager.EXTRA_PASSPOINT_ICON_DATA));
    162                 break;
    163             */
    164             case WifiManager.NETWORK_STATE_CHANGED_ACTION:
    165                 mOsuManager.networkConnectChange(
    166                         (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO));
    167                 break;
    168             case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
    169                 boolean multiNetwork =
    170                         bundle.getBoolean(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false);
    171                 if (multiNetwork) {
    172                     mOsuManager.networkConfigChanged();
    173                 } else if (bundle.getInt(WifiManager.EXTRA_CHANGE_REASON,
    174                         WifiManager.CHANGE_REASON_CONFIG_CHANGE)
    175                         == WifiManager.CHANGE_REASON_REMOVED) {
    176                     WifiConfiguration configuration =
    177                             intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
    178                     mOsuManager.networkDeleted(configuration);
    179                 } else {
    180                     mOsuManager.networkConfigChanged();
    181                 }
    182                 break;
    183             case WifiManager.WIFI_STATE_CHANGED_ACTION:
    184                 int state = bundle.getInt(WifiManager.EXTRA_WIFI_STATE);
    185                 if (state == WifiManager.WIFI_STATE_DISABLED) {
    186                     mOsuManager.wifiStateChange(false);
    187                 } else if (state == WifiManager.WIFI_STATE_ENABLED) {
    188                     mOsuManager.wifiStateChange(true);
    189                 }
    190                 break;
    191             case REMEDIATION_DONE_ACTION:
    192                 String fqdn = bundle.getString(REMEDIATION_FQDN_EXTRA);
    193                 boolean policy = bundle.getBoolean(REMEDIATION_POLICY_EXTRA);
    194                 mOsuManager.remediationDone(fqdn, policy);
    195                 break;
    196             }
    197     }
    198 
    199     public List<OSUData> getOsuData() {
    200         return mOsuManager.getAvailableOSUs();
    201     }
    202 
    203     public void selectOsu(int id) {
    204         mOsuManager.setOSUSelection(id);
    205     }
    206 }
    207