blob: 26f93a4b5d4cd4efb7ac2a3050c006650205bfee [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.nfc;
import static com.google.common.truth.Truth.assertThat;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.Executor;
@RunWith(AndroidJUnit4.class)
public final class NfcStateTest {
private static final String TAG = NfcStateTest.class.getSimpleName();
private static final int MAX_TIMEOUT_MS = 20000;
private Context mContext;
private NfcAdapter mNfcAdapter;
private BroadcastReceiver mAdapterStateChangedReceiver;
private int mState;
private boolean mIsAlwaysOnEnabled;
private boolean mNfcSupported;
private ControllerAlwaysOnListener mListener;
class SynchronousExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
mAdapterStateChangedReceiver = new AdapterStateChangedReceiver();
mContext.registerReceiver(mAdapterStateChangedReceiver, filter);
PackageManager pm = mContext.getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_ANY)) {
mNfcSupported = false;
return;
}
mNfcSupported = true;
mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext);
Assert.assertNotNull(mNfcAdapter);
if (mNfcAdapter.isEnabled()) {
mState = NfcAdapter.STATE_ON;
} else {
mState = NfcAdapter.STATE_OFF;
}
if (mNfcAdapter.isControllerAlwaysOnSupported()) {
mListener = new AlwaysOnStateListener();
mNfcAdapter.registerControllerAlwaysOnListener(new SynchronousExecutor(),
mListener);
mIsAlwaysOnEnabled = mNfcAdapter.isControllerAlwaysOn();
}
}
@After
public void tearDown() throws Exception {
mContext.unregisterReceiver(mAdapterStateChangedReceiver);
if (mNfcAdapter.isControllerAlwaysOnSupported()) {
mNfcAdapter.unregisterControllerAlwaysOnListener(mListener);
}
}
@Test
public void testSetControllerAlwaysOnTrueFromFalseWhenDisabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
@Test
public void testSetControllerAlwaysOnFalseFromTrueWhenDisabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
@Test
public void testSetControllerAlwaysOnFalseFromFalseWhenDisabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
@Test
public void testSetControllerAlwaysOnTrueFromTrueWhenDisabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
@Test
public void testSetControllerAlwaysOnTrueFromFalseWhenEnabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
@Test
public void testSetAlwaysOnFalseFromTrueWhenEnabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
@Test
public void testSetControllerAlwaysOnFalseFromFalseWhenEnabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.setControllerAlwaysOn(false);
wait_for_always_on(false);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(false);
}
@Test
public void testSetControllerAlwaysOnTrueFromTrueWhenEnabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
@Test
public void testEnableWhenSetControllerAlwaysOnTrueAndDisabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(false);
}
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
assertThat(mState).isEqualTo(NfcAdapter.STATE_ON);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(true);
}
@Test
public void testDisableWhenSetControllerAlwaysOnTrueAndEnabled() {
if (!mNfcSupported || !mNfcAdapter.isControllerAlwaysOnSupported()) return;
if (!mNfcAdapter.isControllerAlwaysOn()) {
mNfcAdapter.setControllerAlwaysOn(true);
wait_for_always_on(true);
assertThat(mNfcAdapter.isControllerAlwaysOn()).isEqualTo(true);
}
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(true);
}
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
assertThat(mState).isEqualTo(NfcAdapter.STATE_OFF);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(false);
}
@Test
public void testDisableWhenEnabled() {
if (!mNfcSupported) return;
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
assertThat(mState).isEqualTo(NfcAdapter.STATE_OFF);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(false);
}
@Test
public void testEnableWhenDisabled() {
if (!mNfcSupported) return;
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
assertThat(mState).isEqualTo(NfcAdapter.STATE_ON);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(true);
}
@Test
public void testDisableWhenDisabled() {
if (!mNfcSupported) return;
if (mNfcAdapter.isEnabled()) {
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
}
mNfcAdapter.disable();
wait_for_state(NfcAdapter.STATE_OFF);
assertThat(mState).isEqualTo(NfcAdapter.STATE_OFF);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(false);
}
@Test
public void testEnableWhenEnabled() {
if (!mNfcSupported) return;
if (!mNfcAdapter.isEnabled()) {
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
}
mNfcAdapter.enable();
wait_for_state(NfcAdapter.STATE_ON);
assertThat(mState).isEqualTo(NfcAdapter.STATE_ON);
assertThat(mNfcAdapter.isEnabled()).isEqualTo(true);
}
private class AdapterStateChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(intent.getAction())) {
mState = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
NfcAdapter.STATE_OFF);
Log.i(TAG, "mState = " + mState);
}
}
}
private class AlwaysOnStateListener implements ControllerAlwaysOnListener {
@Override
public void onControllerAlwaysOnChanged(boolean isEnabled) {
Log.i(TAG, "onControllerAlwaysOnChanged, mIsAlwaysOnEnabled = " + isEnabled);
mIsAlwaysOnEnabled = isEnabled;
}
}
private void wait_for_state(int targetState) {
int duration = 100;
for (int i = 0; i < MAX_TIMEOUT_MS / duration; i++) {
msleep(duration);
if (mState == targetState) break;
}
}
private void wait_for_always_on(boolean isEnabled) {
int duration = 1000;
for (int i = 0; i < MAX_TIMEOUT_MS / duration; i++) {
msleep(duration);
if (isEnabled == mIsAlwaysOnEnabled) break;
}
}
private void msleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
}
}