[LeEco Le Pro3 ROMs, Kernels, Recoveries, & Other D] qqzwc:
Edit:20190321: I downgrade my app to older version and smartcardservice can work again now.

I decompiled these two version and find that the old app ony try to call import org.simalliance.openmobileapi.jar

import org.simalliance.openmobileapi.Channel;
import org.simalliance.openmobileapi.Reader;
import org.simalliance.openmobileapi.SEService;
import org.simalliance.openmobileapi.SEService.CallBack;
import org.simalliance.openmobileapi.Session;

But the newer version will try to framework.jar first and got errors

import android.content.Context;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;

I've tried to "kang" smartcardservice blobs from Mi-9(cepheus) AndroidP , but got exactly the same error logcat.So I believe that my app has abandoned smartcardservice.apk's code and now using code from framework.jar (android_frameworks_base/core/java/android/se/omapi)

The logcat is from a add-on app for Chinese users to charge a Bus Card or the NFC-Bus-Card-SecureElements in the SIM1 card.

The main error is : java.lang.NullPointerException: Attempt to invoke virtual method 'android.se.omapi.Session android.se.omapi.Reader.openSession()' on a null object reference

Is this a app bug instead of lineage bug? It seems that the code has no differences with NXP updtream.....

I decompiled the classes.dex of this apk to .jar which can be opened by jd-gui.jar and find the logcat is from these codes:

package cn.com.robusoft.busrecharge.swp;

import android.content.Context;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
import android.util.Log;
import cn.com.robusoft.busrecharge.utils.LoggerHelper;
import cn.com.robusoft.busrecharge.utils.StringUtils;
import java.io.PrintStream;
import java.util.concurrent.Executors;
import org.apache.log4j.Logger;

public class c
{
private static Logger f = new LoggerHelper(c.class).getLogger();
private Object a;
private Context b;
private Channel c;
private SEService d;
private Session e;
private byte[] g = null;

private Channel a(SEService paramSEService, byte[] paramArrayOfByte)
throws Exception
{
paramSEService = a(paramSEService);
try
{
this.e = paramSEService.openSession();
paramSEService = this.e.openLogicalChannel(paramArrayOfByte);
this.c = paramSEService;
return paramSEService;
}
catch (Exception paramSEService)
{
paramSEService.printStackTrace();
throw paramSEService;
}
}

private Reader a(SEService paramSEService)
{
Reader[] arrayOfReader = paramSEService.getReaders();
int i = arrayOfReader.length;
int j = 0;
if (j < i)
{
paramSEService = arrayOfReader[j];
if (!paramSEService.getName().startsWith("SIM")) {}
}
for (;;)
{
return paramSEService;
j++;
break;
paramSEService = null;
}
}

private SEService b()
{
if (this.a == null) {
this.a = new Object();
}
SEService localSEService = new SEService(this.b, Executors.newSingleThreadExecutor(), new a());
int i = 0;
if (i < 3) {}
for (;;)
{
synchronized (this.a)
{
try
{
this.a.wait(3000L);
boolean bool = localSEService.isConnected();
if (bool)
{
System.out.println("==========" + localSEService.isConnected());
if (!localSEService.isConnected()) {
break label143;
}
this.d = localSEService;
return localSEService;
}
}
catch (InterruptedException localInterruptedException)
{
Log.v("PbocAdapter", "waitSEServiceConnected interruptted! But relax, it's Ok.");
i++;
}
}
label143:
Object localObject2 = null;
}
}

public Channel a(String paramString, Context paramContext)
throws Exception
{
Object localObject1 = null;
this.b = paramContext.getApplicationContext();
f.info("==channel init======" + paramString);
Object localObject2 = b();
if (localObject2 == null) {
paramString = (String)localObject1;
}
for (;;)
{
return paramString;
if ((paramString == null) || (paramString.length() == 0)) {
throw new Exception("appAID error");
}
paramContext = a((SEService)localObject2, Method.str2bytes(paramString));
if (paramContext == null) {
throw new Exception("GPAC Rules Error");
}
this.d = ((SEService)localObject2);
this.g = paramContext.getSelectResponse();
localObject2 = new ApduResponse(this.g);
f.info("==channel response======" + StringUtils.bytesToHexString(this.g));
paramString = (String)localObject1;
if (((ApduResponse)localObject2).isOkey()) {
paramString = paramContext;
}
}
}

public ApduResponse a(byte[] paramArrayOfByte)
{
if ((this.c == null) || (!this.c.isOpen())) {
paramArrayOfByte = new ApduResponse(null);
}
for (;;)
{
return paramArrayOfByte;
try
{
Object localObject1 = System.out;
Object localObject2 = new java/lang/StringBuilder;
((StringBuilder)localObject2).<init>();
((PrintStream)localObject1).println("Send------->" + Method.bytesToHexString(paramArrayOfByte));
localObject1 = this.c.transmit(paramArrayOfByte);
paramArrayOfByte = new cn/com/robusoft/busrecharge/swp/ApduResponse;
paramArrayOfByte.<init>((byte[])localObject1);
localObject2 = System.out;
StringBuilder localStringBuilder = new java/lang/StringBuilder;
localStringBuilder.<init>();
((PrintStream)localObject2).println("return<-------" + Method.bytesToHexString((byte[])localObject1));
}
catch (Exception paramArrayOfByte)
{
paramArrayOfByte.printStackTrace();
this.c = null;
paramArrayOfByte = new ApduResponse(null);
}
}
}

public void a()
{
if (this.c != null)
{
if (this.c.isOpen()) {
this.c.close();
}
this.c = null;
}
if (this.e != null)
{
if (!this.e.isClosed()) {
this.e.close();
}
this.e = null;
}
if (this.d != null)
{
if (this.d.isConnected()) {
this.d.shutdown();
}
this.d = null;
}
this.a = null;
this.b = null;
}

public ApduResponse b(String paramString, Context paramContext)
throws Exception
{
Object localObject = null;
this.b = paramContext.getApplicationContext();
f.info("==channel init======" + paramString);
paramContext = b();
if (paramContext == null) {
paramString = (String)localObject;
}
for (;;)
{
return paramString;
if ((paramString == null) || (paramString.length() == 0)) {
throw new Exception("appAID error");
}
paramString = a(paramContext, Method.str2bytes(paramString));
if (paramString == null) {
throw new Exception("GPAC Rules Error");
}
this.d = paramContext;
paramString = paramString.getSelectResponse();
paramContext = new ApduResponse(paramString);
f.info("==channel response======" + StringUtils.bytesToHexString(paramString));
paramString = (String)localObject;
if (paramContext.isOkey()) {
paramString = paramContext;
}
}
}

private class a
implements SEService.OnConnectedListener
{
public a() {}

public void onConnected()
{
synchronized (c.a(c.this))
{
c.a(c.this).notifyAll();
return;
}
}
}
}

Error logcat:

I cn.com.ctbri.pptoc.fragment.PhysicalCardFragment: ===========getAdsByCityName.size=2
E DatabaseUtils: WritingException to parcel
I cn.com.robusoft.busrecharge.swp.c: ==channel init======9156000014010001
I OMAPI.SEService: Service onServiceConnected
I OMAPI.SEService: bindService successful
W System.err:	at cn.com.robusoft.busrecharge.swp.c.a(Unknown Source:4)
W System.err:	at cn.com.robusoft.busrecharge.swp.c.a(Unknown Source:58)
W System.err:	at cn.com.robusoft.busrecharge.swp.PbocCardEDEP.b(Unknown Source:14)
W System.err:	at cn.com.robusoft.busrecharge.swp.PbocCardEDEP.init(Unknown Source:10)
W System.err:	at cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr$SearchProcess.getCityCode(Unknown Source:776)
W System.err:	at cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr$SearchProcess.queryTrans(Unknown Source:18)
W System.err:	at cn.com.robusoft.busrecharge.transport.mgr.TransportMgr.queryTrans(Unknown Source:6)
W System.err:	at cn.com.ctbri.pp2transitcard.tools.utils.ReadCardUtils$1.doInBackground(Unknown Source:136)
W System.err:	at cn.com.ctbri.pp2transitcard.tools.utils.ReadCardUtils$1.doInBackground(Unknown Source:2)
W System.err:	at android.os.AsyncTask$2.call(AsyncTask.java:333)
W System.err:	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W System.err:	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
W System.err:	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W System.err:	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W System.err:	at java.lang.Thread.run(Thread.java:764)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr: java.lang.NullPointerException: Attempt to invoke virtual method 'android.se.omapi.Session android.se.omapi.Reader.openSession()' on a null object reference
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.robusoft.busrecharge.swp.c.a(Unknown Source:4)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.robusoft.busrecharge.swp.c.a(Unknown Source:58)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.robusoft.busrecharge.swp.PbocCardEDEP.b(Unknown Source:14)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.robusoft.busrecharge.swp.PbocCardEDEP.init(Unknown Source:10)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr$SearchProcess.getCityCode(Unknown Source:776)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr$SearchProcess.queryTrans(Unknown Source:18)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.robusoft.busrecharge.transport.mgr.TransportMgr.queryTrans(Unknown Source:6)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.ctbri.pp2transitcard.tools.utils.ReadCardUtils$1.doInBackground(Unknown Source:136)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at cn.com.ctbri.pp2transitcard.tools.utils.ReadCardUtils$1.doInBackground(Unknown Source:2)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at android.os.AsyncTask$2.call(AsyncTask.java:333)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:	at java.lang.Thread.run(Thread.java:764)
E cn.com.ctbri.pp2transitcard.tools.mgr.SearchMgr:
I a : --SharkeySDK>>getConnStatus......

BTW: I found that in android_frameworks_base/core/java/android/nfc/NfcAdapter.java ,line228,it says

public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";

, and in NQNfcNci.apk , android_vendor_nxp_opensource_packages_apps_Nfc/src/com/android/nfc/NfcService.java ,line 4065

it says

String seName = seIntent.getStringExtra("com.android.nfc_extras.extra.SECURE_ELEMENT_NAME");

So in my opinion, NXP NQNfcNci.apk have more supported function than AOSP NfcNci.apk such as secure elements in the SIM card. See android_frameworks_base/core/java/android/nfc/NfcAdapter.java ,line 223

/**
* Mandatory String extra field in {@link #ACTION_TRANSACTION_DETECTED}
* Indicates the Secure Element on which the transaction occurred.
* eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
*/

See attached files .