1 2 /* 3 * Copyright (C) 2024 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package com.android.nfc.utils; 18 19 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.pm.PackageManager; 25 import android.nfc.NfcAdapter; 26 import android.os.RemoteException; 27 import android.util.Log; 28 29 import androidx.test.platform.app.InstrumentationRegistry; 30 import androidx.test.uiautomator.UiDevice; 31 32 import com.google.android.mobly.snippet.Snippet; 33 import com.google.android.mobly.snippet.event.SnippetEvent; 34 import com.google.android.mobly.snippet.rpc.Rpc; 35 36 import java.util.concurrent.CountDownLatch; 37 import java.util.concurrent.TimeUnit; 38 39 public abstract class NfcSnippet implements Snippet { 40 protected static final String TAG = "NfcSnippet"; 41 protected final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); 42 private final UiDevice mDevice = 43 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 44 45 @Rpc(description = "Checks if NFC supported on device") isNfcSupported()46 public boolean isNfcSupported() { 47 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC); 48 } 49 50 @Rpc(description = "Checks if NFC HCE (host-card emulation) supported on device") isNfcHceSupported()51 public boolean isNfcHceSupported() { 52 return mContext.getPackageManager() 53 .hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION); 54 } 55 56 /** Turns device screen off */ 57 @Rpc(description = "Turns device screen off") turnScreenOff()58 public void turnScreenOff() { 59 try { 60 mDevice.sleep(); 61 } catch (RemoteException e) { 62 Log.e(TAG, "RemoteException", e); 63 } 64 } 65 66 /** Turns device screen on */ 67 @Rpc(description = "Turns device screen on") turnScreenOn()68 public void turnScreenOn() { 69 try { 70 mDevice.wakeUp(); 71 } catch (RemoteException e) { 72 Log.e(TAG, "RemoteException", e); 73 } 74 } 75 76 /** Press device menu button to return device to home screen between tests. */ 77 @Rpc(description = "Press menu button") pressMenu()78 public void pressMenu() { 79 mDevice.pressMenu(); 80 } 81 82 @Rpc(description = "Log info level message to device logcat") logInfo(String message)83 public void logInfo(String message) { 84 Log.i(TAG, message); 85 } 86 87 /** Toggle NFC state */ 88 @Rpc(description = "Blocking call to toggle NFC state") setNfcState(boolean enable)89 public void setNfcState(boolean enable) throws InterruptedException { 90 NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(mContext); 91 int expectedState = enable ? NfcAdapter.STATE_ON : NfcAdapter.STATE_OFF; 92 if (nfcAdapter.getAdapterState() == expectedState) { 93 Log.i(TAG, "toggleNfc: Already in expected state: " + expectedState); 94 return; 95 } 96 CountDownLatch countDownLatch = new CountDownLatch(1); 97 IntentFilter intentFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED); 98 final BroadcastReceiver receiver = new BroadcastReceiver() { 99 @Override 100 public void onReceive(Context context, Intent intent) { 101 if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(intent.getAction())) { 102 int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, 103 NfcAdapter.STATE_OFF); 104 if (expectedState == state) countDownLatch.countDown(); 105 } 106 } 107 }; 108 mContext.registerReceiver(receiver, intentFilter); 109 if (enable) { 110 nfcAdapter.enable(); 111 } else { 112 nfcAdapter.disable(); 113 } 114 if (!countDownLatch.await(5, TimeUnit.SECONDS)) { 115 throw new IllegalStateException("Waiting for NFC state change failed"); 116 } 117 } 118 119 /** Creates a SnippetBroadcastReceiver that listens for when the specified action is received */ registerSnippetBroadcastReceiver( String callbackId, String eventName, String action)120 protected void registerSnippetBroadcastReceiver( 121 String callbackId, String eventName, String action) { 122 IntentFilter filter = new IntentFilter(action); 123 mContext.registerReceiver( 124 new SnippetBroadcastReceiver( 125 mContext, new SnippetEvent(callbackId, eventName), action), 126 filter, 127 Context.RECEIVER_EXPORTED); 128 } 129 } 130