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