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