• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.settings.wifi.details2;
17 
18 import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
19 
20 import android.app.Dialog;
21 import android.app.admin.DevicePolicyManager;
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.net.ConnectivityManager;
25 import android.net.NetworkScoreManager;
26 import android.net.wifi.WifiManager;
27 import android.os.Handler;
28 import android.os.HandlerThread;
29 import android.os.Looper;
30 import android.os.Process;
31 import android.os.SimpleClock;
32 import android.os.SystemClock;
33 import android.os.UserHandle;
34 import android.os.UserManager;
35 import android.view.Menu;
36 import android.view.MenuInflater;
37 import android.view.MenuItem;
38 
39 import androidx.annotation.VisibleForTesting;
40 import androidx.preference.PreferenceScreen;
41 
42 import com.android.settings.R;
43 import com.android.settings.Utils;
44 import com.android.settings.dashboard.DashboardFragment;
45 import com.android.settings.wifi.WifiConfigUiBase2;
46 import com.android.settings.wifi.WifiDialog2;
47 import com.android.settingslib.RestrictedLockUtils;
48 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
49 import com.android.settingslib.RestrictedLockUtilsInternal;
50 import com.android.settingslib.core.AbstractPreferenceController;
51 import com.android.wifitrackerlib.NetworkDetailsTracker;
52 import com.android.wifitrackerlib.WifiEntry;
53 
54 import java.time.Clock;
55 import java.time.ZoneOffset;
56 import java.util.ArrayList;
57 import java.util.List;
58 
59 /**
60  * Detail page for the currently connected wifi network.
61  *
62  * <p>The key of {@link WifiEntry} should be saved to the intent Extras when launching this class
63  * in order to properly render this page.
64  */
65 public class WifiNetworkDetailsFragment2 extends DashboardFragment implements
66         WifiDialog2.WifiDialog2Listener {
67 
68     private static final String TAG = "WifiNetworkDetailsFrg2";
69 
70     // Key of a Bundle to save/restore the selected WifiEntry
71     public static final String KEY_CHOSEN_WIFIENTRY_KEY = "key_chosen_wifientry_key";
72 
73     // Max age of tracked WifiEntries
74     private static final long MAX_SCAN_AGE_MILLIS = 15_000;
75     // Interval between initiating SavedNetworkTracker scans
76     private static final long SCAN_INTERVAL_MILLIS = 10_000;
77 
78     @VisibleForTesting
79     NetworkDetailsTracker mNetworkDetailsTracker;
80     private HandlerThread mWorkerThread;
81     private WifiDetailPreferenceController2 mWifiDetailPreferenceController2;
82     private List<WifiDialog2.WifiDialog2Listener> mWifiDialogListeners = new ArrayList<>();
83     @VisibleForTesting
84     List<AbstractPreferenceController> mControllers;
85 
86     @Override
onDestroy()87     public void onDestroy() {
88         mWorkerThread.quit();
89 
90         super.onDestroy();
91     }
92 
93     @Override
getMetricsCategory()94     public int getMetricsCategory() {
95         return SettingsEnums.WIFI_NETWORK_DETAILS;
96     }
97 
98     @Override
getLogTag()99     protected String getLogTag() {
100         return TAG;
101     }
102 
103     @Override
getPreferenceScreenResId()104     protected int getPreferenceScreenResId() {
105         return R.xml.wifi_network_details_fragment2;
106     }
107 
108     @Override
getDialogMetricsCategory(int dialogId)109     public int getDialogMetricsCategory(int dialogId) {
110         if (dialogId == WIFI_DIALOG_ID) {
111             return SettingsEnums.DIALOG_WIFI_AP_EDIT;
112         }
113         return 0;
114     }
115 
116     @Override
onCreateDialog(int dialogId)117     public Dialog onCreateDialog(int dialogId) {
118         if (getActivity() == null || mWifiDetailPreferenceController2 == null) {
119             return null;
120         }
121 
122         final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry();
123         return WifiDialog2.createModal(getActivity(), this, wifiEntry,
124                 WifiConfigUiBase2.MODE_MODIFY);
125     }
126 
127     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)128     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
129         if (isEditable()) {
130             MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify);
131             item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
132             item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
133         }
134         super.onCreateOptionsMenu(menu, inflater);
135     }
136 
137     @Override
onOptionsItemSelected(MenuItem menuItem)138     public boolean onOptionsItemSelected(MenuItem menuItem) {
139         switch (menuItem.getItemId()) {
140             case Menu.FIRST:
141                 if (!mWifiDetailPreferenceController2.canModifyNetwork()) {
142                     EnforcedAdmin admin = RestrictedLockUtilsInternal.getDeviceOwner(getContext());
143                     if (admin == null) {
144                         final DevicePolicyManager dpm = (DevicePolicyManager)
145                                 getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
146                         final UserManager um = (UserManager)
147                                 getContext().getSystemService(Context.USER_SERVICE);
148                         final int profileOwnerUserId = Utils.getManagedProfileId(
149                                 um, UserHandle.myUserId());
150                         if (profileOwnerUserId != UserHandle.USER_NULL) {
151                             admin = new EnforcedAdmin(dpm.getProfileOwnerAsUser(profileOwnerUserId),
152                                     null, UserHandle.of(profileOwnerUserId));
153                         }
154                     }
155                     RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getContext(), admin);
156                 } else {
157                     showDialog(WIFI_DIALOG_ID);
158                 }
159                 return true;
160             default:
161                 return super.onOptionsItemSelected(menuItem);
162         }
163     }
164 
165     @Override
createPreferenceControllers(Context context)166     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
167         mControllers = new ArrayList<>();
168         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
169         setupNetworksDetailTracker();
170         final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry();
171 
172         final WifiSecondSummaryController2 wifiSecondSummaryController2 =
173                 new WifiSecondSummaryController2(context);
174         wifiSecondSummaryController2.setWifiEntry(wifiEntry);
175         mControllers.add(wifiSecondSummaryController2);
176 
177         mWifiDetailPreferenceController2 = WifiDetailPreferenceController2.newInstance(
178                 wifiEntry,
179                 cm,
180                 context,
181                 this,
182                 new Handler(Looper.getMainLooper()),  // UI thread.
183                 getSettingsLifecycle(),
184                 context.getSystemService(WifiManager.class),
185                 mMetricsFeatureProvider);
186         mControllers.add(mWifiDetailPreferenceController2);
187 
188         final WifiAutoConnectPreferenceController2 wifiAutoConnectPreferenceController2 =
189                 new WifiAutoConnectPreferenceController2(context);
190         wifiAutoConnectPreferenceController2.setWifiEntry(wifiEntry);
191         mControllers.add(wifiAutoConnectPreferenceController2);
192 
193         final AddDevicePreferenceController2 addDevicePreferenceController2 =
194                 new AddDevicePreferenceController2(context);
195         addDevicePreferenceController2.setWifiEntry(wifiEntry);
196         mControllers.add(addDevicePreferenceController2);
197 
198         final WifiMeteredPreferenceController2 meteredPreferenceController2 =
199                 new WifiMeteredPreferenceController2(context, wifiEntry);
200         mControllers.add(meteredPreferenceController2);
201 
202         final WifiPrivacyPreferenceController2 privacyController2 =
203                 new WifiPrivacyPreferenceController2(context);
204         privacyController2.setWifiEntry(wifiEntry);
205         mControllers.add(privacyController2);
206 
207         final WifiSubscriptionDetailPreferenceController2
208                 wifiSubscriptionDetailPreferenceController2 =
209                 new WifiSubscriptionDetailPreferenceController2(context);
210         wifiSubscriptionDetailPreferenceController2.setWifiEntry(wifiEntry);
211         mControllers.add(wifiSubscriptionDetailPreferenceController2);
212 
213         // Sets callback listener for wifi dialog.
214         mWifiDialogListeners.add(mWifiDetailPreferenceController2);
215         mWifiDialogListeners.add(privacyController2);
216         mWifiDialogListeners.add(meteredPreferenceController2);
217 
218         return mControllers;
219     }
220 
221     @Override
onSubmit(WifiDialog2 dialog)222     public void onSubmit(WifiDialog2 dialog) {
223         for (WifiDialog2.WifiDialog2Listener listener : mWifiDialogListeners) {
224             listener.onSubmit(dialog);
225         }
226     }
227 
setupNetworksDetailTracker()228     private void setupNetworksDetailTracker() {
229         if (mNetworkDetailsTracker != null) {
230             return;
231         }
232 
233         final Context context = getContext();
234         mWorkerThread = new HandlerThread(TAG
235                 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
236                 Process.THREAD_PRIORITY_BACKGROUND);
237         mWorkerThread.start();
238         final Clock elapsedRealtimeClock = new SimpleClock(ZoneOffset.UTC) {
239             @Override
240             public long millis() {
241                 return SystemClock.elapsedRealtime();
242             }
243         };
244 
245         mNetworkDetailsTracker = NetworkDetailsTracker.createNetworkDetailsTracker(
246                 getSettingsLifecycle(),
247                 context,
248                 context.getSystemService(WifiManager.class),
249                 context.getSystemService(ConnectivityManager.class),
250                 context.getSystemService(NetworkScoreManager.class),
251                 new Handler(Looper.getMainLooper()),
252                 mWorkerThread.getThreadHandler(),
253                 elapsedRealtimeClock,
254                 MAX_SCAN_AGE_MILLIS,
255                 SCAN_INTERVAL_MILLIS,
256                 getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY));
257     }
258 
isEditable()259     private boolean isEditable() {
260         if (mNetworkDetailsTracker == null) {
261             return false;
262         }
263         final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry();
264         if (wifiEntry == null) {
265             return false;
266         }
267         return wifiEntry.isSaved();
268     }
269 
270     /**
271      * API call for refreshing the preferences in this fragment.
272      */
refreshPreferences()273     public void refreshPreferences() {
274         updatePreferenceStates();
275         displayPreferenceControllers();
276     }
277 
displayPreferenceControllers()278     protected void displayPreferenceControllers() {
279         final PreferenceScreen screen = getPreferenceScreen();
280         for (AbstractPreferenceController controller : mControllers) {
281             // WifiDetailPreferenceController2 gets the callback WifiEntryCallback#onUpdated,
282             // it can control the visibility change by itself.
283             // And WifiDetailPreferenceController2#updatePreference renew mEntityHeaderController
284             // instance which will cause icon reset.
285             if (controller instanceof WifiDetailPreferenceController2) {
286                 continue;
287             }
288             controller.displayPreference(screen);
289         }
290     }
291 }
292