• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.android.settings.nfc;
17 
18 import android.content.BroadcastReceiver;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import android.net.Uri;
23 import android.nfc.NfcAdapter;
24 import android.provider.Settings;
25 import android.util.Log;
26 import android.widget.Switch;
27 
28 import androidx.preference.PreferenceScreen;
29 
30 import com.android.settings.R;
31 import com.android.settings.core.TogglePreferenceController;
32 import com.android.settings.slices.SliceBackgroundWorker;
33 import com.android.settingslib.core.lifecycle.LifecycleObserver;
34 import com.android.settingslib.core.lifecycle.events.OnPause;
35 import com.android.settingslib.core.lifecycle.events.OnResume;
36 import com.android.settingslib.widget.MainSwitchPreference;
37 import com.android.settingslib.widget.OnMainSwitchChangeListener;
38 
39 import java.io.IOException;
40 
41 public class NfcPreferenceController extends TogglePreferenceController
42         implements LifecycleObserver, OnResume, OnPause, OnMainSwitchChangeListener {
43 
44     public static final String KEY_TOGGLE_NFC = "toggle_nfc";
45     private final NfcAdapter mNfcAdapter;
46     private NfcEnabler mNfcEnabler;
47     private MainSwitchPreference mPreference;
48 
NfcPreferenceController(Context context, String key)49     public NfcPreferenceController(Context context, String key) {
50         super(context, key);
51         mNfcAdapter = NfcAdapter.getDefaultAdapter(context);
52     }
53 
54     @Override
displayPreference(PreferenceScreen screen)55     public void displayPreference(PreferenceScreen screen) {
56         super.displayPreference(screen);
57         if (!isAvailable()) {
58             mNfcEnabler = null;
59             return;
60         }
61 
62         mPreference = screen.findPreference(getPreferenceKey());
63         mPreference.addOnSwitchChangeListener(this);
64         mNfcEnabler = new NfcEnabler(mContext, mPreference);
65     }
66 
67     @Override
onSwitchChanged(Switch switchView, boolean isChecked)68     public void onSwitchChanged(Switch switchView, boolean isChecked) {
69         if (isChecked != mNfcAdapter.isEnabled()) {
70             setChecked(isChecked);
71         }
72     }
73 
74     @Override
isChecked()75     public boolean isChecked() {
76         return mNfcAdapter.isEnabled();
77     }
78 
79     @Override
setChecked(boolean isChecked)80     public boolean setChecked(boolean isChecked) {
81         if (isChecked) {
82             mNfcAdapter.enable();
83         } else {
84             mNfcAdapter.disable();
85         }
86         return true;
87     }
88 
89     @Override
90     @AvailabilityStatus
getAvailabilityStatus()91     public int getAvailabilityStatus() {
92         return mNfcAdapter != null
93                 ? AVAILABLE
94                 : UNSUPPORTED_ON_DEVICE;
95     }
96 
97     @Override
hasAsyncUpdate()98     public boolean hasAsyncUpdate() {
99         return true;
100     }
101 
102     @Override
isPublicSlice()103     public boolean isPublicSlice() {
104         return true;
105     }
106 
107     @Override
getSliceHighlightMenuRes()108     public int getSliceHighlightMenuRes() {
109         return R.string.menu_key_connected_devices;
110     }
111 
112     @Override
getBackgroundWorkerClass()113     public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
114         return NfcSliceWorker.class;
115     }
116 
117     @Override
onResume()118     public void onResume() {
119         if (mNfcEnabler != null) {
120             mNfcEnabler.resume();
121         }
122     }
123 
124     @Override
onPause()125     public void onPause() {
126         if (mNfcEnabler != null) {
127             mNfcEnabler.pause();
128         }
129     }
130 
shouldTurnOffNFCInAirplaneMode(Context context)131     public static boolean shouldTurnOffNFCInAirplaneMode(Context context) {
132         final String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
133                 Settings.Global.AIRPLANE_MODE_RADIOS);
134         return airplaneModeRadios != null && airplaneModeRadios.contains(Settings.Global.RADIO_NFC);
135     }
136 
isToggleableInAirplaneMode(Context context)137     public static boolean isToggleableInAirplaneMode(Context context) {
138         final String toggleable = Settings.Global.getString(context.getContentResolver(),
139                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
140         return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
141     }
142 
143     /**
144      * Listener for background changes to NFC.
145      *
146      * <p>
147      * Listen to broadcasts from {@link NfcAdapter}. The worker will call notify changed on the
148      * NFC Slice only when the following extras are present in the broadcast:
149      * <ul>
150      * <li>{@link NfcAdapter#STATE_ON}</li>
151      * <li>{@link NfcAdapter#STATE_OFF}</li>
152      * </ul>
153      */
154     public static class NfcSliceWorker extends SliceBackgroundWorker<Void> {
155 
156         private static final String TAG = "NfcSliceWorker";
157 
158         private static final IntentFilter NFC_FILTER =
159                 new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
160 
161         private NfcUpdateReceiver mUpdateObserver;
162 
NfcSliceWorker(Context context, Uri uri)163         public NfcSliceWorker(Context context, Uri uri) {
164             super(context, uri);
165             mUpdateObserver = new NfcUpdateReceiver(this);
166         }
167 
168         @Override
onSlicePinned()169         protected void onSlicePinned() {
170             getContext().registerReceiver(mUpdateObserver, NFC_FILTER);
171         }
172 
173         @Override
onSliceUnpinned()174         protected void onSliceUnpinned() {
175             getContext().unregisterReceiver(mUpdateObserver);
176         }
177 
178         @Override
close()179         public void close() throws IOException {
180             mUpdateObserver = null;
181         }
182 
updateSlice()183         public void updateSlice() {
184             notifySliceChange();
185         }
186 
187         public class NfcUpdateReceiver extends BroadcastReceiver {
188 
189             private final int NO_EXTRA = -1;
190 
191             private final NfcSliceWorker mSliceBackgroundWorker;
192 
NfcUpdateReceiver(NfcSliceWorker sliceWorker)193             public NfcUpdateReceiver(NfcSliceWorker sliceWorker) {
194                 mSliceBackgroundWorker = sliceWorker;
195             }
196 
197             @Override
onReceive(Context context, Intent intent)198             public void onReceive(Context context, Intent intent) {
199                 final int nfcStateExtra = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
200                         NO_EXTRA);
201 
202                 // Do nothing if state change is empty, or an intermediate step.
203                 if ((nfcStateExtra == NO_EXTRA)
204                         || (nfcStateExtra == NfcAdapter.STATE_TURNING_ON)
205                         || (nfcStateExtra == NfcAdapter.STATE_TURNING_OFF)) {
206                     Log.d(TAG, "Transitional update, dropping broadcast");
207                     return;
208                 }
209 
210                 Log.d(TAG, "Nfc broadcast received, updating Slice.");
211                 mSliceBackgroundWorker.updateSlice();
212             }
213         }
214     }
215 }
216