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