• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.managedprovisioning.task;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.net.ConnectivityManager;
22 import android.net.NetworkInfo;
23 import android.net.wifi.WifiManager;
24 import android.os.Handler;
25 import android.os.HandlerThread;
26 import android.os.Looper;
27 import android.support.annotation.Nullable;
28 import android.text.TextUtils;
29 
30 import java.lang.Thread;
31 
32 import com.android.managedprovisioning.NetworkMonitor;
33 import com.android.managedprovisioning.ProvisionLogger;
34 import com.android.managedprovisioning.WifiConfig;
35 import com.android.managedprovisioning.common.Utils;
36 import com.android.managedprovisioning.model.WifiInfo;
37 
38 /**
39  * Adds a wifi network to system.
40  */
41 public class AddWifiNetworkTask implements NetworkMonitor.Callback {
42     private static final int RETRY_SLEEP_DURATION_BASE_MS = 500;
43     private static final int RETRY_SLEEP_MULTIPLIER = 2;
44     private static final int MAX_RETRIES = 6;
45     private static final int RECONNECT_TIMEOUT_MS = 60000;
46 
47     private final Context mContext;
48     @Nullable
49     private final WifiInfo mWifiInfo;
50     private final Callback mCallback;
51 
52     private WifiManager mWifiManager;
53     private NetworkMonitor mNetworkMonitor;
54     private WifiConfig mWifiConfig;
55 
56     private Handler mHandler;
57     private boolean mTaskDone = false;
58 
59     private int mDurationNextSleep = RETRY_SLEEP_DURATION_BASE_MS;
60     private int mRetriesLeft = MAX_RETRIES;
61 
62     private final Utils mUtils = new Utils();
63 
64     /**
65      * @throws IllegalArgumentException if the {@code ssid} parameter is empty.
66      */
AddWifiNetworkTask(Context context, WifiInfo wifiInfo, Callback callback)67     public AddWifiNetworkTask(Context context, WifiInfo wifiInfo, Callback callback) {
68         mCallback = callback;
69         mContext = context;
70         mWifiInfo = wifiInfo;
71         mWifiManager  = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
72         mWifiConfig = new WifiConfig(mWifiManager);
73 
74         HandlerThread thread = new HandlerThread("Timeout thread",
75                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
76         thread.start();
77         Looper looper = thread.getLooper();
78         mHandler = new Handler(looper);
79     }
80 
run()81     public void run() {
82         if (mWifiInfo == null) {
83             mCallback.onSuccess();
84             return;
85         }
86         if (!enableWifi()) {
87             ProvisionLogger.loge("Failed to enable wifi");
88             mCallback.onError();
89             return;
90         }
91 
92         if (isConnectedToSpecifiedWifi()) {
93             mCallback.onSuccess();
94             return;
95         }
96 
97         mNetworkMonitor = new NetworkMonitor(mContext, this);
98         connectToProvidedNetwork();
99     }
100 
connectToProvidedNetwork()101     private void connectToProvidedNetwork() {
102         int netId = mWifiConfig.addNetwork(mWifiInfo.ssid, mWifiInfo.hidden, mWifiInfo.securityType,
103                 mWifiInfo.password, mWifiInfo.proxyHost, mWifiInfo.proxyPort,
104                 mWifiInfo.proxyBypassHosts, mWifiInfo.pacUrl);
105 
106         if (netId == -1) {
107             ProvisionLogger.loge("Failed to save network.");
108             if (mRetriesLeft > 0) {
109                 ProvisionLogger.loge("Retrying in " + mDurationNextSleep + " ms.");
110                 try {
111                     Thread.sleep(mDurationNextSleep);
112                 } catch (InterruptedException e) {
113                     ProvisionLogger.loge("Retry interrupted.");
114                 }
115                 mDurationNextSleep *= RETRY_SLEEP_MULTIPLIER;
116                 mRetriesLeft--;
117                 connectToProvidedNetwork();
118                 return;
119             } else {
120                 ProvisionLogger.loge("Already retried " +  MAX_RETRIES + " times."
121                         + " Quit retrying and report error.");
122                 mCallback.onError();
123                 return;
124             }
125         }
126 
127         // Network was successfully saved, now connect to it.
128         if (!mWifiManager.reconnect()) {
129             ProvisionLogger.loge("Unable to connect to wifi");
130             mCallback.onError();
131             return;
132         }
133 
134         // NetworkMonitor will call onNetworkConnected when in Wifi mode.
135         // Post time out event in case the NetworkMonitor doesn't call back.
136         mHandler.postDelayed(new Runnable() {
137                 public void run(){
138                     synchronized(this) {
139                         if (mTaskDone) return;
140                         mTaskDone = true;
141                     }
142                     ProvisionLogger.loge("Setting up wifi connection timed out.");
143                     mCallback.onError();
144                     return;
145                 }
146             }, RECONNECT_TIMEOUT_MS);
147     }
148 
enableWifi()149     private boolean enableWifi() {
150         return mWifiManager != null
151                 && (mWifiManager.isWifiEnabled() || mWifiManager.setWifiEnabled(true));
152     }
153 
154     @Override
onNetworkConnected()155     public void onNetworkConnected() {
156         if (isConnectedToSpecifiedWifi()) {
157             synchronized(this) {
158                 if (mTaskDone) return;
159                 mTaskDone = true;
160             }
161 
162             ProvisionLogger.logd("Connected to the correct network");
163 
164             // Remove time out callback.
165             mHandler.removeCallbacksAndMessages(null);
166 
167             cleanUp();
168             mCallback.onSuccess();
169             return;
170         }
171     }
172 
173     @Override
onNetworkDisconnected()174     public void onNetworkDisconnected() {
175 
176     }
177 
cleanUp()178     public void cleanUp() {
179         if (mNetworkMonitor != null) {
180             mNetworkMonitor.close();
181             mNetworkMonitor = null;
182         }
183     }
184 
isConnectedToSpecifiedWifi()185     private boolean isConnectedToSpecifiedWifi() {
186         return mUtils.isConnectedToWifi(mContext)
187                 && mWifiManager != null
188                 && mWifiManager.getConnectionInfo() != null
189                 && mWifiInfo.ssid.equals(mWifiManager.getConnectionInfo().getSSID());
190     }
191 
192     public abstract static class Callback {
onSuccess()193         public abstract void onSuccess();
onError()194         public abstract void onError();
195     }
196 }
197