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 OSUService()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 onStartCommand(Intent intent, int flags, int startId)84 public int onStartCommand(Intent intent, int flags, int startId) { 85 onHandleIntent(intent); 86 return START_STICKY; 87 } 88 89 @Override onBind(Intent intent)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 onHandleIntent(Intent intent)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 handleIntent(String action, Intent intent)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 getOsuData()199 public List<OSUData> getOsuData() { 200 return mOsuManager.getAvailableOSUs(); 201 } 202 selectOsu(int id)203 public void selectOsu(int id) { 204 mOsuManager.setOSUSelection(id); 205 } 206 } 207