• 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 
17 package com.android.car.settings.wifi;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.net.TetheringManager;
22 import android.net.wifi.SoftApConfiguration;
23 import android.os.Handler;
24 import android.os.HandlerExecutor;
25 import android.os.Looper;
26 
27 import androidx.annotation.VisibleForTesting;
28 
29 import com.android.car.settings.common.FragmentController;
30 import com.android.car.settings.common.PreferenceController;
31 import com.android.car.ui.preference.CarUiTwoActionSwitchPreference;
32 
33 /**
34  * Controls the availability of wifi tethering preference based on whether tethering is supported
35  */
36 public class WifiTetherPreferenceController extends
37         PreferenceController<CarUiTwoActionSwitchPreference>
38         implements WifiTetheringHandler.WifiTetheringAvailabilityListener {
39 
40     private final TetheringManager mTetheringManager;
41     private final CarWifiManager mCarWifiManager;
42     private final Handler mHandler;
43     private final WifiTetheringHandler mWifiTetheringHandler;
44     private int mConnectedDevicesCount;
45     private volatile boolean mIsTetheringSupported;
46     private volatile boolean mReceivedTetheringEventCallback = false;
47 
48     private final TetheringManager.TetheringEventCallback mTetheringCallback =
49             new TetheringManager.TetheringEventCallback() {
50                 @Override
51                 public void onTetheringSupported(boolean supported) {
52                     mReceivedTetheringEventCallback = true;
53                     if (mIsTetheringSupported != supported) {
54                         mIsTetheringSupported = supported;
55                     }
56                     refreshUi();
57                 }
58             };
59 
WifiTetherPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)60     public WifiTetherPreferenceController(Context context, String preferenceKey,
61             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
62         this(context, preferenceKey, fragmentController, uxRestrictions,
63                 new CarWifiManager(context, fragmentController.getSettingsLifecycle()),
64                 context.getSystemService(TetheringManager.class));
65     }
66 
67     @VisibleForTesting
WifiTetherPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, CarWifiManager carWifiManager, TetheringManager tetheringManager)68     WifiTetherPreferenceController(Context context, String preferenceKey,
69             FragmentController fragmentController, CarUxRestrictions uxRestrictions,
70             CarWifiManager carWifiManager, TetheringManager tetheringManager) {
71         super(context, preferenceKey, fragmentController, uxRestrictions);
72         mCarWifiManager = carWifiManager;
73         mTetheringManager = tetheringManager;
74         mHandler = new Handler(Looper.getMainLooper());
75         mWifiTetheringHandler = new WifiTetheringHandler(context, mCarWifiManager,
76                 mTetheringManager, this, /* monitorRestarts= */ true);
77     }
78 
79     @Override
getPreferenceType()80     protected Class<CarUiTwoActionSwitchPreference> getPreferenceType() {
81         return CarUiTwoActionSwitchPreference.class;
82     }
83 
84     @Override
onCreateInternal()85     protected void onCreateInternal() {
86         getPreference().setOnSecondaryActionClickListener(isChecked -> {
87             mWifiTetheringHandler.updateWifiTetheringState(isChecked);
88         });
89         setClickableWhileDisabled(getPreference(), /* clickable= */ true, p -> {
90             WifiUtil.runClickableWhileDisabled(getContext(), getFragmentController());
91         });
92     }
93 
94     @Override
onStartInternal()95     protected void onStartInternal() {
96         mTetheringManager.registerTetheringEventCallback(
97                 new HandlerExecutor(mHandler), mTetheringCallback);
98         boolean tetheringEnabled = mWifiTetheringHandler.isWifiTetheringEnabled();
99         updateSwitchPreference(tetheringEnabled);
100         mWifiTetheringHandler.onStartInternal();
101     }
102 
103     @Override
onStopInternal()104     protected void onStopInternal() {
105         mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback);
106         mWifiTetheringHandler.onStopInternal();
107     }
108 
109     @Override
getDefaultAvailabilityStatus()110     protected int getDefaultAvailabilityStatus() {
111         if (!mReceivedTetheringEventCallback) {
112             return AVAILABLE_FOR_VIEWING;
113         }
114         if (!mIsTetheringSupported) {
115             return UNSUPPORTED_ON_DEVICE;
116         }
117         if (WifiUtil.isConfigWifiRestrictedByUm(getContext())
118                 || WifiUtil.isConfigWifiRestrictedByDpm(getContext())) {
119             return AVAILABLE_FOR_VIEWING;
120         }
121         return AVAILABLE;
122     }
123 
124     @Override
onWifiTetheringAvailable()125     public void onWifiTetheringAvailable() {
126         updateSwitchPreference(true);
127     }
128 
129     @Override
onWifiTetheringUnavailable()130     public void onWifiTetheringUnavailable() {
131         updateSwitchPreference(false);
132     }
133 
134     @Override
onConnectedClientsChanged(int clientCount)135     public void onConnectedClientsChanged(int clientCount) {
136         mConnectedDevicesCount = clientCount;
137         updateSummary(mWifiTetheringHandler.isWifiTetheringEnabled());
138     }
139 
140     @Override
enablePreference()141     public void enablePreference() {
142         getPreference().setSecondaryActionEnabled(true);
143     }
144 
145     @Override
disablePreference()146     public void disablePreference() {
147         getPreference().setSecondaryActionEnabled(false);
148     }
149 
updateSwitchPreference(boolean switchOn)150     private void updateSwitchPreference(boolean switchOn) {
151         updateSummary(switchOn);
152         getPreference().setSecondaryActionChecked(switchOn);
153     }
154 
updateSummary(boolean hotspotEnabled)155     private void updateSummary(boolean hotspotEnabled) {
156         SoftApConfiguration config = mCarWifiManager.getSoftApConfig();
157         if (config != null) {
158             String subtitle = WifiTetherUtil.getHotspotSubtitle(getContext(),
159                     config, hotspotEnabled, mConnectedDevicesCount);
160             getPreference().setSummary(subtitle);
161         }
162     }
163 }
164