• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.tether;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.net.ConnectivityManager;
24 import android.net.wifi.WifiConfiguration;
25 import android.net.wifi.WifiManager;
26 import android.provider.Settings;
27 import android.support.annotation.VisibleForTesting;
28 import android.support.v7.preference.Preference;
29 import android.support.v7.preference.PreferenceScreen;
30 import android.text.BidiFormatter;
31 
32 import com.android.settings.R;
33 import com.android.settings.Utils;
34 import com.android.settings.core.PreferenceControllerMixin;
35 import com.android.settingslib.core.AbstractPreferenceController;
36 import com.android.settingslib.core.lifecycle.Lifecycle;
37 import com.android.settingslib.core.lifecycle.LifecycleObserver;
38 import com.android.settingslib.core.lifecycle.events.OnStart;
39 import com.android.settingslib.core.lifecycle.events.OnStop;
40 
41 public class WifiTetherPreferenceController extends AbstractPreferenceController
42         implements PreferenceControllerMixin, LifecycleObserver, OnStart, OnStop {
43 
44     private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
45     private static final IntentFilter AIRPLANE_INTENT_FILTER = new IntentFilter(
46             Intent.ACTION_AIRPLANE_MODE_CHANGED);
47     private static final int ID_NULL = -1;
48 
49     private final ConnectivityManager mConnectivityManager;
50     private final String[] mWifiRegexs;
51     private final WifiManager mWifiManager;
52     private final Lifecycle mLifecycle;
53     private int mSoftApState;
54     @VisibleForTesting
55     Preference mPreference;
56     @VisibleForTesting
57     WifiTetherSoftApManager mWifiTetherSoftApManager;
58 
WifiTetherPreferenceController(Context context, Lifecycle lifecycle)59     public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
60         this(context, lifecycle, true /* initSoftApManager */);
61     }
62 
63     @VisibleForTesting
WifiTetherPreferenceController(Context context, Lifecycle lifecycle, boolean initSoftApManager)64     WifiTetherPreferenceController(Context context, Lifecycle lifecycle,
65             boolean initSoftApManager) {
66         super(context);
67         mConnectivityManager =
68                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
69         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
70         mWifiRegexs = mConnectivityManager.getTetherableWifiRegexs();
71         mLifecycle = lifecycle;
72         if (lifecycle != null) {
73             lifecycle.addObserver(this);
74         }
75         if (initSoftApManager) {
76             initWifiTetherSoftApManager();
77         }
78     }
79 
80     @Override
isAvailable()81     public boolean isAvailable() {
82         return mWifiRegexs != null
83                 && mWifiRegexs.length != 0
84                 && !Utils.isMonkeyRunning();
85     }
86 
87     @Override
displayPreference(PreferenceScreen screen)88     public void displayPreference(PreferenceScreen screen) {
89         super.displayPreference(screen);
90         mPreference = screen.findPreference(WIFI_TETHER_SETTINGS);
91         if (mPreference == null) {
92             // unavailable
93             return;
94         }
95     }
96 
97     @Override
getPreferenceKey()98     public String getPreferenceKey() {
99         return WIFI_TETHER_SETTINGS;
100     }
101 
102     @Override
onStart()103     public void onStart() {
104         if (mPreference != null) {
105             mContext.registerReceiver(mReceiver, AIRPLANE_INTENT_FILTER);
106             clearSummaryForAirplaneMode();
107             if (mWifiTetherSoftApManager != null) {
108                 mWifiTetherSoftApManager.registerSoftApCallback();
109             }
110         }
111     }
112 
113     @Override
onStop()114     public void onStop() {
115         if (mPreference != null) {
116             mContext.unregisterReceiver(mReceiver);
117             if (mWifiTetherSoftApManager != null) {
118                 mWifiTetherSoftApManager.unRegisterSoftApCallback();
119             }
120         }
121     }
122 
123     @VisibleForTesting
initWifiTetherSoftApManager()124     void initWifiTetherSoftApManager() {
125         // This manager only handles the number of connected devices, other parts are handled by
126         // normal BroadcastReceiver in this controller
127         mWifiTetherSoftApManager = new WifiTetherSoftApManager(mWifiManager,
128                 new WifiTetherSoftApManager.WifiTetherSoftApCallback() {
129                     @Override
130                     public void onStateChanged(int state, int failureReason) {
131                         mSoftApState = state;
132                         handleWifiApStateChanged(state, failureReason);
133                     }
134 
135                     @Override
136                     public void onNumClientsChanged(int numClients) {
137                         if (mPreference != null
138                                 && mSoftApState == WifiManager.WIFI_AP_STATE_ENABLED) {
139                             // Only show the number of clients when state is on
140                             mPreference.setSummary(mContext.getResources().getQuantityString(
141                                     R.plurals.wifi_tether_connected_summary, numClients,
142                                     numClients));
143                         }
144                     }
145                 });
146     }
147 
148     //
149     // Everything below is copied from WifiApEnabler
150     //
151     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
152         @Override
153         public void onReceive(Context context, Intent intent) {
154             String action = intent.getAction();
155             if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
156                 clearSummaryForAirplaneMode(R.string.wifi_hotspot_off_subtext);
157             }
158         }
159     };
160 
161     @VisibleForTesting
handleWifiApStateChanged(int state, int reason)162     void handleWifiApStateChanged(int state, int reason) {
163         switch (state) {
164             case WifiManager.WIFI_AP_STATE_ENABLING:
165                 mPreference.setSummary(R.string.wifi_tether_starting);
166                 break;
167             case WifiManager.WIFI_AP_STATE_ENABLED:
168                 WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
169                 updateConfigSummary(wifiConfig);
170                 break;
171             case WifiManager.WIFI_AP_STATE_DISABLING:
172                 mPreference.setSummary(R.string.wifi_tether_stopping);
173                 break;
174             case WifiManager.WIFI_AP_STATE_DISABLED:
175                 mPreference.setSummary(R.string.wifi_hotspot_off_subtext);
176                 clearSummaryForAirplaneMode();
177                 break;
178             default:
179                 if (reason == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
180                     mPreference.setSummary(R.string.wifi_sap_no_channel_error);
181                 } else {
182                     mPreference.setSummary(R.string.wifi_error);
183                 }
184                 clearSummaryForAirplaneMode();
185         }
186     }
187 
updateConfigSummary(WifiConfiguration wifiConfig)188     private void updateConfigSummary(WifiConfiguration wifiConfig) {
189         final String s = mContext.getString(
190                 com.android.internal.R.string.wifi_tether_configure_ssid_default);
191 
192         mPreference.setSummary(mContext.getString(R.string.wifi_tether_enabled_subtext,
193                 BidiFormatter.getInstance().unicodeWrap(
194                         (wifiConfig == null) ? s : wifiConfig.SSID)));
195     }
196 
clearSummaryForAirplaneMode()197     private void clearSummaryForAirplaneMode() {
198         clearSummaryForAirplaneMode(ID_NULL);
199     }
200 
clearSummaryForAirplaneMode(int defaultId)201     private void clearSummaryForAirplaneMode(int defaultId) {
202         boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
203                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
204         if (isAirplaneMode) {
205             mPreference.setSummary(R.string.wifi_tether_disabled_by_airplane);
206         } else if (defaultId != ID_NULL){
207             mPreference.setSummary(defaultId);
208         }
209     }
210     //
211     // Everything above is copied from WifiApEnabler
212     //
213 }
214