1 /*
2  * Copyright (C) 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.tv.settings.connectivity;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.net.wifi.WifiConfiguration;
22 import android.os.Bundle;
23 
24 import androidx.fragment.app.Fragment;
25 import androidx.fragment.app.FragmentTransaction;
26 import androidx.lifecycle.ViewModelProviders;
27 
28 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
29 import com.android.settingslib.wifi.AccessPoint;
30 import com.android.tv.settings.R;
31 import com.android.tv.settings.connectivity.setup.AddStartState;
32 import com.android.tv.settings.connectivity.setup.AdvancedWifiOptionsFlow;
33 import com.android.tv.settings.connectivity.setup.ConnectAuthFailureState;
34 import com.android.tv.settings.connectivity.setup.ConnectFailedState;
35 import com.android.tv.settings.connectivity.setup.ConnectRejectedByApState;
36 import com.android.tv.settings.connectivity.setup.ConnectState;
37 import com.android.tv.settings.connectivity.setup.ConnectTimeOutState;
38 import com.android.tv.settings.connectivity.setup.EnterPasswordState;
39 import com.android.tv.settings.connectivity.setup.KnownNetworkState;
40 import com.android.tv.settings.connectivity.setup.OptionsOrConnectState;
41 import com.android.tv.settings.connectivity.setup.SuccessState;
42 import com.android.tv.settings.connectivity.setup.UserChoiceInfo;
43 import com.android.tv.settings.connectivity.util.State;
44 import com.android.tv.settings.connectivity.util.StateMachine;
45 import com.android.tv.settings.connectivity.util.WifiSecurityUtil;
46 import com.android.tv.settings.core.instrumentation.InstrumentedActivity;
47 
48 /**
49  * Add a wifi network where we already know the ssid/security; normal post-install settings.
50  */
51 public class WifiConnectionActivity extends InstrumentedActivity implements
52         State.FragmentChangeListener {
53     private static final String TAG = "WifiConnectionActivity";
54 
55     private static final String EXTRA_WIFI_SSID = "wifi_ssid";
56     private static final String EXTRA_WIFI_SECURITY_NAME = "wifi_security_name";
57 
createIntent(Context context, AccessPoint result, int security)58     public static Intent createIntent(Context context, AccessPoint result, int security) {
59         return new Intent(context, WifiConnectionActivity.class)
60                 .putExtra(EXTRA_WIFI_SSID, result.getSsidStr())
61                 .putExtra(EXTRA_WIFI_SECURITY_NAME, security);
62     }
63 
createIntent(Context context, AccessPoint result)64     public static Intent createIntent(Context context, AccessPoint result) {
65         final int security = result.getSecurity();
66         return createIntent(context, result, security);
67     }
68 
createIntent(Context context, WifiConfiguration configuration)69     public static Intent createIntent(Context context, WifiConfiguration configuration) {
70         final int security = WifiSecurityUtil.getSecurity(configuration);
71         final String ssid = configuration.getPrintableSsid();
72         return new Intent(context, WifiConnectionActivity.class)
73                 .putExtra(EXTRA_WIFI_SSID, ssid)
74                 .putExtra(EXTRA_WIFI_SECURITY_NAME, security);
75     }
76 
77     private WifiConfiguration mConfiguration;
78     private int mWifiSecurity;
79     private StateMachine mStateMachine;
80     private State mConnectAuthFailureState;
81     private State mConnectFailedState;
82     private State mConnectRejectedByApState;
83     private State mConnectState;
84     private State mConnectTimeOutState;
85     private State mEnterPasswordState;
86     private State mKnownNetworkState;
87     private State mSuccessState;
88     private State mOptionsOrConnectState;
89     private State mAddStartState;
90     private State mFinishState;
91 
92     private final StateMachine.Callback mStateMachineCallback = new StateMachine.Callback() {
93         @Override
94         public void onFinish(int result) {
95             setResult(result);
96             finish();
97         }
98     };
99 
100     @Override
onCreate(Bundle savedInstanceState)101     protected void onCreate(Bundle savedInstanceState) {
102         super.onCreate(savedInstanceState);
103         setContentView(R.layout.wifi_container);
104         mStateMachine = ViewModelProviders.of(this).get(StateMachine.class);
105         mStateMachine.setCallback(mStateMachineCallback);
106         mKnownNetworkState = new KnownNetworkState(this);
107         mEnterPasswordState = new EnterPasswordState(this);
108         mConnectState = new ConnectState(this);
109         mConnectTimeOutState = new ConnectTimeOutState(this);
110         mConnectRejectedByApState = new ConnectRejectedByApState(this);
111         mConnectFailedState = new ConnectFailedState(this);
112         mConnectAuthFailureState = new ConnectAuthFailureState(this);
113         mSuccessState = new SuccessState(this);
114         mOptionsOrConnectState = new OptionsOrConnectState(this);
115         mAddStartState = new AddStartState(this);
116         mFinishState = new FinishState(this);
117 
118         /* KnownNetwork */
119         mStateMachine.addState(
120                 mKnownNetworkState,
121                 StateMachine.ADD_START,
122                 mAddStartState);
123         mStateMachine.addState(
124                 mKnownNetworkState,
125                 StateMachine.SELECT_WIFI,
126                 mFinishState);
127 
128         /* Add Start */
129         mStateMachine.addState(
130                 mAddStartState,
131                 StateMachine.PASSWORD,
132                 mEnterPasswordState);
133         mStateMachine.addState(
134                 mAddStartState,
135                 StateMachine.CONNECT,
136                 mConnectState);
137 
138         /* Enter Password */
139         mStateMachine.addState(
140                 mEnterPasswordState,
141                 StateMachine.OPTIONS_OR_CONNECT,
142                 mOptionsOrConnectState);
143 
144         /* Option or Connect */
145         mStateMachine.addState(
146                 mOptionsOrConnectState,
147                 StateMachine.CONNECT,
148                 mConnectState);
149 
150         /* Connect */
151         mStateMachine.addState(
152                 mConnectState,
153                 StateMachine.RESULT_REJECTED_BY_AP,
154                 mConnectRejectedByApState);
155         mStateMachine.addState(
156                 mConnectState,
157                 StateMachine.RESULT_UNKNOWN_ERROR,
158                 mConnectFailedState);
159         mStateMachine.addState(
160                 mConnectState,
161                 StateMachine.RESULT_TIMEOUT,
162                 mConnectTimeOutState);
163         mStateMachine.addState(
164                 mConnectState,
165                 StateMachine.RESULT_BAD_AUTH,
166                 mConnectAuthFailureState);
167         mStateMachine.addState(
168                 mConnectState,
169                 StateMachine.RESULT_SUCCESS,
170                 mSuccessState);
171 
172         /* Connect Failed */
173         mStateMachine.addState(
174                 mConnectFailedState,
175                 StateMachine.TRY_AGAIN,
176                 mOptionsOrConnectState
177         );
178         mStateMachine.addState(
179                 mConnectFailedState,
180                 StateMachine.SELECT_WIFI,
181                 mFinishState
182         );
183 
184         /* Connect Timeout */
185         mStateMachine.addState(
186                 mConnectTimeOutState,
187                 StateMachine.TRY_AGAIN,
188                 mOptionsOrConnectState
189         );
190         mStateMachine.addState(
191                 mConnectTimeOutState,
192                 StateMachine.SELECT_WIFI,
193                 mFinishState
194         );
195 
196         /* Connect Rejected By AP */
197         mStateMachine.addState(
198                 mConnectRejectedByApState,
199                 StateMachine.TRY_AGAIN,
200                 mOptionsOrConnectState);
201         mStateMachine.addState(
202                 mConnectRejectedByApState,
203                 StateMachine.SELECT_WIFI,
204                 mFinishState);
205 
206         /*Connect Auth Failure */
207         mStateMachine.addState(
208                 mConnectAuthFailureState,
209                 StateMachine.TRY_AGAIN,
210                 mOptionsOrConnectState
211         );
212         mStateMachine.addState(
213                 mConnectAuthFailureState,
214                 StateMachine.SELECT_WIFI,
215                 mFinishState
216         );
217 
218         mWifiSecurity = getIntent().getIntExtra(EXTRA_WIFI_SECURITY_NAME, 0);
219         mConfiguration = WifiConfigHelper.getConfiguration(
220                 this, getIntent().getStringExtra(EXTRA_WIFI_SSID), mWifiSecurity);
221 
222         AdvancedWifiOptionsFlow.createFlow(
223                 this, false, true, null,
224                 mOptionsOrConnectState, mConnectState, AdvancedWifiOptionsFlow.START_DEFAULT_PAGE);
225         UserChoiceInfo userChoiceInfo =
226                     ViewModelProviders.of(this).get(UserChoiceInfo.class);
227         userChoiceInfo.setWifiConfiguration(mConfiguration);
228         userChoiceInfo.setWifiSecurity(mWifiSecurity);
229 
230         WifiConfiguration.NetworkSelectionStatus networkStatus =
231                 mConfiguration.getNetworkSelectionStatus();
232         if (networkStatus.getNetworkSelectionDisableReason()
233                 == WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD) {
234             mStateMachine.setStartState(mEnterPasswordState);
235         } else if (WifiConfigHelper.isNetworkSaved(mConfiguration)) {
236             mStateMachine.setStartState(mKnownNetworkState);
237         } else {
238             mStateMachine.setStartState(mAddStartState);
239         }
240         mStateMachine.start(true);
241     }
242 
243     @Override
onBackPressed()244     public void onBackPressed() {
245         mStateMachine.back();
246     }
247 
updateView(androidx.fragment.app.Fragment fragment, boolean movingForward)248     private void updateView(androidx.fragment.app.Fragment fragment, boolean movingForward) {
249         if (fragment != null) {
250             FragmentTransaction updateTransaction = getSupportFragmentManager().beginTransaction();
251             if (movingForward) {
252                 updateTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
253             } else {
254                 updateTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
255             }
256             updateTransaction.replace(R.id.wifi_container, fragment, TAG);
257             updateTransaction.commit();
258         }
259     }
260 
261     @Override
onFragmentChange(Fragment newFragment, boolean movingForward)262     public void onFragmentChange(Fragment newFragment, boolean movingForward) {
263         updateView(newFragment, movingForward);
264     }
265 
266     @Override
getMetricsCategory()267     public int getMetricsCategory() {
268         return MetricsEvent.SETTINGS_TV_WIFI_ADD_KNOWN_CATEGORY;
269     }
270 }
271