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.os.Handler;
23 import android.os.HandlerExecutor;
24 import android.os.Looper;
25 
26 import com.android.car.settings.R;
27 import com.android.car.settings.common.FragmentController;
28 import com.android.car.settings.common.PreferenceController;
29 import com.android.car.ui.preference.CarUiTwoActionSwitchPreference;
30 
31 /**
32  * Controls the availability of wifi tethering preference based on whether tethering is supported
33  */
34 public class WifiTetherPreferenceController extends
35         PreferenceController<CarUiTwoActionSwitchPreference>
36         implements WifiTetheringHandler.WifiTetheringAvailabilityListener {
37 
38     private final TetheringManager mTetheringManager =
39             getContext().getSystemService(TetheringManager.class);
40     private final Handler mHandler;
41     private WifiTetheringHandler mWifiTetheringHandler;
42     private volatile boolean mIsTetheringSupported;
43     private volatile boolean mReceivedTetheringEventCallback = false;
44 
45     private TetheringManager.TetheringEventCallback mTetheringCallback =
46             new TetheringManager.TetheringEventCallback() {
47                 @Override
48                 public void onTetheringSupported(boolean supported) {
49                     mReceivedTetheringEventCallback = true;
50                     if (mIsTetheringSupported != supported) {
51                         mIsTetheringSupported = supported;
52                     }
53                     refreshUi();
54                 }
55             };
56 
WifiTetherPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)57     public WifiTetherPreferenceController(Context context, String preferenceKey,
58             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
59         super(context, preferenceKey, fragmentController, uxRestrictions);
60         mHandler = new Handler(Looper.getMainLooper());
61         mWifiTetheringHandler = new WifiTetheringHandler(context,
62                 fragmentController.getSettingsLifecycle(), this);
63     }
64 
65     @Override
getPreferenceType()66     protected Class<CarUiTwoActionSwitchPreference> getPreferenceType() {
67         return CarUiTwoActionSwitchPreference.class;
68     }
69 
70     @Override
onCreateInternal()71     protected void onCreateInternal() {
72         getPreference().setOnSecondaryActionClickListener(isChecked -> {
73             mWifiTetheringHandler.updateWifiTetheringState(isChecked);
74         });
75         setClickableWhileDisabled(getPreference(), /* clickable= */ true, p -> {
76             WifiUtil.runClickableWhileDisabled(getContext(), getFragmentController());
77         });
78     }
79 
80     @Override
onStartInternal()81     protected void onStartInternal() {
82         mTetheringManager.registerTetheringEventCallback(
83                 new HandlerExecutor(mHandler), mTetheringCallback);
84         boolean tetheringEnabled = mWifiTetheringHandler.isWifiTetheringEnabled();
85         updateSwitchPreference(tetheringEnabled);
86         mWifiTetheringHandler.onStartInternal();
87     }
88 
89     @Override
onStopInternal()90     protected void onStopInternal() {
91         mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback);
92         mWifiTetheringHandler.onStopInternal();
93     }
94 
95     @Override
getAvailabilityStatus()96     protected int getAvailabilityStatus() {
97         if (!mReceivedTetheringEventCallback) {
98             return AVAILABLE_FOR_VIEWING;
99         }
100         if (!mIsTetheringSupported) {
101             return UNSUPPORTED_ON_DEVICE;
102         }
103         if (WifiUtil.isConfigWifiRestrictedByUm(getContext())
104                 || WifiUtil.isConfigWifiRestrictedByDpm(getContext())) {
105             return AVAILABLE_FOR_VIEWING;
106         }
107         return AVAILABLE;
108     }
109 
110     @Override
onWifiTetheringAvailable()111     public void onWifiTetheringAvailable() {
112         updateSwitchPreference(true);
113     }
114 
115     @Override
onWifiTetheringUnavailable()116     public void onWifiTetheringUnavailable() {
117         updateSwitchPreference(false);
118     }
119 
120     @Override
enablePreference()121     public void enablePreference() {
122         getPreference().setSecondaryActionEnabled(true);
123     }
124 
125     @Override
disablePreference()126     public void disablePreference() {
127         getPreference().setSecondaryActionEnabled(false);
128     }
129 
updateSwitchPreference(boolean switchOn)130     private void updateSwitchPreference(boolean switchOn) {
131         getPreference().setSummary(switchOn ? R.string.car_ui_preference_switch_on
132                 : R.string.car_ui_preference_switch_off);
133         getPreference().setSecondaryActionChecked(switchOn);
134     }
135 }
136