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.car.developeroptions.wifi.savedaccesspoints;
18 
19 import android.annotation.Nullable;
20 import android.app.Dialog;
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.net.wifi.WifiManager;
25 import android.os.Bundle;
26 import android.util.FeatureFlagUtils;
27 import android.util.Log;
28 
29 import com.android.car.developeroptions.R;
30 import com.android.car.developeroptions.core.FeatureFlags;
31 import com.android.car.developeroptions.core.SubSettingLauncher;
32 import com.android.car.developeroptions.dashboard.DashboardFragment;
33 import com.android.car.developeroptions.development.featureflags.FeatureFlagPersistent;
34 import com.android.car.developeroptions.wifi.WifiConfigUiBase;
35 import com.android.car.developeroptions.wifi.WifiDialog;
36 import com.android.car.developeroptions.wifi.WifiSettings;
37 import com.android.car.developeroptions.wifi.details.WifiNetworkDetailsFragment;
38 import com.android.settingslib.wifi.AccessPoint;
39 import com.android.settingslib.wifi.AccessPointPreference;
40 
41 /**
42  * UI to manage saved networks/access points.
43  */
44 public class SavedAccessPointsWifiSettings extends DashboardFragment
45         implements WifiDialog.WifiDialogListener, DialogInterface.OnCancelListener {
46 
47     private static final String TAG = "SavedAccessPoints";
48 
49     private WifiManager mWifiManager;
50     private Bundle mAccessPointSavedState;
51     private AccessPoint mSelectedAccessPoint;
52 
53     // Instance state key
54     private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
55 
56     @Override
getMetricsCategory()57     public int getMetricsCategory() {
58         return SettingsEnums.WIFI_SAVED_ACCESS_POINTS;
59     }
60 
61     @Override
getPreferenceScreenResId()62     protected int getPreferenceScreenResId() {
63         return R.xml.wifi_display_saved_access_points;
64     }
65 
66     @Override
getLogTag()67     protected String getLogTag() {
68         return TAG;
69     }
70 
71     @Override
onAttach(Context context)72     public void onAttach(Context context) {
73         super.onAttach(context);
74         mWifiManager = (WifiManager) getContext()
75                 .getApplicationContext().getSystemService(Context.WIFI_SERVICE);
76         use(SavedAccessPointsPreferenceController.class)
77                 .setHost(this);
78         use(SubscribedAccessPointsPreferenceController.class)
79                 .setHost(this);
80     }
81 
82     @Override
onCreate(Bundle savedInstanceState)83     public void onCreate(Bundle savedInstanceState) {
84         super.onCreate(savedInstanceState);
85         if (savedInstanceState != null) {
86             if (savedInstanceState.containsKey(SAVE_DIALOG_ACCESS_POINT_STATE)) {
87                 mAccessPointSavedState =
88                         savedInstanceState.getBundle(SAVE_DIALOG_ACCESS_POINT_STATE);
89             }
90         }
91     }
92 
showWifiDialog(@ullable AccessPointPreference accessPoint)93     public void showWifiDialog(@Nullable AccessPointPreference accessPoint) {
94         removeDialog(WifiSettings.WIFI_DIALOG_ID);
95 
96         if (accessPoint != null) {
97             // Save the access point and edit mode
98             mSelectedAccessPoint = accessPoint.getAccessPoint();
99         } else {
100             // No access point is selected. Clear saved state.
101             mSelectedAccessPoint = null;
102             mAccessPointSavedState = null;
103         }
104 
105         if (usingDetailsFragment(getContext())) {
106             if (mSelectedAccessPoint == null) {
107                 mSelectedAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState);
108             }
109             final Bundle savedState = new Bundle();
110             mSelectedAccessPoint.saveWifiState(savedState);
111 
112             new SubSettingLauncher(getContext())
113                     .setTitleText(mSelectedAccessPoint.getTitle())
114                     .setDestination(WifiNetworkDetailsFragment.class.getName())
115                     .setArguments(savedState)
116                     .setSourceMetricsCategory(getMetricsCategory())
117                     .launch();
118         } else {
119             showDialog(WifiSettings.WIFI_DIALOG_ID);
120         }
121     }
122 
123     @Override
onCreateDialog(int dialogId)124     public Dialog onCreateDialog(int dialogId) {
125         switch (dialogId) {
126             case WifiSettings.WIFI_DIALOG_ID:
127                 // Modify network
128                 if (mSelectedAccessPoint == null) {
129                     // Restore AP from save state
130                     mSelectedAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState);
131                     // Reset the saved access point data
132                     mAccessPointSavedState = null;
133                 }
134                 final WifiDialog dialog = WifiDialog.createModal(
135                         getActivity(), this, mSelectedAccessPoint, WifiConfigUiBase.MODE_VIEW);
136                 dialog.setOnCancelListener(this);
137 
138                 return dialog;
139         }
140         return super.onCreateDialog(dialogId);
141     }
142 
143     @Override
getDialogMetricsCategory(int dialogId)144     public int getDialogMetricsCategory(int dialogId) {
145         switch (dialogId) {
146             case WifiSettings.WIFI_DIALOG_ID:
147                 return SettingsEnums.DIALOG_WIFI_SAVED_AP_EDIT;
148             default:
149                 return 0;
150         }
151     }
152 
153     @Override
onSaveInstanceState(Bundle outState)154     public void onSaveInstanceState(Bundle outState) {
155         super.onSaveInstanceState(outState);
156         // If the dialog is showing (indicated by the existence of mSelectedAccessPoint), then we
157         // save its state.
158         if (mSelectedAccessPoint != null) {
159             mAccessPointSavedState = new Bundle();
160             mSelectedAccessPoint.saveWifiState(mAccessPointSavedState);
161             outState.putBundle(SAVE_DIALOG_ACCESS_POINT_STATE, mAccessPointSavedState);
162         }
163     }
164 
165     @Override
onForget(WifiDialog dialog)166     public void onForget(WifiDialog dialog) {
167         if (mSelectedAccessPoint != null) {
168             if (mSelectedAccessPoint.isPasspointConfig()) {
169                 try {
170                     mWifiManager.removePasspointConfiguration(
171                             mSelectedAccessPoint.getPasspointFqdn());
172                 } catch (RuntimeException e) {
173                     Log.e(TAG, "Failed to remove Passpoint configuration for "
174                             + mSelectedAccessPoint.getConfigName());
175                 }
176                 if (isSubscriptionsFeatureEnabled()) {
177                     use(SubscribedAccessPointsPreferenceController.class)
178                             .postRefreshSubscribedAccessPoints();
179                 } else {
180                     use(SavedAccessPointsPreferenceController.class)
181                             .postRefreshSavedAccessPoints();
182                 }
183             } else {
184                 // both onSuccess/onFailure will call postRefreshSavedAccessPoints
185                 mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId,
186                         use(SavedAccessPointsPreferenceController.class));
187             }
188             mSelectedAccessPoint = null;
189         }
190     }
191 
192     @Override
onCancel(DialogInterface dialog)193     public void onCancel(DialogInterface dialog) {
194         mSelectedAccessPoint = null;
195     }
196 
197     /**
198      * Checks if showing WifiNetworkDetailsFragment when clicking saved network item.
199      */
usingDetailsFragment(Context context)200     public static boolean usingDetailsFragment(Context context) {
201         return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_SAVED_SCREEN);
202     }
203 
isSubscriptionsFeatureEnabled()204     boolean isSubscriptionsFeatureEnabled() {
205         return FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.MOBILE_NETWORK_V2)
206                 && FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2);
207     }
208 }
209