Skip to content
This repository has been archived by the owner on Nov 8, 2023. It is now read-only.

Commit

Permalink
Merge "[Nfc framework] API to include/exclude Other category service …
Browse files Browse the repository at this point in the history
…component" into main
  • Loading branch information
Treehugger Robot authored and Gerrit Code Review committed Oct 31, 2023
2 parents 3b16630 + 0554227 commit 8c7eea4
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 35 deletions.
1 change: 1 addition & 0 deletions core/java/android/nfc/INfcCardEmulation.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ interface INfcCardEmulation
boolean unsetPreferredService();
boolean supportsAidPrefixRegistration();
ApduServiceInfo getPreferredPaymentService(int userHandle);
boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
boolean isDefaultPaymentRegistered();
}
115 changes: 80 additions & 35 deletions core/java/android/nfc/cardemulation/ApduServiceInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,34 @@ public final class ApduServiceInfo implements Parcelable {
*/
private final String mSettingsActivityName;

/**
* State of the service for CATEGORY_OTHER selection
*/
private boolean mOtherServiceSelectionState;

/**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
boolean requiresUnlock, int bannerResource, int uid,
String settingsActivityName, String offHost, String staticOffHost) {
this(info, onHost, description, staticAidGroups, dynamicAidGroups,
requiresUnlock, bannerResource, uid, settingsActivityName,
offHost, staticOffHost, false);
}

/**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
boolean requiresUnlock, int bannerResource, int uid,
String settingsActivityName, String offHost, String staticOffHost,
boolean isSelected) {
this(info, onHost, description, staticAidGroups, dynamicAidGroups,
requiresUnlock, onHost ? true : false, bannerResource, uid,
settingsActivityName, offHost, staticOffHost);
settingsActivityName, offHost, staticOffHost, isSelected);
}

/**
Expand All @@ -144,7 +162,7 @@ public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
String settingsActivityName, String offHost, String staticOffHost) {
String settingsActivityName, String offHost, String staticOffHost, boolean isSelected) {
this.mService = info;
this.mDescription = description;
this.mStaticAidGroups = new HashMap<String, AidGroup>();
Expand All @@ -163,6 +181,8 @@ public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
this.mBannerResourceId = bannerResource;
this.mUid = uid;
this.mSettingsActivityName = settingsActivityName;
this.mOtherServiceSelectionState = isSelected;

}

/**
Expand Down Expand Up @@ -351,6 +371,9 @@ public ApduServiceInfo(@NonNull PackageManager pm, @NonNull ResolveInfo info, bo
}
// Set uid
mUid = si.applicationInfo.uid;

mOtherServiceSelectionState = false; // support other category

}

/**
Expand Down Expand Up @@ -720,43 +743,47 @@ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mBannerResourceId);
dest.writeInt(mUid);
dest.writeString(mSettingsActivityName);

dest.writeInt(mOtherServiceSelectionState ? 1 : 0);
};

@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
public static final @NonNull Parcelable.Creator<ApduServiceInfo> CREATOR =
new Parcelable.Creator<ApduServiceInfo>() {
@Override
public ApduServiceInfo createFromParcel(Parcel source) {
ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
String description = source.readString();
boolean onHost = source.readInt() != 0;
String offHostName = source.readString();
String staticOffHostName = source.readString();
ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
int numStaticGroups = source.readInt();
if (numStaticGroups > 0) {
source.readTypedList(staticAidGroups, AidGroup.CREATOR);
}
ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
int numDynamicGroups = source.readInt();
if (numDynamicGroups > 0) {
source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
}
boolean requiresUnlock = source.readInt() != 0;
boolean requiresScreenOn = source.readInt() != 0;
int bannerResource = source.readInt();
int uid = source.readInt();
String settingsActivityName = source.readString();
return new ApduServiceInfo(info, onHost, description, staticAidGroups,
dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid,
settingsActivityName, offHostName, staticOffHostName);
}
@Override
public ApduServiceInfo createFromParcel(Parcel source) {
ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
String description = source.readString();
boolean onHost = source.readInt() != 0;
String offHostName = source.readString();
String staticOffHostName = source.readString();
ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
int numStaticGroups = source.readInt();
if (numStaticGroups > 0) {
source.readTypedList(staticAidGroups, AidGroup.CREATOR);
}
ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
int numDynamicGroups = source.readInt();
if (numDynamicGroups > 0) {
source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
}
boolean requiresUnlock = source.readInt() != 0;
boolean requiresScreenOn = source.readInt() != 0;
int bannerResource = source.readInt();
int uid = source.readInt();
String settingsActivityName = source.readString();
boolean isSelected = source.readInt() != 0;
return new ApduServiceInfo(info, onHost, description, staticAidGroups,
dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid,
settingsActivityName, offHostName, staticOffHostName,
isSelected);
}

@Override
public ApduServiceInfo[] newArray(int size) {
return new ApduServiceInfo[size];
}
};
@Override
public ApduServiceInfo[] newArray(int size) {
return new ApduServiceInfo[size];
}
};

/**
* Dump contents for debugging.
Expand All @@ -779,14 +806,16 @@ public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
}
pw.println(" Static AID groups:");
for (AidGroup group : mStaticAidGroups.values()) {
pw.println(" Category: " + group.getCategory());
pw.println(" Category: " + group.getCategory()
+ "(selected: " + mOtherServiceSelectionState + ")");
for (String aid : group.getAids()) {
pw.println(" AID: " + aid);
}
}
pw.println(" Dynamic AID groups:");
for (AidGroup group : mDynamicAidGroups.values()) {
pw.println(" Category: " + group.getCategory());
pw.println(" Category: " + group.getCategory()
+ "(selected: " + mOtherServiceSelectionState + ")");
for (String aid : group.getAids()) {
pw.println(" AID: " + aid);
}
Expand All @@ -796,6 +825,22 @@ public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
pw.println(" Requires Device ScreenOn: " + mRequiresDeviceScreenOn);
}


/**
* @hide
*/
public void setOtherServiceState(boolean selected) {
mOtherServiceSelectionState = selected;
}


/**
* @hide
*/
public boolean isSelectedOtherService() {
return mOtherServiceSelectionState;
}

/**
* Dump debugging info as ApduServiceInfoProto.
*
Expand Down
33 changes: 33 additions & 0 deletions core/java/android/nfc/cardemulation/CardEmulation.java
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,39 @@ public static boolean isValidAid(String aid) {
return true;
}

/**
* Allows to set or unset preferred service (category other) to avoid AID Collision.
*
* @param service The ComponentName of the service
* @param status true to enable, false to disable
* @return set service for the category and true if service is already set return false.
*
* @hide
*/
public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status) {
if (service == null) {
throw new NullPointerException("activity or service or category is null");
}
int userId = mContext.getUser().getIdentifier();

try {
return sService.setServiceEnabledForCategoryOther(userId, service, status);
} catch (RemoteException e) {
// Try one more time
recoverService();
if (sService == null) {
Log.e(TAG, "Failed to recover CardEmulationService.");
return false;
}
try {
return sService.setServiceEnabledForCategoryOther(userId, service, status);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
}
}
}

void recoverService() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
sService = adapter.getCardEmulationService();
Expand Down

0 comments on commit 8c7eea4

Please sign in to comment.