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