1 package com.android.cts.verifier.nfc.hce; 2 3 import static android.content.Context.RECEIVER_EXPORTED; 4 5 import android.annotation.TargetApi; 6 import android.app.Activity; 7 import android.app.AlertDialog; 8 import android.app.ProgressDialog; 9 import android.content.BroadcastReceiver; 10 import android.content.ComponentName; 11 import android.content.Context; 12 import android.content.DialogInterface; 13 import android.content.Intent; 14 import android.content.IntentFilter; 15 import android.nfc.NfcAdapter; 16 import android.nfc.cardemulation.CardEmulation; 17 import android.os.AsyncTask; 18 import android.os.Bundle; 19 import android.os.UserHandle; 20 import android.util.Log; 21 22 import com.android.cts.verifier.PassFailButtons; 23 import com.android.cts.verifier.R; 24 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.List; 28 29 @TargetApi(19) 30 public abstract class BaseEmulatorActivity extends PassFailButtons.Activity { 31 static final String TAG = "BaseEmulatorActivity"; 32 NfcAdapter mAdapter; 33 CardEmulation mCardEmulation; 34 ProgressDialog mSetupDialog; 35 ComponentName mMakingDefault; 36 37 final ArrayList<ComponentName> SERVICES = new ArrayList<ComponentName>( 38 Arrays.asList( 39 PaymentService1.COMPONENT, 40 PaymentService2.COMPONENT, 41 TransportService1.COMPONENT, 42 TransportService2.COMPONENT, 43 AccessService.COMPONENT, 44 ThroughputService.COMPONENT, 45 OffHostService.COMPONENT, 46 PaymentServiceDynamicAids.COMPONENT, 47 PrefixPaymentService1.COMPONENT, 48 PrefixPaymentService2.COMPONENT, 49 PrefixTransportService1.COMPONENT, 50 PrefixTransportService2.COMPONENT, 51 PrefixAccessService.COMPONENT, 52 LargeNumAidsService.COMPONENT, 53 ScreenOnOnlyOffHostService.COMPONENT, 54 ScreenOffPaymentService.COMPONENT) 55 ); 56 57 @Override onCreate(Bundle savedInstanceState)58 protected void onCreate(Bundle savedInstanceState) { 59 super.onCreate(savedInstanceState); 60 61 mAdapter = NfcAdapter.getDefaultAdapter(this); 62 mCardEmulation = CardEmulation.getInstance(mAdapter); 63 IntentFilter filter = new IntentFilter(HceUtils.ACTION_APDU_SEQUENCE_COMPLETE); 64 registerReceiver(mReceiver, filter, RECEIVER_EXPORTED); 65 } 66 onServicesSetup(boolean result)67 abstract void onServicesSetup(boolean result); 68 onApduSequenceComplete(ComponentName component, long duration)69 abstract void onApduSequenceComplete(ComponentName component, long duration); 70 onApduSequenceError()71 void onApduSequenceError() { 72 73 } 74 75 @Override onStop()76 protected void onStop() { 77 super.onStop(); 78 } 79 80 @Override onDestroy()81 protected void onDestroy() { 82 super.onDestroy(); 83 unregisterReceiver(mReceiver); 84 } 85 86 @Override onPause()87 protected void onPause() { 88 super.onPause(); 89 } 90 91 @Override onResume()92 protected void onResume() { 93 super.onResume(); 94 } 95 setupServices(Context context, ComponentName... components)96 final void setupServices(Context context, ComponentName... components) { 97 mSetupDialog = new ProgressDialog(context); 98 new SetupServicesTask().execute(components); 99 } 100 makePaymentDefault(final ComponentName defaultComponent, int stringId)101 final boolean makePaymentDefault(final ComponentName defaultComponent, int stringId) { 102 if (!mCardEmulation.isDefaultServiceForCategory(defaultComponent, 103 CardEmulation.CATEGORY_PAYMENT)) { 104 AlertDialog.Builder builder = new AlertDialog.Builder(this); 105 builder.setTitle("Note"); 106 builder.setMessage(stringId); 107 mMakingDefault = defaultComponent; 108 builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 109 @Override 110 public void onClick(DialogInterface dialog, int which) { 111 Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT); 112 changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, 113 CardEmulation.CATEGORY_PAYMENT); 114 changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, defaultComponent); 115 changeDefault.putExtra(Intent.EXTRA_USER, 116 UserHandle.getUserHandleForUid(getApplicationInfo().uid)); 117 startActivityForResult(changeDefault, 0); 118 } 119 }); 120 builder.show(); 121 return true; 122 } else { 123 return false; 124 } 125 } 126 127 final BroadcastReceiver mReceiver = new BroadcastReceiver() { 128 @Override 129 public void onReceive(Context context, Intent intent) { 130 String action = intent.getAction(); 131 if (HceUtils.ACTION_APDU_SEQUENCE_COMPLETE.equals(action)) { 132 // Get component whose sequence was completed 133 ComponentName component = intent.getParcelableExtra(HceUtils.EXTRA_COMPONENT); 134 long duration = intent.getLongExtra(HceUtils.EXTRA_DURATION, 0); 135 if (component != null) { 136 onApduSequenceComplete(component, duration); 137 } 138 } else if (HceUtils.ACTION_APDU_SEQUENCE_ERROR.equals(action)) { 139 onApduSequenceError(); 140 } 141 } 142 }; 143 144 private class SetupServicesTask extends AsyncTask<ComponentName, Void, Boolean> { 145 @Override onPostExecute(Boolean result)146 protected void onPostExecute(Boolean result) { 147 super.onPostExecute(result); 148 mSetupDialog.dismiss(); 149 onServicesSetup(result); 150 } 151 152 @Override onPreExecute()153 protected void onPreExecute() { 154 super.onPreExecute(); 155 mSetupDialog.setTitle(R.string.nfc_hce_please_wait); 156 mSetupDialog.setMessage(getString(R.string.nfc_hce_setting_up)); 157 mSetupDialog.setCancelable(false); 158 mSetupDialog.show(); 159 } 160 161 @Override doInBackground(ComponentName... components)162 protected Boolean doInBackground(ComponentName... components) { 163 List<ComponentName> enableComponents = Arrays.asList(components); 164 for (ComponentName component : SERVICES) { 165 if (enableComponents.contains(component)) { 166 Log.d(TAG, "Enabling component " + component); 167 HceUtils.enableComponent(getPackageManager(), component); 168 } else { 169 Log.d(TAG, "Disabling component " + component); 170 HceUtils.disableComponent(getPackageManager(), component); 171 } 172 } 173 // This is a trick to invalidate the HCE cache and avoid 174 // having to wait for PackageManager broadcasts to NFCService. 175 ComponentName bogusComponent = new ComponentName("com.android.cts.verifier", 176 "com.android.cts.verifier.nfc.hce.BogusService"); 177 mCardEmulation.isDefaultServiceForCategory(bogusComponent, 178 CardEmulation.CATEGORY_PAYMENT); 179 return true; 180 } 181 } 182 183 @Override onActivityResult(int requestCode, int resultCode, Intent data)184 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 185 super.onActivityResult(requestCode, resultCode, data); 186 if (resultCode == Activity.RESULT_OK) { 187 // Verify it's default 188 if (!mCardEmulation.isDefaultServiceForCategory(mMakingDefault, 189 CardEmulation.CATEGORY_PAYMENT)) { 190 // Popup dialog-box 191 AlertDialog.Builder builder = new AlertDialog.Builder(this); 192 builder.setTitle("Test failed."); 193 builder.setMessage("The service was not made the default service according " + 194 "to CardEmulation.getDefaultServiceForCategory(), verify the make " + 195 "default implementation is correct."); 196 builder.setPositiveButton("OK", null); 197 builder.show(); 198 onPaymentDefaultResult(mMakingDefault, false); 199 } else { 200 onPaymentDefaultResult(mMakingDefault, true); 201 } 202 } else { 203 AlertDialog.Builder builder = new AlertDialog.Builder(this); 204 builder.setTitle("Test failed."); 205 builder.setMessage("You clicked no."); 206 builder.setPositiveButton("OK", null); 207 builder.show(); 208 onPaymentDefaultResult(mMakingDefault, false); 209 } 210 } 211 onPaymentDefaultResult(ComponentName component, boolean success)212 void onPaymentDefaultResult(ComponentName component, boolean success) { 213 214 }; 215 } 216