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 } 59 onServicesSetup(boolean result)60 abstract void onServicesSetup(boolean result); 61 onApduSequenceComplete(ComponentName component, long duration)62 abstract void onApduSequenceComplete(ComponentName component, long duration); 63 onApduSequenceError()64 void onApduSequenceError() { 65 66 } 67 68 @Override onPause()69 protected void onPause() { 70 super.onPause(); 71 unregisterReceiver(mReceiver); 72 } 73 74 @Override onResume()75 protected void onResume() { 76 super.onResume(); 77 IntentFilter filter = new IntentFilter(HceUtils.ACTION_APDU_SEQUENCE_COMPLETE); 78 registerReceiver(mReceiver, filter); 79 } 80 setupServices(Context context, ComponentName... components)81 final void setupServices(Context context, ComponentName... components) { 82 mSetupDialog = new ProgressDialog(context); 83 new SetupServicesTask().execute(components); 84 } 85 makePaymentDefault(final ComponentName defaultComponent, int stringId)86 final boolean makePaymentDefault(final ComponentName defaultComponent, int stringId) { 87 if (!mCardEmulation.isDefaultServiceForCategory(defaultComponent, 88 CardEmulation.CATEGORY_PAYMENT)) { 89 AlertDialog.Builder builder = new AlertDialog.Builder(this); 90 builder.setTitle("Note"); 91 builder.setMessage(stringId); 92 mMakingDefault = defaultComponent; 93 builder.setPositiveButton("OK", new DialogInterface.OnClickListener() { 94 @Override 95 public void onClick(DialogInterface dialog, int which) { 96 Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT); 97 changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT); 98 changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, defaultComponent); 99 startActivityForResult(changeDefault, 0); 100 } 101 }); 102 builder.show(); 103 return true; 104 } else { 105 return false; 106 } 107 } 108 109 final BroadcastReceiver mReceiver = new BroadcastReceiver() { 110 @Override 111 public void onReceive(Context context, Intent intent) { 112 String action = intent.getAction(); 113 if (HceUtils.ACTION_APDU_SEQUENCE_COMPLETE.equals(action)) { 114 // Get component whose sequence was completed 115 ComponentName component = intent.getParcelableExtra(HceUtils.EXTRA_COMPONENT); 116 long duration = intent.getLongExtra(HceUtils.EXTRA_DURATION, 0); 117 if (component != null) { 118 onApduSequenceComplete(component, duration); 119 } 120 } else if (HceUtils.ACTION_APDU_SEQUENCE_ERROR.equals(action)) { 121 onApduSequenceError(); 122 } 123 } 124 }; 125 126 private class SetupServicesTask extends AsyncTask<ComponentName, Void, Boolean> { 127 @Override onPostExecute(Boolean result)128 protected void onPostExecute(Boolean result) { 129 super.onPostExecute(result); 130 mSetupDialog.dismiss(); 131 onServicesSetup(result); 132 } 133 134 @Override onPreExecute()135 protected void onPreExecute() { 136 super.onPreExecute(); 137 mSetupDialog.setTitle(R.string.nfc_hce_please_wait); 138 mSetupDialog.setMessage(getString(R.string.nfc_hce_setting_up)); 139 mSetupDialog.setCancelable(false); 140 mSetupDialog.show(); 141 } 142 143 @Override doInBackground(ComponentName... components)144 protected Boolean doInBackground(ComponentName... components) { 145 List<ComponentName> enableComponents = Arrays.asList(components); 146 for (ComponentName component : SERVICES) { 147 if (enableComponents.contains(component)) { 148 Log.d(TAG, "Enabling component " + component); 149 HceUtils.enableComponent(getPackageManager(), component); 150 } else { 151 Log.d(TAG, "Disabling component " + component); 152 HceUtils.disableComponent(getPackageManager(), component); 153 } 154 } 155 // This is a trick to invalidate the HCE cache and avoid 156 // having to wait for PackageManager broadcasts to NFCService. 157 ComponentName bogusComponent = new ComponentName("com.android.cts.verifier", 158 "com.android.cts.verifier.nfc.hce.BogusService"); 159 mCardEmulation.isDefaultServiceForCategory(bogusComponent, 160 CardEmulation.CATEGORY_PAYMENT); 161 return true; 162 } 163 } 164 165 @Override onActivityResult(int requestCode, int resultCode, Intent data)166 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 167 super.onActivityResult(requestCode, resultCode, data); 168 if (resultCode == Activity.RESULT_OK) { 169 // Verify it's default 170 if (!mCardEmulation.isDefaultServiceForCategory(mMakingDefault, 171 CardEmulation.CATEGORY_PAYMENT)) { 172 // Popup dialog-box 173 AlertDialog.Builder builder = new AlertDialog.Builder(this); 174 builder.setTitle("Test failed."); 175 builder.setMessage("The service was not made the default service according " + 176 "to CardEmulation.getDefaultServiceForCategory(), verify the make " + 177 "default implementation is correct."); 178 builder.setPositiveButton("OK", null); 179 builder.show(); 180 onPaymentDefaultResult(mMakingDefault, false); 181 } else { 182 onPaymentDefaultResult(mMakingDefault, true); 183 } 184 } else { 185 AlertDialog.Builder builder = new AlertDialog.Builder(this); 186 builder.setTitle("Test failed."); 187 builder.setMessage("You clicked no."); 188 builder.setPositiveButton("OK", null); 189 builder.show(); 190 onPaymentDefaultResult(mMakingDefault, false); 191 } 192 } 193 onPaymentDefaultResult(ComponentName component, boolean success)194 void onPaymentDefaultResult(ComponentName component, boolean success) { 195 196 }; 197 } 198