• 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 static com.android.internal.util.Preconditions.checkNotNull;
20 
21 import android.content.Context;
22 import android.net.wifi.WifiConfiguration;
23 import android.net.wifi.WifiManager;
24 import android.os.Handler;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.managedprovisioning.R;
28 import com.android.managedprovisioning.common.ProvisionLogger;
29 import com.android.managedprovisioning.common.Utils;
30 import com.android.managedprovisioning.model.ProvisioningParams;
31 import com.android.managedprovisioning.task.wifi.NetworkMonitor;
32 import com.android.managedprovisioning.task.wifi.WifiConfigurationProvider;
33 
34 /**
35  * Adds a wifi network to the system and waits for it to successfully connect. If the system does
36  * not support wifi, the adding or connection times out {@link #error(int)} will be called.
37  */
38 public class AddWifiNetworkTask extends AbstractProvisioningTask
39         implements NetworkMonitor.NetworkConnectedCallback {
40     private static final int RETRY_SLEEP_DURATION_BASE_MS = 500;
41     private static final int RETRY_SLEEP_MULTIPLIER = 2;
42     private static final int MAX_RETRIES = 6;
43     private static final int RECONNECT_TIMEOUT_MS = 60000;
44 
45     private final WifiConfigurationProvider mWifiConfigurationProvider;
46     private final WifiManager mWifiManager;
47     private final NetworkMonitor mNetworkMonitor;
48 
49     private Handler mHandler;
50     private boolean mTaskDone = false;
51 
52     private final Utils mUtils = new Utils();
53     private Runnable mTimeoutRunnable;
54 
AddWifiNetworkTask( Context context, ProvisioningParams provisioningParams, Callback callback)55     public AddWifiNetworkTask(
56             Context context,
57             ProvisioningParams provisioningParams,
58             Callback callback) {
59         this(
60                 new NetworkMonitor(context),
61                 new WifiConfigurationProvider(),
62                 context, provisioningParams, callback);
63     }
64 
65     @VisibleForTesting
AddWifiNetworkTask( NetworkMonitor networkMonitor, WifiConfigurationProvider wifiConfigurationProvider, Context context, ProvisioningParams provisioningParams, Callback callback)66     AddWifiNetworkTask(
67             NetworkMonitor networkMonitor,
68             WifiConfigurationProvider wifiConfigurationProvider,
69             Context context,
70             ProvisioningParams provisioningParams,
71             Callback callback) {
72         super(context, provisioningParams, callback);
73 
74         mNetworkMonitor = checkNotNull(networkMonitor);
75         mWifiConfigurationProvider = checkNotNull(wifiConfigurationProvider);
76         mWifiManager  = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
77     }
78 
79     @Override
run(int userId)80     public void run(int userId) {
81         if (mProvisioningParams.wifiInfo == null) {
82             success();
83             return;
84         }
85 
86         if (mWifiManager == null || !enableWifi()) {
87             ProvisionLogger.loge("Failed to enable wifi");
88             error(0);
89             return;
90         }
91 
92         if (isConnectedToSpecifiedWifi()) {
93             success();
94             return;
95         }
96 
97         mTaskDone = false;
98         mHandler = new Handler();
99         mNetworkMonitor.startListening(this);
100         connectToProvidedNetwork();
101     }
102 
103     @Override
getStatusMsgId()104     public int getStatusMsgId() {
105         return R.string.progress_connect_to_wifi;
106     }
107 
connectToProvidedNetwork()108     private void connectToProvidedNetwork() {
109         WifiConfiguration wifiConf =
110                 mWifiConfigurationProvider.generateWifiConfiguration(mProvisioningParams.wifiInfo);
111 
112         if (wifiConf == null) {
113             ProvisionLogger.loge("WifiConfiguration is null");
114             error(0);
115             return;
116         }
117 
118         int netId = tryAddingNetwork(wifiConf);
119         if (netId == -1) {
120             ProvisionLogger.loge("Unable to add network after trying " +  MAX_RETRIES + " times.");
121             error(0);
122             return;
123         }
124 
125         // Setting disableOthers to 'true' should trigger a connection attempt.
126         mWifiManager.enableNetwork(netId, true);
127         mWifiManager.saveConfiguration();
128 
129         // Network was successfully saved, now connect to it.
130         if (!mWifiManager.reconnect()) {
131             ProvisionLogger.loge("Unable to connect to wifi");
132             error(0);
133             return;
134         }
135 
136         // NetworkMonitor will call onNetworkConnected when in Wifi mode.
137         // Post time out event in case the NetworkMonitor doesn't call back.
138         mTimeoutRunnable = () -> finishTask(false);
139         mHandler.postDelayed(mTimeoutRunnable, RECONNECT_TIMEOUT_MS);
140     }
141 
tryAddingNetwork(WifiConfiguration wifiConf)142     private int tryAddingNetwork(WifiConfiguration wifiConf) {
143         int netId = mWifiManager.addNetwork(wifiConf);
144         int retriesLeft = MAX_RETRIES;
145         int durationNextSleep = RETRY_SLEEP_DURATION_BASE_MS;
146 
147         while(netId == -1 && retriesLeft > 0) {
148             ProvisionLogger.loge("Retrying in " + durationNextSleep + " ms.");
149             try {
150                 Thread.sleep(durationNextSleep);
151             } catch (InterruptedException e) {
152                 ProvisionLogger.loge("Retry interrupted.");
153             }
154             durationNextSleep *= RETRY_SLEEP_MULTIPLIER;
155             retriesLeft--;
156             netId = mWifiManager.addNetwork(wifiConf);
157         }
158         return netId;
159     }
160 
enableWifi()161     private boolean enableWifi() {
162         return mWifiManager.isWifiEnabled() || mWifiManager.setWifiEnabled(true);
163     }
164 
165     @Override
onNetworkConnected()166     public void onNetworkConnected() {
167         if (isConnectedToSpecifiedWifi()) {
168             ProvisionLogger.logd("Connected to the correct network");
169             finishTask(true);
170             // Remove time out callback.
171             mHandler.removeCallbacks(mTimeoutRunnable);
172         }
173     }
174 
finishTask(boolean isSuccess)175     private synchronized void finishTask(boolean isSuccess) {
176         if (mTaskDone) {
177             return;
178         }
179 
180         mTaskDone = true;
181         mNetworkMonitor.stopListening();
182         if (isSuccess) {
183             success();
184         } else {
185             error(0);
186         }
187     }
188 
isConnectedToSpecifiedWifi()189     private boolean isConnectedToSpecifiedWifi() {
190         return mUtils.isConnectedToWifi(mContext)
191                 && mWifiManager.getConnectionInfo() != null
192                 && mProvisioningParams.wifiInfo.ssid.equals(
193                         mWifiManager.getConnectionInfo().getSSID());
194     }
195 }
196