summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/nfc/NfcService.java22
-rw-r--r--src/com/android/nfc/RoutingTableParser.java284
-rw-r--r--src/com/android/nfc/beam/BeamReceiveService.java3
-rw-r--r--src/com/android/nfc/beam/BeamSendService.java3
-rw-r--r--src/com/android/nfc/beam/SendUi.java2
-rw-r--r--src/com/android/nfc/cardemulation/AppChooserActivity.java62
-rw-r--r--src/com/android/nfc/cardemulation/CardEmulationManager.java27
-rw-r--r--src/com/android/nfc/cardemulation/TapAgainDialog.java39
8 files changed, 293 insertions, 149 deletions
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 2ec29477..60f4f85b 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -77,6 +77,7 @@ import android.os.UserManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
import android.se.omapi.ISecureElementService;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -536,6 +537,7 @@ public class NfcService implements DeviceHostListener {
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_ADDED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
// Listen for work profile adds or removes.
@@ -775,6 +777,7 @@ public class NfcService implements DeviceHostListener {
mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
mPrefsEditor.apply();
mDeviceHost.factoryReset();
+ setPaymentForegroundPreference(mUserId);
}
Log.d(TAG, "checking on firmware download");
if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
@@ -889,6 +892,7 @@ public class NfcService implements DeviceHostListener {
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_ADDED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
mIsRecovering = false;
}
@@ -3243,6 +3247,9 @@ public class NfcService implements DeviceHostListener {
if (screenState != mScreenState) {
new ApplyRoutingTask().execute(Integer.valueOf(screenState));
}
+ } else if (action.equals(Intent.ACTION_USER_ADDED)) {
+ int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ setPaymentForegroundPreference(userId);
}
}
};
@@ -3267,6 +3274,7 @@ public class NfcService implements DeviceHostListener {
action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED) ||
action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
mCardEmulationManager.onManagedProfileChanged();
+ setPaymentForegroundPreference(user.getIdentifier());
}
}
};
@@ -3313,6 +3321,20 @@ public class NfcService implements DeviceHostListener {
}
};
+ private void setPaymentForegroundPreference(int user) {
+ try {
+ // Check whether the Settings.Secure.NFC_PAYMENT_FOREGROUND exists or not.
+ Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND, user);
+ } catch (SettingNotFoundException e) {
+ boolean foregroundPreference =
+ mContext.getResources().getBoolean(R.bool.payment_foreground_preference);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.NFC_PAYMENT_FOREGROUND, foregroundPreference ? 1 : 0, user);
+ Log.d(TAG, "Set NFC_PAYMENT_FOREGROUND preference:" + foregroundPreference);
+ }
+ }
+
/**
* for debugging only - no i18n
*/
diff --git a/src/com/android/nfc/RoutingTableParser.java b/src/com/android/nfc/RoutingTableParser.java
index d2c7f1ad..9174c244 100644
--- a/src/com/android/nfc/RoutingTableParser.java
+++ b/src/com/android/nfc/RoutingTableParser.java
@@ -17,10 +17,12 @@
package com.android.nfc;
import android.os.SystemProperties;
-import java.util.Locale;
import android.util.Log;
import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Vector;
/**
* Parse the Routing Table from the last backup lmrt cmd and dump it with a clear typography
@@ -28,57 +30,92 @@ import java.io.PrintWriter;
public class RoutingTableParser {
static final boolean DBG = SystemProperties.getBoolean("persist.nfc.debug_enabled", false);
private static final String TAG = "RoutingTableParser";
+ private static int sRoutingTableSize = 0;
+ private static int sRoutingTableMaxSize = 0;
+ private static Vector<RoutingEntryInfo> sRoutingTable = new Vector<RoutingEntryInfo>(0);
+
+ // Entry types
+ static final byte TYPE_TECHNOLOGY = 0;
+ static final byte TYPE_PROTOCOL = 1;
+ static final byte TYPE_AID = 2;
+ static final byte TYPE_SYSTEMCODE = 3;
+ static final byte TYPE_UNSUPPORTED = 4;
+
+ // Commit status
+ static final int STATS_HOST_OK = 0;
+ static final int STATS_OFFHOST_OK = 1;
+ static final int STATS_NOT_FOUND = 2;
- private String getTechStr(int value) {
+ private interface GetEntryStr {
+ String getEntryStr(byte[] entry);
+ }
+
+ private GetEntryStr[] mGetEntryStrFuncs = new GetEntryStr[] {
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getTechStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getProtoStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getAidStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getSystemCodeStr(entry); } },
+ };
+
+ private String getTechStr(byte[] tech) {
String[] tech_mask_list = {
"TECHNOLOGY_A", "TECHNOLOGY_B", "TECHNOLOGY_F", "TECHNOLOGY_V"
};
- if (value > tech_mask_list.length) {
+ if (tech[0] > tech_mask_list.length) {
return "UNSUPPORTED_TECH";
}
- return tech_mask_list[value];
+ return tech_mask_list[tech[0]];
}
- private String getProtoStr(int value) {
+ private String getProtoStr(byte[] proto) {
String[] proto_mask_list = {
"PROTOCOL_UNDETERMINED", "PROTOCOL_T1T", "PROTOCOL_T2T", "PROTOCOL_T3T",
"PROTOCOL_ISO_DEP", "PROTOCOL_NFC_DEP", "PROTOCOL_T5T", "PROTOCOL_NDEF"
};
- if (value > proto_mask_list.length) {
+ if (proto[0] > proto_mask_list.length) {
return "UNSUPPORTED_PROTO";
}
- return proto_mask_list[value];
+ return proto_mask_list[proto[0]];
}
- private String getAidStr(byte[] rt, int offset, int aidLen) {
- String Aid = "";
- for (int i = 0; i < aidLen; i++) {
- Aid += String.format("%02X", rt[offset + i]);
+ private String getAidStr(byte[] aid) {
+ String aidStr = "";
+
+ for (byte b : aid) {
+ aidStr += String.format("%02X", b);
}
- if (Aid.length() == 0) {
+ if (aidStr.length() == 0) {
return "Empty_AID";
}
- return "AID_" + Aid;
+ return "AID_" + aidStr;
}
- private String getSystemCodeStr(byte[] rt, int offset, int scLen) {
- String SystemCode = "";
- for (int i = 0; i < scLen; i++) {
- SystemCode += String.format("%02X", rt[offset + i]);
+ private String getSystemCodeStr(byte[] sc) {
+ String systemCodeStr = "";
+ for (byte b : sc) {
+ systemCodeStr += String.format("%02X", b);
}
- return "SYSTEMCODE_" + SystemCode;
+ return "SYSTEMCODE_" + systemCodeStr;
}
- private String getBlockCtrlStr(int mask) {
+ private String getBlockCtrlStr(byte mask) {
if ((mask & 0x40) != 0) {
return "True";
}
return "False";
}
- private String getPrefixSubsetStr(int mask) {
+ private String getPrefixSubsetStr(byte mask, byte type) {
+ if (type != TYPE_AID) {
+ return "";
+ }
+
String prefix_subset_str = "";
if ((mask & 0x10) != 0) {
prefix_subset_str += "Prefix ";
@@ -98,84 +135,172 @@ public class RoutingTableParser {
return String.format(fmt, entry, eeId, pwrState, blkCtrl, extra);
}
- private void dumpTechEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 >= rtSize) return;
+ private class RoutingEntryInfo {
+ public final byte mQualifier;
+ public final byte mType;
+ public final byte mNfceeId;
+ public final byte mPowerState;
+ public final byte[] mEntry;
+
+ private RoutingEntryInfo(byte qualifier, byte type, byte eeId, byte pwrState,
+ byte[] entry) {
+ mQualifier = qualifier;
+ mType = type;
+ mNfceeId = eeId;
+ mPowerState = pwrState;
+ mEntry = entry;
+ }
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getTechStr(rt[offset + 4]);
+ private void dump(PrintWriter pw) {
+ String blkCtrl = getBlockCtrlStr(mQualifier);
+ String eeId = String.format("0x%02X", mNfceeId);
+ String pwrState = String.format("0x%02X", mPowerState);
+ String entry = mGetEntryStrFuncs[mType].getEntryStr(mEntry);
+ String extra = getPrefixSubsetStr(mQualifier, mType);
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, extra));
+ }
}
- private void dumpProtoEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 >= rtSize) return;
+ private boolean validateEntryInfo(byte type, byte[] entry) {
+ switch(type) {
+ case TYPE_TECHNOLOGY:
+ if (entry.length != 1) return false;
+ break;
+ case TYPE_PROTOCOL:
+ if (entry.length != 1) return false;
+ break;
+ case TYPE_AID:
+ if (entry.length > 16) return false;
+ break;
+ case TYPE_SYSTEMCODE:
+ if (entry.length != 2) return false;
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getProtoStr(rt[offset + 4]);
+ /**
+ * Check commit status by inputting type and entry
+ */
+ public int getCommitStatus(byte type, byte[] entry) {
+ if (!validateEntryInfo(type, entry)) return STATS_NOT_FOUND;
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ for (RoutingEntryInfo routingEntry : sRoutingTable) {
+ if (routingEntry.mType != type) {
+ continue;
+ }
+ if (Arrays.equals(routingEntry.mEntry, entry)) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ if (routingEntry.mType != TYPE_AID) {
+ continue;
+ }
+ if ((routingEntry.mQualifier & 0x10) != 0
+ && entry.length > routingEntry.mEntry.length) {
+ int ptr = 0;
+ while (entry[ptr] == routingEntry.mEntry[ptr]) {
+ ptr += 1;
+ }
+ if (ptr == routingEntry.mEntry.length) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ }
+ if ((routingEntry.mQualifier & 0x20) != 0
+ && entry.length < routingEntry.mEntry.length) {
+ int ptr = 0;
+ while (entry[ptr] == routingEntry.mEntry[ptr]) {
+ ptr += 1;
+ }
+ if (ptr == entry.length) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ }
+ }
+ return STATS_NOT_FOUND;
}
- private void dumpAidEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 + rt[offset + 1] - 2 >= rtSize) return;
+ private void addRoutingEntry(byte[] rt, int offset) {
+ if (offset + 1 >= rt.length) return;
+ int valueLength = rt[offset + 1];
+
+ // Qualifier-Type(1 byte) + Length(1 byte) + Value(valueLength bytes)
+ if (offset + 2 + valueLength > rt.length) return;
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String extra = getPrefixSubsetStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getAidStr(rt, offset + 4, rt[offset + 1] - 2);
+ byte qualifier = (byte) (rt[offset] & 0xF0);
+ byte type = (byte) (rt[offset] & 0x0F);
+ byte eeId = rt[offset + 2];
+ byte pwrState = rt[offset + 3];
+ byte[] entry = new byte[valueLength - 2];
+ for (int i = 0; i < valueLength - 2; i++) {
+ entry[i] = rt[offset + 4 + i];
+ }
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, extra));
+ if (type == TYPE_SYSTEMCODE && (entry.length & 1) == 0 && entry.length <= 64) {
+ for (int i = 0; i < entry.length; i += 2) {
+ byte[] sc_entry = {entry[i], entry[i + 1]};
+ sRoutingTable.add(new RoutingEntryInfo(qualifier, type, eeId, pwrState, sc_entry));
+ }
+ } else if (validateEntryInfo(type, entry)) {
+ sRoutingTable.add(new RoutingEntryInfo(qualifier, type, eeId, pwrState, entry));
+ }
}
- private void dumpSystemEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 + rt[offset + 1] - 2 >= rtSize) return;
+ /**
+ * Parse the raw data of routing table
+ */
+ public void parse(byte[] rt) {
+ int offset = 0;
+
+ logRoutingTableRawData(rt);
+
+ sRoutingTable.clear();
+ while (offset < rt.length) {
+ byte type = (byte) (rt[offset] & 0x0F);
+ if (type >= TYPE_UNSUPPORTED) {
+ // Unrecognizable entry type
+ Log.e(TAG, String.format("Unrecognizable entry type: 0x%02X, stop parsing", type));
+ return;
+ }
+ if (offset + 1 >= rt.length) {
+ // Buffer overflow
+ Log.e(TAG, String.format("Wrong tlv length, stop parsing"));
+ return;
+ }
+ // Qualifier-Type(1 byte) + Length(1 byte) + Value(valueLength bytes)
+ int tlvLength = rt[offset + 1] + 2;
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getSystemCodeStr(rt, offset + 4, rt[offset + 1] - 2);
+ addRoutingEntry(rt, offset);
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ offset += tlvLength;
+ }
}
/**
- * Get Routing Table from the last backup lmrt cmd and dump it
+ * Get Routing Table from the last backup lmrt cmd and parse it
*/
- public void dump(DeviceHost dh, PrintWriter pw) {
- int offset = 0;
+ public void update(DeviceHost dh) {
+ sRoutingTableMaxSize = dh.getMaxRoutingTableSize();
byte[] rt = dh.getRoutingTable();
- int maxSize = dh.getMaxRoutingTableSize();
+ sRoutingTableSize = rt.length;
+ parse(rt);
+ }
- logRoutingTableRawData(rt);
+ /**
+ * Get Routing Table from the last backup lmrt cmd and dump it
+ */
+ public void dump(DeviceHost dh, PrintWriter pw) {
+ update(dh);
pw.println("--- dumpRoutingTable: start ---");
- pw.println(String.format(Locale.US, "RoutingTableSize: %d/%d", rt.length, maxSize));
+ pw.println(String.format(Locale.US, "RoutingTableSize: %d/%d",
+ sRoutingTableSize, sRoutingTableMaxSize));
pw.println(formatRow("Entry", "NFCEE_ID", "Power State", "Block Ctrl", "Extra Info"));
- while (offset < rt.length) {
- int type = rt[offset] & 0x0F;
- if (type == 0x00) {
- // Technology-based routing entry
- dumpTechEntry(rt, rt.length, pw, offset);
- } else if (type == 0x01) {
- // Protocol-based routing entry
- dumpProtoEntry(rt, rt.length, pw, offset);
- } else if (type == 0x02) {
- // AID-based routing entry
- dumpAidEntry(rt, rt.length, pw, offset);
- } else if (type == 0x03) {
- // System Code-based routing entry
- dumpSystemEntry(rt, rt.length, pw, offset);
- } else {
- // Unrecognizable entry type
- Log.d(TAG, String.format("Unrecognizable entry type: 0x%02X, stop parsing", type));
- break;
- }
- offset += rt[offset+1] + 2;
+
+ for (RoutingEntryInfo routingEntry : sRoutingTable) {
+ routingEntry.dump(pw);
}
pw.println("--- dumpRoutingTable: end ---");
@@ -184,10 +309,11 @@ public class RoutingTableParser {
private void logRoutingTableRawData(byte[] lmrt_cmd) {
if (!DBG) return;
String lmrt_str = "";
- for (int i = 0; i < lmrt_cmd.length; i++) {
- lmrt_str += String.format("%02X ", lmrt_cmd[i]);
+
+ for (byte b : lmrt_cmd) {
+ lmrt_str += String.format("%02X ", b);
}
- Log.d(TAG, String.format("RoutingTableSize: %d", lmrt_cmd.length));
- Log.d(TAG, String.format("RoutingTable: %s", lmrt_str));
+ Log.i(TAG, String.format("RoutingTableSize: %d", lmrt_cmd.length));
+ Log.i(TAG, String.format("RoutingTable: %s", lmrt_str));
}
}
diff --git a/src/com/android/nfc/beam/BeamReceiveService.java b/src/com/android/nfc/beam/BeamReceiveService.java
index 5602997b..444b12ed 100644
--- a/src/com/android/nfc/beam/BeamReceiveService.java
+++ b/src/com/android/nfc/beam/BeamReceiveService.java
@@ -94,7 +94,8 @@ public class BeamReceiveService extends Service implements BeamTransferManager.C
// register Beam status receiver
mBeamStatusReceiver = new BeamStatusReceiver(this, mTransferManager);
registerReceiver(mBeamStatusReceiver, mBeamStatusReceiver.getIntentFilter(),
- BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler());
+ BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler(),
+ Context.RECEIVER_EXPORTED);
mTransferManager.start();
mTransferManager.updateNotification();
diff --git a/src/com/android/nfc/beam/BeamSendService.java b/src/com/android/nfc/beam/BeamSendService.java
index f4880d49..13f8f3d3 100644
--- a/src/com/android/nfc/beam/BeamSendService.java
+++ b/src/com/android/nfc/beam/BeamSendService.java
@@ -107,7 +107,8 @@ public class BeamSendService extends Service implements BeamTransferManager.Call
// register Beam status receiver
mBeamStatusReceiver = new BeamStatusReceiver(this, mTransferManager);
registerReceiver(mBeamStatusReceiver, mBeamStatusReceiver.getIntentFilter(),
- BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler());
+ BeamStatusReceiver.BEAM_STATUS_PERMISSION, new Handler(),
+ Context.RECEIVER_EXPORTED);
if (transferRecord.dataLinkType == BeamTransferRecord.DATA_LINK_TYPE_BLUETOOTH) {
if (mBluetoothAdapter.isEnabled()) {
diff --git a/src/com/android/nfc/beam/SendUi.java b/src/com/android/nfc/beam/SendUi.java
index 966d1376..e2094163 100644
--- a/src/com/android/nfc/beam/SendUi.java
+++ b/src/com/android/nfc/beam/SendUi.java
@@ -331,7 +331,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener,
new ScreenshotTask().execute();
final IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- mContext.registerReceiver(mReceiver, filter);
+ mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);
}
/** Show pre-send animation */
diff --git a/src/com/android/nfc/cardemulation/AppChooserActivity.java b/src/com/android/nfc/cardemulation/AppChooserActivity.java
index 11f4d46e..ee16aeb1 100644
--- a/src/com/android/nfc/cardemulation/AppChooserActivity.java
+++ b/src/com/android/nfc/cardemulation/AppChooserActivity.java
@@ -42,15 +42,17 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
import com.android.internal.R;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback;
import java.util.ArrayList;
import java.util.List;
-public class AppChooserActivity extends AlertActivity
+public class AppChooserActivity extends AppCompatActivity
implements AdapterView.OnItemClickListener {
static final String TAG = "AppChooserActivity";
@@ -60,6 +62,7 @@ public class AppChooserActivity extends AlertActivity
public static final String EXTRA_FAILED_COMPONENT = "failed_component";
private int mIconSize;
+ private TextView mTextView;
private ListView mListView;
private ListAdapter mListAdapter;
private CardEmulation mCardEmuManager;
@@ -81,7 +84,6 @@ public class AppChooserActivity extends AlertActivity
protected void onCreate(Bundle savedInstanceState, String category,
ArrayList<ApduServiceInfo> options, ComponentName failedComponent) {
super.onCreate(savedInstanceState);
- setTheme(com.android.nfc.R.style.DialogAlertDayNight);
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(mReceiver, filter);
@@ -97,7 +99,6 @@ public class AppChooserActivity extends AlertActivity
final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
mCardEmuManager = CardEmulation.getInstance(adapter);
- AlertController.AlertParams ap = mAlertParams;
final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconSize = am.getLauncherLargeIconSize();
@@ -108,6 +109,27 @@ public class AppChooserActivity extends AlertActivity
// 3. No failed component and alternatives: pick alternative
PackageManager pm = getPackageManager();
+ setContentView(com.android.nfc.R.layout.cardemu_resolver_bottomsheet);
+
+
+ findViewById(com.android.nfc.R.id.touch_outside).setOnClickListener(v -> finish());
+ BottomSheetBehavior.from(findViewById(com.android.nfc.R.id.bottom_sheet))
+ .setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
+ @Override
+ public void onStateChanged(@NonNull View bottomSheet, int newState) {
+ switch (newState) {
+ case BottomSheetBehavior.STATE_HIDDEN:
+ finish();
+ break;
+ }
+ }
+
+ @Override
+ public void onSlide(@NonNull View bottomSheet, float slideOffset) {
+ // no op
+ }
+ });
+
CharSequence applicationLabel = "unknown";
if (failedComponent != null) {
try {
@@ -117,30 +139,20 @@ public class AppChooserActivity extends AlertActivity
}
}
+ mTextView = (TextView) findViewById(com.android.nfc.R.id.appchooser_text);
if (options.size() == 0 && failedComponent != null) {
String formatString = getString(com.android.nfc.R.string.transaction_failure);
- ap.mTitle = "";
- ap.mMessage = String.format(formatString, applicationLabel);
- ap.mPositiveButtonText = getString(R.string.ok);
- setupAlert();
+ mTextView.setText(String.format(formatString, applicationLabel));
} else {
mListAdapter = new ListAdapter(this, options);
if (failedComponent != null) {
String formatString = getString(com.android.nfc.R.string.could_not_use_app);
- ap.mTitle = String.format(formatString, applicationLabel);
- ap.mNegativeButtonText = getString(R.string.cancel);
- } else {
- if (CardEmulation.CATEGORY_PAYMENT.equals(category)) {
- ap.mTitle = getString(com.android.nfc.R.string.pay_with);
- } else {
- ap.mTitle = getString(com.android.nfc.R.string.complete_with);
- }
+ mTextView.setText(String.format(formatString, applicationLabel));
}
- ap.mView = getLayoutInflater().inflate(com.android.nfc.R.layout.cardemu_resolver, null);
- mListView = (ListView) ap.mView.findViewById(com.android.nfc.R.id.resolver_list);
+ mListView = (ListView) findViewById(com.android.nfc.R.id.resolver_list);
+ mListView.setDivider(getResources().getDrawable(android.R.color.transparent));
if (isPayment) {
- mListView.setDivider(getResources().getDrawable(android.R.color.transparent));
int height = (int) (getResources().getDisplayMetrics().density * 16);
mListView.setDividerHeight(height);
} else {
@@ -148,10 +160,9 @@ public class AppChooserActivity extends AlertActivity
}
mListView.setAdapter(mListAdapter);
mListView.setOnItemClickListener(this);
-
- setupAlert();
}
Window window = getWindow();
+ window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
}
@@ -206,7 +217,10 @@ public class AppChooserActivity extends AlertActivity
for (ApduServiceInfo service : services) {
CharSequence label = service.getDescription();
if (label == null) label = service.loadLabel(pm);
- Drawable icon = service.loadIcon(pm);
+
+ Drawable icon = pm.getUserBadgedIcon(service.loadIcon(pm),
+ UserHandle.getUserHandleForUid(service.getUid()));
+
Drawable banner = null;
if (mIsPayment) {
banner = service.loadBanner(pm);
@@ -258,8 +272,6 @@ public class AppChooserActivity extends AlertActivity
if (mIsPayment) {
holder.banner.setImageDrawable(appInfo.displayBanner);
} else {
- ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
- lp.width = lp.height = mIconSize;
holder.icon.setImageDrawable(appInfo.displayIcon);
holder.text.setText(appInfo.displayLabel);
}
diff --git a/src/com/android/nfc/cardemulation/CardEmulationManager.java b/src/com/android/nfc/cardemulation/CardEmulationManager.java
index e3d21627..378fe6e0 100644
--- a/src/com/android/nfc/cardemulation/CardEmulationManager.java
+++ b/src/com/android/nfc/cardemulation/CardEmulationManager.java
@@ -264,30 +264,9 @@ public class CardEmulationManager implements RegisteredServicesCache.Callback,
getDefaultServiceForCategory(userId, CardEmulation.CATEGORY_PAYMENT, true);
if (DBG) Log.d(TAG, "Current default: " + defaultPaymentService);
if (defaultPaymentService == null) {
- // A payment service may have been removed, leaving only one;
- // in that case, automatically set that app as default.
- int numPaymentServices = 0;
- ComponentName lastFoundPaymentService = null;
- for (ApduServiceInfo service : services) {
- if (service.hasCategory(CardEmulation.CATEGORY_PAYMENT)) {
- numPaymentServices++;
- lastFoundPaymentService = service.getComponent();
- }
- }
- if (numPaymentServices > 1) {
- // More than one service left, leave default unset
- if (DBG) Log.d(TAG, "No default set, more than one service left.");
- setDefaultServiceForCategoryChecked(userId, null, CardEmulation.CATEGORY_PAYMENT);
- } else if (numPaymentServices == 1) {
- // Make single found payment service the default
- if (DBG) Log.d(TAG, "No default set, making single service default.");
- setDefaultServiceForCategoryChecked(userId, lastFoundPaymentService,
- CardEmulation.CATEGORY_PAYMENT);
- } else {
- // No payment services left, leave default at null
- if (DBG) Log.d(TAG, "No default set, last payment service removed.");
- setDefaultServiceForCategoryChecked(userId, null, CardEmulation.CATEGORY_PAYMENT);
- }
+ // A payment service may have been removed, set default payment selection to "not set".
+ if (DBG) Log.d(TAG, "No default set, last payment service removed.");
+ setDefaultServiceForCategoryChecked(userId, null, CardEmulation.CATEGORY_PAYMENT);
}
}
diff --git a/src/com/android/nfc/cardemulation/TapAgainDialog.java b/src/com/android/nfc/cardemulation/TapAgainDialog.java
index e786ab33..a46735b8 100644
--- a/src/com/android/nfc/cardemulation/TapAgainDialog.java
+++ b/src/com/android/nfc/cardemulation/TapAgainDialog.java
@@ -22,13 +22,18 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
import android.nfc.NfcAdapter;
import android.nfc.cardemulation.ApduServiceInfo;
import android.nfc.cardemulation.CardEmulation;
import android.os.Bundle;
+import android.os.UserHandle;
+import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.widget.ImageView;
import android.widget.TextView;
+import androidx.appcompat.widget.Toolbar;
import com.android.internal.R;
import com.android.internal.app.AlertActivity;
@@ -56,7 +61,7 @@ public class TapAgainDialog extends AlertActivity implements DialogInterface.OnC
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setTheme(com.android.nfc.R.style.DialogAlertDayNight);
+ setTheme(com.android.nfc.R.style.TapAgainDayNight);
final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
mCardEmuManager = CardEmulation.getInstance(adapter);
@@ -72,24 +77,22 @@ public class TapAgainDialog extends AlertActivity implements DialogInterface.OnC
ap.mView = getLayoutInflater().inflate(com.android.nfc.R.layout.tapagain, null);
PackageManager pm = getPackageManager();
- TextView tv = (TextView) ap.mView.findViewById(com.android.nfc.R.id.textview);
- String description = serviceInfo.getDescription();
- if (description == null) {
- CharSequence label = serviceInfo.loadLabel(pm);
- if (label == null) {
+
+ Toolbar toolbar = (Toolbar) ap.mView.findViewById(com.android.nfc.R.id.tap_again_toolbar);
+ toolbar.setNavigationIcon(getDrawable(com.android.nfc.R.drawable.ic_close));
+ toolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
finish();
- } else {
- description = label.toString();
}
- }
- if (CardEmulation.CATEGORY_PAYMENT.equals(category)) {
- String formatString = getString(com.android.nfc.R.string.tap_again_to_pay);
- tv.setText(String.format(formatString, description));
- } else {
- String formatString = getString(com.android.nfc.R.string.tap_again_to_complete);
- tv.setText(String.format(formatString, description));
- }
- ap.mNegativeButtonText = getString(R.string.cancel);
+ });
+
+ ImageView iv = (ImageView) ap.mView.findViewById(com.android.nfc.R.id.tap_again_appicon);
+ Drawable icon = pm.getUserBadgedIcon(serviceInfo.loadIcon(pm),
+ UserHandle.getUserHandleForUid(serviceInfo.getUid()));
+
+ iv.setImageDrawable(icon);
+
setupAlert();
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
@@ -113,4 +116,4 @@ public class TapAgainDialog extends AlertActivity implements DialogInterface.OnC
public void onClick(DialogInterface dialog, int which) {
finish();
}
-} \ No newline at end of file
+}