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