1 package com.android.hotspot2.flow; 2 3 import android.annotation.Nullable; 4 import android.app.IntentService; 5 import android.content.BroadcastReceiver; 6 import android.content.Context; 7 import android.content.Intent; 8 import android.content.IntentFilter; 9 import android.net.Network; 10 import android.net.wifi.WifiInfo; 11 import android.net.wifi.WifiManager; 12 import android.os.IBinder; 13 import android.util.Log; 14 15 import com.android.hotspot2.osu.OSUFlowManager; 16 import com.android.hotspot2.osu.OSUManager; 17 import com.android.hotspot2.osu.OSUOperationStatus; 18 import com.android.hotspot2.pps.HomeSP; 19 20 import java.io.IOException; 21 22 /** 23 * This is the Hotspot 2.0 release 2 service that handles actual provisioning and remediation flows. 24 * 25 * The OSU App is made up of two services; FlowService and OSUService. 26 * 27 * OSUService is a long running light weight service, kept alive throughout the lifetime of the 28 * operating system by being bound from the framework (in WifiManager in stage 29 * PHASE_THIRD_PARTY_APPS_CAN_START), and is responsible for continuously caching OSU information 30 * and notifying the UI when OSUs are available. 31 * 32 * FlowService is only started on demand from OSUService and is responsible for handling actual 33 * provisioning and remediation flows, and requires a fairly significant memory footprint. 34 * 35 * FlowService is defined to run in its own process through the definition 36 * <service android:name=".flow.FlowService" android:process=":osuflow"> 37 * in the AndroidManifest. 38 * This is done as a means to keep total app memory footprint low (pss < 10M) and only start the 39 * FlowService on demand and make it available for "garbage collection" by the OS when not in use. 40 */ 41 public class FlowService extends IntentService { 42 private static final String[] INTENTS = { 43 WifiManager.NETWORK_STATE_CHANGED_ACTION 44 }; 45 46 private OSUFlowManager mOSUFlowManager; 47 private PlatformAdapter mPlatformAdapter; 48 private final FlowServiceImpl mOSUAccessor = new FlowServiceImpl(); 49 50 /* 51 public FlowService(Context context) { 52 super("FlowService"); 53 mOSUFlowManager = new OSUFlowManager(); 54 mPlatformAdapter = new PlatformAdapter(context); 55 BroadcastReceiver receiver = new BroadcastReceiver() { 56 @Override 57 public void onReceive(Context context, Intent intent) { 58 handleIntent(intent.getAction(), intent); 59 } 60 }; 61 for (String intentString : INTENTS) { 62 context.registerReceiver(receiver, new IntentFilter(intentString)); 63 } 64 } 65 */ 66 67 public FlowService() { 68 super("FlowService"); 69 } 70 71 public final class FlowServiceImpl extends IFlowService.Stub { 72 public void provision(OSUInfo osuInfo) { 73 FlowService.this.provision(osuInfo); 74 } 75 76 public void remediate(String spFqdn, String url, boolean policy, Network network) { 77 FlowService.this.remediate(spFqdn, url, policy, network); 78 } 79 80 public void spDeleted(String fqdn) { 81 FlowService.this.serviceProviderDeleted(fqdn); 82 } 83 } 84 85 public void provision(OSUInfo osuInfo) { 86 try { 87 mOSUFlowManager.appendFlow(new OSUFlowManager.OSUFlow(osuInfo, mPlatformAdapter, 88 mPlatformAdapter.getKeyManager(null))); 89 } catch (IOException ioe) { 90 mPlatformAdapter.notifyUser(OSUOperationStatus.ProvisioningFailure, ioe.getMessage(), 91 osuInfo.getName(PlatformAdapter.LOCALE)); 92 } 93 } 94 95 /** 96 * Initiate remediation 97 * @param spFqdn The FQDN of the current SP, not set for WNM based remediation 98 * @param url The URL of the remediation server 99 * @param policy Set if this is a policy update rather than a subscription update 100 * @param network The network to use for remediation 101 */ 102 public void remediate(String spFqdn, String url, boolean policy, Network network) { 103 Log.d(OSUManager.TAG, "Starting remediation for " + spFqdn + " to " + url); 104 if (spFqdn != null) { 105 HomeSP homeSP = mPlatformAdapter.getHomeSP(spFqdn); 106 if (homeSP == null) { 107 Log.e(OSUManager.TAG, "No HomeSP object matches '" + spFqdn + "'"); 108 return; 109 } 110 111 try { 112 mOSUFlowManager.appendFlow(new OSUFlowManager.OSUFlow(network, url, 113 mPlatformAdapter, mPlatformAdapter.getKeyManager(homeSP), 114 homeSP, policy 115 ? OSUFlowManager.FlowType.Policy : OSUFlowManager.FlowType.Remediation)); 116 } catch (IOException ioe) { 117 Log.e(OSUManager.TAG, "Failed to remediate: " + ioe, ioe); 118 } 119 } else { 120 HomeSP homeSP = mPlatformAdapter.getCurrentSP(); 121 if (homeSP == null) { 122 Log.e(OSUManager.TAG, "Remediation request on unidentified Passpoint network "); 123 return; 124 } 125 126 try { 127 mOSUFlowManager.appendFlow(new OSUFlowManager.OSUFlow(network, url, 128 mPlatformAdapter, mPlatformAdapter.getKeyManager(homeSP), homeSP, 129 OSUFlowManager.FlowType.Remediation)); 130 } catch (IOException ioe) { 131 Log.e(OSUManager.TAG, "Failed to start remediation: " + ioe, ioe); 132 } 133 } 134 } 135 136 public void serviceProviderDeleted(String fqdn) { 137 mPlatformAdapter.serviceProviderDeleted(fqdn); 138 } 139 140 @Override 141 public IBinder onBind(Intent intent) { 142 mOSUFlowManager = new OSUFlowManager(this); 143 mPlatformAdapter = new PlatformAdapter(this); 144 BroadcastReceiver receiver = new BroadcastReceiver() { 145 @Override 146 public void onReceive(Context context, Intent intent) { 147 handleIntent(intent.getAction(), intent); 148 } 149 }; 150 for (String intentString : INTENTS) { 151 registerReceiver(receiver, new IntentFilter(intentString)); 152 } 153 return mOSUAccessor; 154 } 155 156 @Override 157 protected void onHandleIntent(@Nullable Intent intent) { 158 } 159 160 private void handleIntent(String action, Intent intent) { 161 if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { 162 WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); 163 if (wifiInfo != null) { 164 mOSUFlowManager.networkChange(); 165 } 166 } 167 } 168 } 169