10701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistpackage com.android.hotspot2.osu; 20701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 30701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.content.Context; 40701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.content.Intent; 50701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.net.Network; 60701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.net.wifi.WifiConfiguration; 70701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.net.wifi.WifiInfo; 80701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.os.SystemClock; 90701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.util.Log; 100701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 110701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.Utils; 120701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.flow.FlowService; 130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.flow.OSUInfo; 140701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.flow.PlatformAdapter; 150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.pps.HomeSP; 160701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 170701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.io.IOException; 180701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.net.MalformedURLException; 190701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.util.Iterator; 200701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.util.LinkedList; 210701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 220701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport javax.net.ssl.KeyManager; 230701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 240701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistpublic class OSUFlowManager { 250701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private static final boolean MATCH_BSSID = false; 260701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private static final long WAIT_QUANTA = 10000L; 270701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private static final long WAIT_TIMEOUT = 1800000L; 280701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 290701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final Context mContext; 300701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final LinkedList<OSUFlow> mQueue; 310701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private FlowWorker mWorker; 320701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private OSUFlow mCurrent; 330701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 340701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public OSUFlowManager(Context context) { 350701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mContext = context; 360701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mQueue = new LinkedList<>(); 370701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 380701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 390701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public enum FlowType {Provisioning, Remediation, Policy} 400701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 410701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public static class OSUFlow implements Runnable { 420701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final OSUClient mOSUClient; 430701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final PlatformAdapter mPlatformAdapter; 440701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final HomeSP mHomeSP; 450701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final String mSpName; 460701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final FlowType mFlowType; 470701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final KeyManager mKeyManager; 480701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final Object mNetworkLock = new Object(); 490701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final Network mNetwork; 500701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private Network mResultNetwork; 510701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private boolean mNetworkCreated; 520701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private int mWifiNetworkId; 530701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private volatile long mLaunchTime; 540701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private volatile boolean mAborted; 550701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 560701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist /** 570701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * A policy flow. 580701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param osuInfo The OSU information for the flow (SSID, BSSID, URL) 590701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param platformAdapter the platform adapter 600701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param km A key manager for TLS 610701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @throws MalformedURLException 620701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist */ 630701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public OSUFlow(OSUInfo osuInfo, PlatformAdapter platformAdapter, KeyManager km) 640701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist throws MalformedURLException { 650701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 660701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWifiNetworkId = -1; 670701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetwork = null; 680701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient = new OSUClient(osuInfo, 690701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist platformAdapter.getKeyStore(), platformAdapter.getContext()); 700701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mPlatformAdapter = platformAdapter; 710701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mHomeSP = null; 720701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mSpName = osuInfo.getName(OSUManager.LOCALE); 730701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mFlowType = FlowType.Provisioning; 740701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mKeyManager = km; 750701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 760701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 770701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist /** 780701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * A Remediation flow for credential or policy provisioning. 790701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param network The network to use, only set for timed provisioning 800701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param osuURL The URL to connect to. 810701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param platformAdapter the platform adapter 820701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param km A key manager for TLS 830701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param homeSP The Home SP to which this remediation flow pertains. 840701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @param flowType Remediation or Policy 850701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * @throws MalformedURLException 860701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist */ 870701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public OSUFlow(Network network, String osuURL, 880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist PlatformAdapter platformAdapter, KeyManager km, HomeSP homeSP, 890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist FlowType flowType) throws MalformedURLException { 900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetwork = network; 920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWifiNetworkId = network.netId; 930701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient = new OSUClient(osuURL, 940701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist platformAdapter.getKeyStore(), platformAdapter.getContext()); 950701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mPlatformAdapter = platformAdapter; 960701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mHomeSP = homeSP; 970701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mSpName = homeSP.getFriendlyName(); 980701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mFlowType = flowType; 990701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mKeyManager = km; 1000701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1010701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1020701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private boolean deleteNetwork(OSUFlow next) { 1030701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1040701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (!mNetworkCreated) { 1050701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return false; 1060701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else if (next.getFlowType() != FlowType.Provisioning) { 1070701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return true; 1080701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1090701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist OSUInfo thisInfo = mOSUClient.getOSUInfo(); 1100701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist OSUInfo thatInfo = next.mOSUClient.getOSUInfo(); 1110701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (thisInfo.getOsuSsid().equals(thatInfo.getOsuSsid()) 1120701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist && thisInfo.getOSUBssid() == thatInfo.getOSUBssid()) { 1130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // Reuse the OSU network from previous and carry forward the creation fact. 1140701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetworkCreated = true; 1150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return false; 1160701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 1170701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return true; 1180701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1190701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1200701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1210701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1220701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private Network connect() throws IOException { 1230701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Network network = networkMatch(); 1240701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1250701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1260701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mResultNetwork = network; 1270701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mResultNetwork != null) { 1280701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mResultNetwork; 1290701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1300701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1310701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1320701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "No network match for " + toString()); 1330701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1340701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist int osuNetworkId = -1; 1350701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist boolean created = false; 1360701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1370701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mFlowType == FlowType.Provisioning) { 1380701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist osuNetworkId = mPlatformAdapter.connect(mOSUClient.getOSUInfo()); 1390701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist created = true; 1400701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1410701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1420701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1430701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetworkCreated = created; 1440701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (created) { 1450701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWifiNetworkId = osuNetworkId; 1460701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1470701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, String.format("%s waiting for %snet ID %d", 1480701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist toString(), created ? "created " : "existing ", osuNetworkId)); 1490701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1500701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist while (mResultNetwork == null && !mAborted) { 1510701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist try { 1520701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetworkLock.wait(); 1530701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } catch (InterruptedException ie) { 1540701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist throw new IOException("Interrupted"); 1550701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1560701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1570701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mAborted) { 1580701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist throw new IOException("Aborted"); 1590701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1600701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Utils.delay(500L); 1610701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1620701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mResultNetwork; 1630701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1640701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1650701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private Network networkMatch() { 1660701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mFlowType == FlowType.Provisioning) { 1670701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist OSUInfo match = mOSUClient.getOSUInfo(); 1680701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist WifiConfiguration config = mPlatformAdapter.getActiveWifiConfig(); 1690701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (config != null && bssidMatch(match, mPlatformAdapter) 1700701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist && Utils.decodeSsid(config.SSID).equals(match.getOsuSsid())) { 1710701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1720701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWifiNetworkId = config.networkId; 1730701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1740701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mPlatformAdapter.getCurrentNetwork(); 1750701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1760701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 1770701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist WifiConfiguration config = mPlatformAdapter.getActiveWifiConfig(); 1780701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1790701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWifiNetworkId = config != null ? config.networkId : -1; 1800701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1810701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mNetwork; 1820701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1830701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return null; 1840701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1850701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1860701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private void networkChange() { 1870701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist WifiInfo connectionInfo = mPlatformAdapter.getConnectionInfo(); 1880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (connectionInfo == null) { 1890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return; 1900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 1910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Network network = mPlatformAdapter.getCurrentNetwork(); 1920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "New network " + network 1930701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist + ", current OSU " + mOSUClient.getOSUInfo() + 1940701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist ", addr " + Utils.toIpString(connectionInfo.getIpAddress())); 1950701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 1960701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 1970701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mResultNetwork == null && network != null && connectionInfo.getIpAddress() != 0 1980701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist && connectionInfo.getNetworkId() == mWifiNetworkId) { 1990701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mResultNetwork = network; 2000701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetworkLock.notifyAll(); 2010701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2020701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2030701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2040701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2050701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public boolean createdNetwork() { 2060701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 2070701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mNetworkCreated; 2080701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2090701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2100701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2110701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public FlowType getFlowType() { 2120701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mFlowType; 2130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2140701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public PlatformAdapter getPlatformAdapter() { 2160701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mPlatformAdapter; 2170701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2180701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2190701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private void setLaunchTime() { 2200701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mLaunchTime = SystemClock.currentThreadTimeMillis(); 2210701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2220701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2230701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public long getLaunchTime() { 2240701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mLaunchTime; 2250701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2260701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2270701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private int getWifiNetworkId() { 2280701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 2290701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mWifiNetworkId; 2300701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2310701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2320701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2330701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist @Override 2340701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void run() { 2350701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist try { 2360701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Network network = connect(); 2370701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "OSU SSID Associated at " + network); 2380701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2390701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mFlowType == FlowType.Provisioning) { 2400701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient.provision(mPlatformAdapter, network, mKeyManager); 2410701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 2420701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient.remediate(mPlatformAdapter, network, 2430701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mKeyManager, mHomeSP, mFlowType); 2440701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2450701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } catch (Throwable t) { 2460701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mAborted) { 2470701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "OSU flow aborted: " + t, t); 2480701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 2490701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.w(OSUManager.TAG, "OSU flow failed: " + t, t); 2500701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mPlatformAdapter.provisioningFailed(mSpName, t.getMessage()); 2510701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2520701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } finally { 2530701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (!mAborted) { 2540701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient.close(false); 2550701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2560701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2570701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2580701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2590701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void abort() { 2600701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mNetworkLock) { 2610701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mAborted = true; 2620701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mNetworkLock.notifyAll(); 2630701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2640701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // Sockets cannot be closed on the main thread... 2650701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // TODO: Might want to change this to a handler. 2660701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist new Thread() { 2670701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist @Override 2680701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void run() { 2690701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist try { 2700701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mOSUClient.close(true); 2710701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } catch (Throwable t) { 2720701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Exception aborting " + toString()); 2730701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2740701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2750701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist }.start(); 2760701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2770701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2780701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist @Override 2790701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public String toString() { 2800701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return mFlowType + " for " + mSpName; 2810701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2820701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2830701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2840701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private class FlowWorker extends Thread { 2850701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private final PlatformAdapter mPlatformAdapter; 2860701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2870701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private FlowWorker(PlatformAdapter platformAdapter) { 2880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mPlatformAdapter = platformAdapter; 2890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 2910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist @Override 2920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void run() { 2930701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist for (; ; ) { 2940701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mQueue) { 2950701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mCurrent != null && mCurrent.createdNetwork() 2960701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist && (mQueue.isEmpty() || mCurrent.deleteNetwork(mQueue.getLast()))) { 2970701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mPlatformAdapter.deleteNetwork(mCurrent.getWifiNetworkId()); 2980701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 2990701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3000701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent = null; 3010701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist while (mQueue.isEmpty()) { 3020701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist try { 3030701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mQueue.wait(WAIT_QUANTA); 3040701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } catch (InterruptedException ie) { 3050701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return; 3060701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3070701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mQueue.isEmpty()) { 3080701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // Bail out on time out 3090701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Flow worker terminating."); 3100701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWorker = null; 3110701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mContext.stopService(new Intent(mContext, FlowService.class)); 3120701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return; 3130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3140701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent = mQueue.removeLast(); 3160701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent.setLaunchTime(); 3170701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3180701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Starting " + mCurrent); 3190701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent.run(); 3200701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Exiting " + mCurrent); 3210701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3220701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3230701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3240701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3250701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist /* 3260701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * Provisioning: Wait until there is an active WiFi info and the active WiFi config 3270701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * matches SSID and optionally BSSID. 3280701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * WNM Remediation: Wait until the active WiFi info matches BSSID. 3290701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist * Timed remediation: The network is given (may be cellular). 3300701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist */ 3310701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3320701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void appendFlow(OSUFlow flow) { 3330701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mQueue) { 3340701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mCurrent != null && 3350701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist SystemClock.currentThreadTimeMillis() 3360701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist - mCurrent.getLaunchTime() >= WAIT_TIMEOUT) { 3370701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Aborting stale OSU flow " + mCurrent); 3380701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent.abort(); 3390701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent = null; 3400701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3410701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3420701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (flow.getFlowType() == FlowType.Provisioning) { 3430701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // Kill any outstanding provisioning flows. 3440701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Iterator<OSUFlow> flows = mQueue.iterator(); 3450701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist while (flows.hasNext()) { 3460701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (flows.next().getFlowType() == FlowType.Provisioning) { 3470701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist flows.remove(); 3480701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3490701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3500701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3510701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mCurrent != null 3520701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist && mCurrent.getFlowType() == FlowType.Provisioning) { 3530701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Aborting current provisioning flow " + mCurrent); 3540701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent.abort(); 3550701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mCurrent = null; 3560701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3570701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3580701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mQueue.addLast(flow); 3590701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 3600701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mQueue.addFirst(flow); 3610701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3620701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3630701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (mWorker == null) { 3640701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist // TODO: Might want to change this to a handler. 3650701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWorker = new FlowWorker(flow.getPlatformAdapter()); 3660701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mWorker.start(); 3670701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3680701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3690701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist mQueue.notifyAll(); 3700701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3710701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3720701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3730701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist public void networkChange() { 3740701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist OSUFlow pending; 3750701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist synchronized (mQueue) { 3760701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist pending = mCurrent; 3770701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3780701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist Log.d(OSUManager.TAG, "Network change, current flow: " + pending); 3790701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (pending != null) { 3800701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist pending.networkChange(); 3810701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3820701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3830701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist 3840701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist private static boolean bssidMatch(OSUInfo osuInfo, PlatformAdapter platformAdapter) { 3850701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist if (MATCH_BSSID) { 3860701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist WifiInfo wifiInfo = platformAdapter.getConnectionInfo(); 3870701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return wifiInfo != null && Utils.parseMac(wifiInfo.getBSSID()) == osuInfo.getOSUBssid(); 3880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } else { 3890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist return true; 3900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist } 3920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist} 393