diff --git a/extract-files.sh b/extract-files.sh index 259ffded..3fe776d9 100755 --- a/extract-files.sh +++ b/extract-files.sh @@ -78,6 +78,15 @@ function blob_fixup() { "${PATCHELF}" --remove-needed "android.hidl.base@1.0.so" "${2}" ;; + vendor/bin/mlipayd@1.1) + "${PATCHELF}" --remove-needed vendor.xiaomi.hardware.mtdservice@1.0.so "${2}" + ;; + + vendor/lib64/libmlipay.so | vendor/lib64/libmlipay@1.1.so) + "${PATCHELF}" --remove-needed vendor.xiaomi.hardware.mtdservice@1.0.so "${2}" + sed -i "s|/system/etc/firmware|/vendor/firmware\x0\x0\x0\x0|g" "${2}" + ;; + vendor/lib/hw/camera.sdm660.so) "${PATCHELF}" --add-needed camera.sdm660_shim.so "${2}" ;; diff --git a/manifest.xml b/manifest.xml index fe0986f6..dcf127d0 100755 --- a/manifest.xml +++ b/manifest.xml @@ -282,4 +282,9 @@ hwbinder @3.0::IRTPService/imsrtpservice + + vendor.xiaomi.hardware.mlipay + hwbinder + @1.1::IMlipayService/default + diff --git a/org.ifaa.android.manager/Android.bp b/org.ifaa.android.manager/Android.bp new file mode 100644 index 00000000..359f920b --- /dev/null +++ b/org.ifaa.android.manager/Android.bp @@ -0,0 +1,21 @@ +/* +* Copyright (C) 2017-2020 The LineageOS Project +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +java_library { + name: "org.ifaa.android.manager", + installable: true, + srcs: [ + "src/**/*.java", + "src/**/I*.aidl", + ], + libs: [ + "unsupportedappusage", + ], + aidl: { + local_include_dirs: ["src"], + }, +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java new file mode 100644 index 00000000..82cb659d --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java @@ -0,0 +1,69 @@ +package org.ifaa.android.manager; + +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; +import android.os.Build.VERSION; +import android.os.SystemProperties; + +public abstract class IFAAManager { + private static final int IFAA_VERSION_V2 = 2; + private static final int IFAA_VERSION_V3 = 3; + private static final int IFAA_VERSION_V4 = 4; + + static int sIfaaVer; + static boolean sIsFod = SystemProperties.getBoolean("ro.hardware.fp.fod", false); + + /** + * 返回手机系统上支持的校验方式,目前IFAF协议1.0版本指纹为0x01、虹膜为0x02 + */ + @UnsupportedAppUsage + public abstract int getSupportBIOTypes(Context context); + + /** + * 启动系统的指纹/虹膜管理应用界面,让用户进行指纹录入。指纹录入是在系统的指纹管理应用中实现的, + * 本函数的作用只是将指纹管理应用运行起来,直接进行页面跳转,方便用户录入。 + * @param context + * @param authType 生物特征识别类型,指纹为1,虹膜为2 + * @return 0,成功启动指纹管理应用;-1,启动指纹管理应用失败。 + */ + @UnsupportedAppUsage + public abstract int startBIOManager(Context context, int authType); + + /** + * 通过ifaateeclient的so文件实现REE到TA的通道 + * @param context + * @param param 用于传输到IFAA TA的数据buffer + * @return IFAA TA返回给REE数据buffer + */ + @UnsupportedAppUsage + public native byte[] processCmd(Context context, byte[] param); + + /** + * 获取设备型号,同一款机型型号需要保持一致 + */ + @UnsupportedAppUsage + public abstract String getDeviceModel(); + + /** + * 获取IFAAManager接口定义版本,目前为1 + */ + @UnsupportedAppUsage + public abstract int getVersion(); + + /** + * load so to communicate from REE to TEE + */ + static { + sIfaaVer = 1; + + if (VERSION.SDK_INT >= 28) { + sIfaaVer = IFAA_VERSION_V4; + } else if (sIsFod) { + sIfaaVer = IFAA_VERSION_V3; + } else if (VERSION.SDK_INT >= 24) { + sIfaaVer = IFAA_VERSION_V2; + } else { + System.loadLibrary("teeclientjni"); //teeclientjni for TA test binary //ifaateeclient + } + } +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java new file mode 100644 index 00000000..36978741 --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java @@ -0,0 +1,11 @@ +package org.ifaa.android.manager; + +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; + +public class IFAAManagerFactory { + @UnsupportedAppUsage + public static IFAAManager getIFAAManager(Context context, int authType) { + return IFAAManagerImpl.getInstance(context); + } +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerImpl.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerImpl.java new file mode 100644 index 00000000..123c6afe --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerImpl.java @@ -0,0 +1,322 @@ +package org.ifaa.android.manager; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Build; +import android.os.Build.VERSION; +import android.os.HwBinder; +import android.os.HwBlob; +import android.os.HwParcel; +import android.os.IBinder; +import android.os.IBinder.DeathRecipient; +import android.os.IHwBinder; +import android.os.Parcel; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.util.Slog; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.json.JSONObject; + +public class IFAAManagerImpl extends IFAAManagerV4 { + private static final int CODE_PROCESS_CMD = 1; + private static final int CODE_GETIDLIST_CMD = 2; + + private static final int IFAA_TYPE_FINGER = 1; + private static final int IFAA_TYPE_IRIS = 2; + private static final int IFAA_TYPE_SENSOR_FOD = 16; + + private static final int ACTIVITY_START_SUCCESS = 0; + private static final int ACTIVITY_START_FAILED = -1; + + private static volatile IFAAManagerImpl INSTANCE = null; + + private static final String CA_CERT_ALIAS_DELIMITER = " "; + + private static final String INTERFACE_DESCRIPTOR = + "vendor.xiaomi.hardware.mlipay@1.1::IMlipayService"; + private static final String SERVICE_NAME = + "vendor.xiaomi.hardware.mlipay@1.1::IMlipayService"; + private static final String TAG = "IfaaManagerImpl"; + + private static final String mIfaaActName = "org.ifaa.android.manager.IFAAService"; + private static final String mIfaaInterfaceDesc = "org.ifaa.android.manager.IIFAAService"; + private static final String mIfaaPackName = "com.tencent.soter.soterserver"; + + private static IBinder mService = null; + private String mDevModel = null; + private static Context mContext = null; + + private static ServiceConnection ifaaconn = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + mService = service; + try { + mService.linkToDeath(mDeathRecipient, 0); + } catch (RemoteException e) { + Slog.e(TAG, "linkToDeath fail.", e); + } + } + + public void onServiceDisconnected(ComponentName name) { + if (mContext != null) { + Slog.i(TAG, "re-bind the service."); + initService(); + } + } + }; + + private static DeathRecipient mDeathRecipient = new DeathRecipient() { + public void binderDied() { + if (mService != null) { + Slog.d(TAG, "binderDied, unlink the service."); + mService.unlinkToDeath(mDeathRecipient, 0); + } + } + }; + + public static IFAAManagerV4 getInstance(Context context) { + if (INSTANCE == null) { + synchronized (IFAAManagerImpl.class) { + if (INSTANCE == null) { + INSTANCE = new IFAAManagerImpl(); + if (VERSION.SDK_INT >= 28) { + mContext = context; + initService(); + } + } + } + } + + return INSTANCE; + } + + private String initExtString() { + String extStr = ""; + JSONObject obj = new JSONObject(); + JSONObject keyInfo = new JSONObject(); + String xy = ""; + String wh = ""; + + if (VERSION.SDK_INT >= 28) { + xy = SystemProperties.get("persist.vendor.sys.fp.fod.location.X_Y", ""); + wh = SystemProperties.get("persist.vendor.sys.fp.fod.size.width_height", ""); + } else { + xy = SystemProperties.get("persist.sys.fp.fod.location.X_Y", ""); + wh = SystemProperties.get("persist.sys.fp.fod.size.width_height", ""); + } + + try { + if (validateVal(xy) && validateVal(wh)) { + String[] splitXy = xy.split(","); + String[] splitWh = wh.split(","); + keyInfo.put("startX", Integer.parseInt(splitXy[0])); + keyInfo.put("startY", Integer.parseInt(splitXy[1])); + keyInfo.put("width", Integer.parseInt(splitWh[0])); + keyInfo.put("height", Integer.parseInt(splitWh[1])); + keyInfo.put("navConflict", true); + obj.put("type", 0); + obj.put("fullView", keyInfo); + extStr = obj.toString(); + } else { + Slog.e(TAG, "initExtString invalidate, xy:" + xy + " wh:" + wh); + } + } catch (Exception e) { + Slog.e(TAG, "Exception , xy:" + xy + " wh:" + wh, e); + } + + return extStr; + } + + private static void initService() { + Intent ifaaIntent = new Intent(); + ifaaIntent.setClassName(mIfaaPackName, mIfaaActName); + if (!mContext.bindService(ifaaIntent, ifaaconn, 1)) { + Slog.e(TAG, "cannot bind service org.ifaa.android.manager.IFAAService"); + } + } + + private boolean validateVal(String value) { + return !"".equalsIgnoreCase(value) && value.contains(","); + } + + public String getDeviceModel() { + if (mDevModel == null) { + mDevModel = Build.MANUFACTURER + "-" + Build.DEVICE; + } + + Slog.i(TAG, "getDeviceModel deviceModel:" + mDevModel); + return mDevModel; + } + + public int getEnabled(int bioType) { + return 1 == bioType ? 1000 : 1003; + } + + public String getExtInfo(int authType, String keyExtInfo) { + Slog.i(TAG, "getExtInfo:" + authType + CA_CERT_ALIAS_DELIMITER + keyExtInfo); + return initExtString(); + } + + public int[] getIDList(int bioType) { + int[] idList = new int[]{0}; + if (1 == bioType) { + int retry_count = 10; + while (true) { + int retry_count2 = retry_count - 1; + if (retry_count <= 0) { + break; + } + if (mService == null || !mService.pingBinder()) { + try { + Thread.sleep(30); + } catch (InterruptedException e) { + Slog.e(TAG, "getIDList InterruptedException while waiting: " + e, e); + } + } else { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + try { + data.writeInterfaceToken(mIfaaInterfaceDesc); + data.writeInt(bioType); + mService.transact(CODE_GETIDLIST_CMD, data, reply, 0); + reply.readException(); + idList = reply.createIntArray(); + } catch (RemoteException e) { + Slog.e(TAG, "getIDList transact failed. ", e); + } catch (Throwable th) { + data.recycle(); + reply.recycle(); + } + data.recycle(); + reply.recycle(); + } + retry_count = retry_count2; + } + } + return idList; + } + + public int getSupportBIOTypes(Context context) { + int ifaaProp; + String fpVendor = ""; + + if (VERSION.SDK_INT >= 28) { + ifaaProp = SystemProperties.getInt("persist.vendor.sys.pay.ifaa", 0); + fpVendor = SystemProperties.get("persist.vendor.sys.fp.vendor", ""); + } else { + ifaaProp = SystemProperties.getInt("persist.sys.ifaa", 0); + fpVendor = SystemProperties.get("persist.sys.fp.vendor", ""); + } + + int res = "none".equalsIgnoreCase(fpVendor) ? + ifaaProp & IFAA_TYPE_IRIS : ifaaProp & (IFAA_TYPE_FINGER | IFAA_TYPE_IRIS); + + if ((res & IFAA_TYPE_FINGER) == IFAA_TYPE_FINGER && sIsFod) { + res |= IFAA_TYPE_SENSOR_FOD; + } + + Slog.i(TAG, "getSupportBIOTypes:" + ifaaProp + ", " + sIsFod + ", " + fpVendor + + ", res:" + res); + return res; + } + + public int getVersion() { + Slog.i(TAG, "getVersion sdk:" + VERSION.SDK_INT + " ifaaVer:" + sIfaaVer); + return sIfaaVer; + } + + public byte[] processCmdV2(Context context, byte[] param) { + Slog.i(TAG, "processCmdV2 sdk:" + VERSION.SDK_INT); + + if (VERSION.SDK_INT >= 28) { + int retry_count = 10; + + while (true) { + int retry_count2 = retry_count - 1; + if (retry_count <= 0) { + break; + } + if (mService == null || !mService.pingBinder()) { + Slog.i(TAG, "processCmdV2 waiting ifaaService, remain: " + retry_count2 + + " time(s)"); + try { + Thread.sleep(30); + } catch (InterruptedException e) { + Slog.e(TAG, "processCmdV2 InterruptedException while waiting: " + e, e); + } + } else { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + try { + data.writeInterfaceToken(mIfaaInterfaceDesc); + data.writeByteArray(param); + mService.transact(CODE_PROCESS_CMD, data, reply, 0); + reply.readException(); + return reply.createByteArray(); + } catch (RemoteException e) { + Slog.e(TAG, "processCmdV2 transact failed. ", e); + retry_count = retry_count2; + } finally { + data.recycle(); + reply.recycle(); + } + } + retry_count = retry_count2; + } + + Slog.e(TAG, "processCmdV2, return null"); + return null; + } + + HwParcel hidl_reply = new HwParcel(); + try { + IHwBinder hwService = HwBinder.getService(SERVICE_NAME, "default"); + if (hwService != null) { + HwParcel hidl_request = new HwParcel(); + hidl_request.writeInterfaceToken(INTERFACE_DESCRIPTOR); + ArrayList sbuf = new ArrayList(Arrays.asList(HwBlob.wrapArray(param))); + hidl_request.writeInt8Vector(sbuf); + hidl_request.writeInt32(sbuf.size()); + hwService.transact(CODE_PROCESS_CMD, hidl_request, hidl_reply, 0); + hidl_reply.verifySuccess(); + hidl_request.releaseTemporaryStorage(); + ArrayList val = hidl_reply.readInt8Vector(); + byte[] array = new byte[val.size()]; + for (int i = 0; i < val.size(); i++) { + array[i] = ((Byte) val.get(i)).byteValue(); + } + hidl_reply.release(); + return array; + } + } catch (RemoteException e) { + Slog.e(TAG, "transact failed. ", e); + } catch (Throwable th) { + hidl_reply.release(); + } + + hidl_reply.release(); + Slog.e(TAG, "processCmdV2, return null"); + return null; + } + + public void setExtInfo(int authType, String keyExtInfo, String valExtInfo) { + } + + public int startBIOManager(Context context, int authType) { + int res = ACTIVITY_START_FAILED; + + if (authType == IFAA_TYPE_FINGER) { + Intent intent = new Intent("android.settings.SECURITY_SETTINGS"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + res = ACTIVITY_START_SUCCESS; + } + + Slog.i(TAG, "startBIOManager authType:" + authType + " res:" + res); + return res; + } +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV2.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV2.java new file mode 100644 index 00000000..d634ef0d --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV2.java @@ -0,0 +1,9 @@ +package org.ifaa.android.manager; + +import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; + +public abstract class IFAAManagerV2 extends IFAAManager { + @UnsupportedAppUsage + public abstract byte[] processCmdV2(Context paramContext, byte[] paramArrayOfByte); +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV3.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV3.java new file mode 100644 index 00000000..328fd75b --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV3.java @@ -0,0 +1,20 @@ +package org.ifaa.android.manager; + +import android.compat.annotation.UnsupportedAppUsage; + +public abstract class IFAAManagerV3 extends IFAAManagerV2 { + @UnsupportedAppUsage + public static final String KEY_FINGERPRINT_FULLVIEW = "org.ifaa.ext.key.CUSTOM_VIEW"; + @UnsupportedAppUsage + public static final String KEY_GET_SENSOR_LOCATION = "org.ifaa.ext.key.GET_SENSOR_LOCATION"; + @UnsupportedAppUsage + public static final String VALUE_FINGERPRINT_DISABLE = "disable"; + @UnsupportedAppUsage + public static final String VLAUE_FINGERPRINT_ENABLE = "enable"; + + @UnsupportedAppUsage + public abstract String getExtInfo(int authType, String keyExtInfo); + + @UnsupportedAppUsage + public abstract void setExtInfo(int authType, String keyExtInfo, String valExtInfo); +} diff --git a/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV4.java b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV4.java new file mode 100644 index 00000000..2c47557c --- /dev/null +++ b/org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV4.java @@ -0,0 +1,11 @@ +package org.ifaa.android.manager; + +import android.compat.annotation.UnsupportedAppUsage; + +public abstract class IFAAManagerV4 extends IFAAManagerV3 { + @UnsupportedAppUsage + public abstract int getEnabled(int i); + + @UnsupportedAppUsage + public abstract int[] getIDList(int i); +} diff --git a/proprietary-files.txt b/proprietary-files.txt index 4b64ff64..3db198ed 100644 --- a/proprietary-files.txt +++ b/proprietary-files.txt @@ -520,6 +520,14 @@ vendor/lib64/libOmxQcelp13Dec.so|5a8e892912cd56c74b72420ea4fea62918bf260e vendor/lib64/libOmxWmaDec.so|12f994f034be6249acf8f25306bce4a38405e099 vendor/lib64/libmm-color-convertor.so|d7404046e5863a87922b35c3ff3edc5e76d6c249 +# Mlipay - from wayne V9.7.4 +vendor/bin/mlipayd@1.1|13e9167024fd2dc49a56ed27e583057408dcc1eb +vendor/etc/init/vendor.xiaomi.hardware.mlipay@1.1-service.rc|b5ab5bcd031fe4d9781b5911c0595eaeac8b80ea +vendor/lib64/libmlipay.so|6cacf75f4a7eb50cbb7de384a3cfc1702a3a5f4a +vendor/lib64/libmlipay@1.1.so|4dfa016779bcba8da2ff293e5112c678044c6474 +vendor/lib64/vendor.xiaomi.hardware.mlipay@1.0.so|d0bb854210433066945f9d6e7943d08a8435e746 +vendor/lib64/vendor.xiaomi.hardware.mlipay@1.1.so|785984e3c3b30671b78624484899dd418979cb56 + # Perf - from LA.UM.8.6.2.r1-08600-89xx.0 vendor/lib64/libadaptlaunch.so|cf784401fc827e5195d595a6d855ec89ea8c22bf vendor/lib64/libappclassifier.so|d5956c2dc9344ddcca0e78d84c393320c2e0cc97 diff --git a/sdm660.mk b/sdm660.mk index 4e7f309c..db378f71 100644 --- a/sdm660.mk +++ b/sdm660.mk @@ -288,6 +288,11 @@ PRODUCT_COPY_FILES += \ $(COMMON_PATH)/configs/idc/uinput-fpc.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/uinput-fpc.idc \ $(COMMON_PATH)/configs/idc/uinput-goodix.idc:$(TARGET_COPY_OUT_VENDOR)/usr/idc/uinput-goodix.idc +# IFAAService +PRODUCT_PACKAGES += \ + IFAAService \ + org.ifaa.android.manager + # IMS PRODUCT_PACKAGES += \ ims-ext-common \ diff --git a/sepolicy/private/system_app.te b/sepolicy/private/system_app.te index 39dedf5b..cec1ec5a 100644 --- a/sepolicy/private/system_app.te +++ b/sepolicy/private/system_app.te @@ -1 +1,2 @@ +hal_client_domain(system_app, hal_mlipay) binder_call(system_app, storaged) diff --git a/sepolicy/public/attributes b/sepolicy/public/attributes new file mode 100644 index 00000000..1a0c38aa --- /dev/null +++ b/sepolicy/public/attributes @@ -0,0 +1 @@ +hal_attribute_lineage(mlipay) diff --git a/sepolicy/vendor/app.te b/sepolicy/vendor/app.te index df5807fa..def8a3eb 100644 --- a/sepolicy/vendor/app.te +++ b/sepolicy/vendor/app.te @@ -1,4 +1,5 @@ get_prop({ appdomain -isolated_app }, hal_fingerprint_prop) +get_prop({ appdomain -isolated_app }, mlipay_prop) allow { appdomain -isolated_app } adsprpcd_file:dir r_dir_perms; allow { appdomain -isolated_app } public_adsprpcd_file:file r_file_perms; diff --git a/sepolicy/vendor/file_contexts b/sepolicy/vendor/file_contexts index a8161e00..1b5d6ca1 100644 --- a/sepolicy/vendor/file_contexts +++ b/sepolicy/vendor/file_contexts @@ -61,6 +61,9 @@ # Lights /vendor/bin/hw/android\.hardware\.light-service\.xiaomi u:object_r:hal_light_default_exec:s0 +# Mlipay +/(vendor|system/vendor)/bin/mlipayd@1.1 u:object_r:hal_mlipay_default_exec:s0 + # Notification LED /sys/devices/platform/soc/800f000.qcom,spmi/spmi-0/spmi0-03/800f000.qcom,spmi:qcom,pm660l@3:qcom,leds@d000/leds/blue(/.*)? u:object_r:sysfs_graphics:s0 /sys/devices/platform/soc/800f000.qcom,spmi/spmi-0/spmi0-03/800f000.qcom,spmi:qcom,pm660l@3:qcom,leds@d000/leds/green(/.*)? u:object_r:sysfs_graphics:s0 diff --git a/sepolicy/vendor/hal_mlipay.te b/sepolicy/vendor/hal_mlipay.te new file mode 100644 index 00000000..18d04133 --- /dev/null +++ b/sepolicy/vendor/hal_mlipay.te @@ -0,0 +1,20 @@ +type hal_mlipay_default, domain; +hal_server_domain(hal_mlipay_default, hal_mlipay) + +type hal_mlipay_default_exec, exec_type, vendor_file_type, file_type; +init_daemon_domain(hal_mlipay_default) + +# Allow hwbinder call from hal client to server +binder_call(hal_mlipay_client, hal_mlipay_server) + +# Add hwservice related rules +add_hwservice(hal_mlipay_server, hal_mlipay_hwservice) +allow hal_mlipay_client hal_mlipay_hwservice:hwservice_manager find; + +allow hal_mlipay_default tee_device:chr_file rw_file_perms; +allow hal_mlipay_default ion_device:chr_file r_file_perms; + +r_dir_file(hal_mlipay_default, firmware_file) +set_prop(hal_mlipay_default, mlipay_prop); + +get_prop(hal_mlipay_default, hal_fingerprint_prop);