1 /*
2  * Copyright (C) 2019 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.settings.wifi;
18 
19 import android.app.ActionBar;
20 import android.app.Activity;
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.HandlerThread;
27 import android.os.Looper;
28 import android.os.Process;
29 import android.os.SimpleClock;
30 import android.os.SystemClock;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.view.WindowManager;
35 import android.widget.Button;
36 
37 import androidx.annotation.VisibleForTesting;
38 
39 import com.android.settings.R;
40 import com.android.settings.core.InstrumentedFragment;
41 import com.android.settings.overlay.FeatureFactory;
42 import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
43 import com.android.wifitrackerlib.NetworkDetailsTracker;
44 import com.android.wifitrackerlib.WifiEntry;
45 
46 import java.time.Clock;
47 import java.time.ZoneOffset;
48 
49 /**
50  * Detail page for configuring Wi-Fi network.
51  *
52  * The WifiEntry should be saved to the argument when launching this class in order to properly
53  * render this page.
54  */
55 public class ConfigureWifiEntryFragment extends InstrumentedFragment implements WifiConfigUiBase2 {
56 
57     private static final String TAG = "ConfigureWifiEntryFragment";
58 
59     public static final String NETWORK_CONFIG_KEY = "network_config_key";
60 
61     private static final int SUBMIT_BUTTON_ID = android.R.id.button1;
62     private static final int CANCEL_BUTTON_ID = android.R.id.button2;
63 
64     // Max age of tracked WifiEntries
65     private static final long MAX_SCAN_AGE_MILLIS = 15_000;
66     // Interval between initiating SavedNetworkTracker scans
67     private static final long SCAN_INTERVAL_MILLIS = 10_000;
68 
69     private WifiConfigController2 mUiController;
70     private Button mSubmitBtn;
71     private Button mCancelBtn;
72     private WifiEntry mWifiEntry;
73     @VisibleForTesting
74     NetworkDetailsTracker mNetworkDetailsTracker;
75     private HandlerThread mWorkerThread;
76 
77     @Override
onAttach(Context context)78     public void onAttach(Context context) {
79         super.onAttach(context);
80 
81         setupNetworkDetailsTracker();
82         mWifiEntry = mNetworkDetailsTracker.getWifiEntry();
83     }
84 
85     @Override
onDestroy()86     public void onDestroy() {
87         if (mWorkerThread != null) {
88             mWorkerThread.quit();
89         }
90 
91         super.onDestroy();
92     }
93 
94     @Override
getMetricsCategory()95     public int getMetricsCategory() {
96         return SettingsEnums.SETTINGS_WIFI_CONFIGURE_NETWORK;
97     }
98 
99     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)100     public View onCreateView(LayoutInflater inflater, ViewGroup container,
101             Bundle savedInstanceState) {
102         final View rootView = inflater.inflate(R.layout.wifi_add_network_view,
103                 container, false /* attachToRoot */);
104 
105         final Button neutral = rootView.findViewById(android.R.id.button3);
106         if (neutral != null) {
107             neutral.setVisibility(View.GONE);
108         }
109 
110         mSubmitBtn = rootView.findViewById(SUBMIT_BUTTON_ID);
111         mCancelBtn = rootView.findViewById(CANCEL_BUTTON_ID);
112         mSubmitBtn.setOnClickListener(view -> handleSubmitAction());
113         mCancelBtn.setOnClickListener(view -> handleCancelAction());
114 
115         mUiController = new WifiConfigController2(this, rootView, mWifiEntry, getMode());
116 
117         /**
118          * For this add WifiEntry UI, need to remove the Home button, so set related feature as
119          * false.
120          */
121         final ActionBar actionBar = getActivity().getActionBar();
122         if (actionBar != null) {
123             actionBar.setDisplayHomeAsUpEnabled(false);
124             actionBar.setHomeButtonEnabled(false);
125             actionBar.setDisplayShowHomeEnabled(false);
126         }
127 
128         // Resize the layout when keyboard opens.
129         getActivity().getWindow().setSoftInputMode(
130                 WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
131 
132         return rootView;
133     }
134 
135     @Override
onResume()136     public void onResume() {
137         super.onResume();
138         mUiController.showSecurityFields(
139             /* refreshEapMethods */ false, /* refreshCertificates */ true);
140     }
141 
142     @Override
onViewStateRestored(Bundle savedInstanceState)143     public void onViewStateRestored(Bundle savedInstanceState) {
144         super.onViewStateRestored(savedInstanceState);
145         mUiController.updatePassword();
146     }
147 
148     @Override
getMode()149     public int getMode() {
150         return WifiConfigUiBase2.MODE_CONNECT;
151     }
152 
153     @Override
getController()154     public WifiConfigController2 getController() {
155         return mUiController;
156     }
157 
158     @Override
dispatchSubmit()159     public void dispatchSubmit() {
160         handleSubmitAction();
161     }
162 
163     @Override
setTitle(int id)164     public void setTitle(int id) {
165         getActivity().setTitle(id);
166     }
167 
168     @Override
setTitle(CharSequence title)169     public void setTitle(CharSequence title) {
170         getActivity().setTitle(title);
171     }
172 
173     @Override
setSubmitButton(CharSequence text)174     public void setSubmitButton(CharSequence text) {
175         mSubmitBtn.setText(text);
176     }
177 
178     @Override
setCancelButton(CharSequence text)179     public void setCancelButton(CharSequence text) {
180         mCancelBtn.setText(text);
181     }
182 
183     @Override
setForgetButton(CharSequence text)184     public void setForgetButton(CharSequence text) {
185         // AddNetwork doesn't need forget button.
186     }
187 
188     @Override
getSubmitButton()189     public Button getSubmitButton() {
190         return mSubmitBtn;
191     }
192 
193     @Override
getCancelButton()194     public Button getCancelButton() {
195         return mCancelBtn;
196     }
197 
198     @Override
getForgetButton()199     public Button getForgetButton() {
200         // AddNetwork doesn't need forget button.
201         return null;
202     }
203 
204     @VisibleForTesting
handleSubmitAction()205     void handleSubmitAction() {
206         final Intent intent = new Intent();
207         final Activity activity = getActivity();
208         intent.putExtra(NETWORK_CONFIG_KEY, mUiController.getConfig());
209         activity.setResult(Activity.RESULT_OK, intent);
210         activity.finish();
211     }
212 
213     @VisibleForTesting
handleCancelAction()214     void handleCancelAction() {
215         getActivity().finish();
216     }
217 
setupNetworkDetailsTracker()218     private void setupNetworkDetailsTracker() {
219         if (mNetworkDetailsTracker != null) {
220             return;
221         }
222 
223         final Context context = getContext();
224         mWorkerThread = new HandlerThread(TAG
225                 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
226                 Process.THREAD_PRIORITY_BACKGROUND);
227         mWorkerThread.start();
228         final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
229             @Override
230             public long millis() {
231                 return SystemClock.elapsedRealtime();
232             }
233         };
234 
235         mNetworkDetailsTracker = FeatureFactory.getFeatureFactory()
236                 .getWifiTrackerLibProvider()
237                 .createNetworkDetailsTracker(
238                         getSettingsLifecycle(),
239                         context,
240                         new Handler(Looper.getMainLooper()),
241                         mWorkerThread.getThreadHandler(),
242                         elapsedRealtimeClock,
243                         MAX_SCAN_AGE_MILLIS,
244                         SCAN_INTERVAL_MILLIS,
245                         getArguments().getString(
246                                 WifiNetworkDetailsFragment.KEY_CHOSEN_WIFIENTRY_KEY));
247     }
248 }
249