1 /* 2 * Copyright (C) 2021 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.uwb; 18 19 import static androidx.lifecycle.Lifecycle.Event.ON_START; 20 import static androidx.lifecycle.Lifecycle.Event.ON_STOP; 21 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.pm.PackageManager; 27 import android.os.Handler; 28 import android.provider.Settings; 29 import android.uwb.UwbManager; 30 import android.uwb.UwbManager.AdapterStateCallback; 31 32 import androidx.lifecycle.LifecycleObserver; 33 import androidx.lifecycle.OnLifecycleEvent; 34 import androidx.preference.Preference; 35 import androidx.preference.PreferenceScreen; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.settings.R; 39 import com.android.settings.core.TogglePreferenceController; 40 41 import java.util.concurrent.Executor; 42 import java.util.concurrent.Executors; 43 44 /** Controller for "UWB" toggle. */ 45 public class UwbPreferenceController extends TogglePreferenceController implements 46 AdapterStateCallback, LifecycleObserver { 47 @VisibleForTesting 48 static final String KEY_UWB_SETTINGS = "uwb_settings"; 49 @VisibleForTesting 50 UwbManager mUwbManager; 51 @VisibleForTesting 52 boolean mAirplaneModeOn; 53 @VisibleForTesting 54 private final BroadcastReceiver mAirplaneModeChangedReceiver; 55 private final Executor mExecutor; 56 private final Handler mHandler; 57 private Preference mPreference; 58 UwbPreferenceController(Context context, String key)59 public UwbPreferenceController(Context context, String key) { 60 super(context, key); 61 mExecutor = Executors.newSingleThreadExecutor(); 62 mHandler = new Handler(context.getMainLooper()); 63 if (isUwbSupportedOnDevice()) { 64 mUwbManager = context.getSystemService(UwbManager.class); 65 } 66 mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(), 67 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 68 mAirplaneModeChangedReceiver = new BroadcastReceiver() { 69 @Override 70 public void onReceive(Context context, Intent intent) { 71 mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(), 72 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 73 updateState(mPreference); 74 } 75 }; 76 } 77 78 @VisibleForTesting isUwbSupportedOnDevice()79 boolean isUwbSupportedOnDevice() { 80 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB); 81 } 82 83 @Override getAvailabilityStatus()84 public int getAvailabilityStatus() { 85 if (!isUwbSupportedOnDevice()) { 86 return UNSUPPORTED_ON_DEVICE; 87 } else if (mAirplaneModeOn) { 88 return DISABLED_DEPENDENT_SETTING; 89 } else { 90 return AVAILABLE; 91 } 92 } 93 94 @Override displayPreference(PreferenceScreen screen)95 public void displayPreference(PreferenceScreen screen) { 96 super.displayPreference(screen); 97 mPreference = screen.findPreference(getPreferenceKey()); 98 } 99 100 @Override isChecked()101 public boolean isChecked() { 102 int state = mUwbManager.getAdapterState(); 103 return state == STATE_ENABLED_ACTIVE || state == STATE_ENABLED_INACTIVE; 104 } 105 106 @Override setChecked(boolean isChecked)107 public boolean setChecked(boolean isChecked) { 108 mAirplaneModeOn = Settings.Global.getInt(mContext.getContentResolver(), 109 Settings.Global.AIRPLANE_MODE_ON, 0) == 1; 110 if (isUwbSupportedOnDevice()) { 111 if (mAirplaneModeOn) { 112 mUwbManager.setUwbEnabled(false); 113 } else { 114 mUwbManager.setUwbEnabled(isChecked); 115 } 116 } 117 return true; 118 } 119 120 @Override onStateChanged(int state, int reason)121 public void onStateChanged(int state, int reason) { 122 Runnable runnable = () -> updateState(mPreference); 123 mHandler.post(runnable); 124 } 125 126 /** Called when activity starts being displayed to user. */ 127 @OnLifecycleEvent(ON_START) onStart()128 public void onStart() { 129 if (isUwbSupportedOnDevice()) { 130 mUwbManager.registerAdapterStateCallback(mExecutor, this); 131 } 132 if (mAirplaneModeChangedReceiver != null) { 133 mContext.registerReceiver(mAirplaneModeChangedReceiver, 134 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); 135 } 136 refreshSummary(mPreference); 137 } 138 139 /** Called when activity stops being displayed to user. */ 140 @OnLifecycleEvent(ON_STOP) onStop()141 public void onStop() { 142 if (isUwbSupportedOnDevice()) { 143 mUwbManager.unregisterAdapterStateCallback(this); 144 } 145 if (mAirplaneModeChangedReceiver != null) { 146 mContext.unregisterReceiver(mAirplaneModeChangedReceiver); 147 } 148 } 149 150 @Override updateState(Preference preference)151 public void updateState(Preference preference) { 152 super.updateState(preference); 153 preference.setEnabled(!mAirplaneModeOn); 154 refreshSummary(preference); 155 } 156 157 @Override getSummary()158 public CharSequence getSummary() { 159 if (mAirplaneModeOn) { 160 return mContext.getResources().getString(R.string.uwb_settings_summary_airplane_mode); 161 } else { 162 return mContext.getResources().getString(R.string.uwb_settings_summary); 163 } 164 } 165 166 @Override getSliceHighlightMenuRes()167 public int getSliceHighlightMenuRes() { 168 return R.string.menu_key_connected_devices; 169 } 170 } 171 172