└── org.ifaa.android.manager ├── src └── org │ └── ifaa │ └── android │ └── manager │ ├── IFAAManagerV2.java │ ├── IFAAManagerV4.java │ ├── IFAAManagerFactory.java │ ├── IIFAAService.aidl │ ├── IFAAManagerV3.java │ ├── IFAAManager.java │ └── IFAAManagerImpl.java └── Android.bp /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV2.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.compat.annotation.UnsupportedAppUsage; 4 | import android.content.Context; 5 | 6 | public abstract class IFAAManagerV2 extends IFAAManager { 7 | @UnsupportedAppUsage 8 | public abstract byte[] processCmdV2(Context paramContext, byte[] paramArrayOfByte); 9 | } 10 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV4.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.compat.annotation.UnsupportedAppUsage; 4 | 5 | public abstract class IFAAManagerV4 extends IFAAManagerV3 { 6 | @UnsupportedAppUsage 7 | public abstract int getEnabled(int i); 8 | 9 | @UnsupportedAppUsage 10 | public abstract int[] getIDList(int i); 11 | } 12 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerFactory.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.compat.annotation.UnsupportedAppUsage; 4 | import android.content.Context; 5 | 6 | public class IFAAManagerFactory { 7 | @UnsupportedAppUsage 8 | public static IFAAManager getIFAAManager(Context context, int authType) { 9 | return IFAAManagerImpl.getInstance(context); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IIFAAService.aidl: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | interface IIFAAService { 4 | byte[] processCmd_v2(in byte[] param); 5 | int[] getIDList(int bioType); 6 | int faceEnroll(String sessionId, int flags); 7 | int faceUpgrade(int action, String path, int offset, in byte[] data, int data_len); 8 | int faceAuthenticate_v2(String sessionId, int flags); 9 | int faceCancel_v2(String sessionId); 10 | byte[] faceInvokeCommand(in byte[] param); 11 | int faceGetCellinfo(); 12 | } 13 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerV3.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.compat.annotation.UnsupportedAppUsage; 4 | 5 | public abstract class IFAAManagerV3 extends IFAAManagerV2 { 6 | @UnsupportedAppUsage 7 | public static final String KEY_FINGERPRINT_FULLVIEW = "org.ifaa.ext.key.CUSTOM_VIEW"; 8 | @UnsupportedAppUsage 9 | public static final String KEY_GET_SENSOR_LOCATION = "org.ifaa.ext.key.GET_SENSOR_LOCATION"; 10 | @UnsupportedAppUsage 11 | public static final String VALUE_FINGERPRINT_DISABLE = "disable"; 12 | @UnsupportedAppUsage 13 | public static final String VLAUE_FINGERPRINT_ENABLE = "enable"; 14 | 15 | @UnsupportedAppUsage 16 | public abstract String getExtInfo(int authType, String keyExtInfo); 17 | 18 | @UnsupportedAppUsage 19 | public abstract void setExtInfo(int authType, String keyExtInfo, String valExtInfo); 20 | } 21 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/Android.bp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017-2020 The LineageOS Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | java_library { 18 | name: "org.ifaa.android.manager", 19 | installable: true, 20 | srcs: [ 21 | "src/**/*.java", 22 | "src/**/I*.aidl", 23 | ], 24 | libs: [ 25 | "unsupportedappusage", 26 | ], 27 | aidl: { 28 | local_include_dirs: ["src"], 29 | }, 30 | } 31 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManager.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.compat.annotation.UnsupportedAppUsage; 4 | import android.content.Context; 5 | import android.os.Build.VERSION; 6 | import android.os.SystemProperties; 7 | 8 | public abstract class IFAAManager { 9 | private static final int IFAA_VERSION_V2 = 2; 10 | private static final int IFAA_VERSION_V3 = 3; 11 | private static final int IFAA_VERSION_V4 = 4; 12 | 13 | static int sIfaaVer; 14 | static boolean sIsFod = SystemProperties.getBoolean("ro.hardware.fp.fod", false); 15 | 16 | /** 17 | * 返回手机系统上支持的校验方式,目前IFAF协议1.0版本指纹为0x01、虹膜为0x02 18 | */ 19 | @UnsupportedAppUsage 20 | public abstract int getSupportBIOTypes(Context context); 21 | 22 | /** 23 | * 启动系统的指纹/虹膜管理应用界面,让用户进行指纹录入。指纹录入是在系统的指纹管理应用中实现的, 24 | * 本函数的作用只是将指纹管理应用运行起来,直接进行页面跳转,方便用户录入。 25 | * @param context 26 | * @param authType 生物特征识别类型,指纹为1,虹膜为2 27 | * @return 0,成功启动指纹管理应用;-1,启动指纹管理应用失败。 28 | */ 29 | @UnsupportedAppUsage 30 | public abstract int startBIOManager(Context context, int authType); 31 | 32 | /** 33 | * 通过ifaateeclient的so文件实现REE到TA的通道 34 | * @param context 35 | * @param param 用于传输到IFAA TA的数据buffer 36 | * @return IFAA TA返回给REE数据buffer 37 | */ 38 | @UnsupportedAppUsage 39 | public native byte[] processCmd(Context context, byte[] param); 40 | 41 | /** 42 | * 获取设备型号,同一款机型型号需要保持一致 43 | */ 44 | @UnsupportedAppUsage 45 | public abstract String getDeviceModel(); 46 | 47 | /** 48 | * 获取IFAAManager接口定义版本,目前为1 49 | */ 50 | @UnsupportedAppUsage 51 | public abstract int getVersion(); 52 | 53 | /** 54 | * load so to communicate from REE to TEE 55 | */ 56 | static { 57 | sIfaaVer = 1; 58 | 59 | if (VERSION.SDK_INT >= 28) { 60 | sIfaaVer = IFAA_VERSION_V4; 61 | } else if (sIsFod) { 62 | sIfaaVer = IFAA_VERSION_V3; 63 | } else if (VERSION.SDK_INT >= 24) { 64 | sIfaaVer = IFAA_VERSION_V2; 65 | } else { 66 | System.loadLibrary("teeclientjni"); //teeclientjni for TA test binary //ifaateeclient 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /org.ifaa.android.manager/src/org/ifaa/android/manager/IFAAManagerImpl.java: -------------------------------------------------------------------------------- 1 | package org.ifaa.android.manager; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.ServiceConnection; 7 | import android.os.Build; 8 | import android.os.Build.VERSION; 9 | import android.os.HwBinder; 10 | import android.os.HwBlob; 11 | import android.os.HwParcel; 12 | import android.os.IBinder; 13 | import android.os.IBinder.DeathRecipient; 14 | import android.os.IHwBinder; 15 | import android.os.Parcel; 16 | import android.os.RemoteException; 17 | import android.os.SystemProperties; 18 | import android.util.Slog; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Arrays; 22 | 23 | import org.json.JSONObject; 24 | 25 | public class IFAAManagerImpl extends IFAAManagerV4 { 26 | private static final int CODE_PROCESS_CMD = 1; 27 | private static final int CODE_GETIDLIST_CMD = 2; 28 | 29 | private static final int IFAA_TYPE_FINGER = 1; 30 | private static final int IFAA_TYPE_IRIS = 2; 31 | private static final int IFAA_TYPE_SENSOR_FOD = 16; 32 | 33 | private static final int ACTIVITY_START_SUCCESS = 0; 34 | private static final int ACTIVITY_START_FAILED = -1; 35 | 36 | private static volatile IFAAManagerImpl INSTANCE = null; 37 | 38 | private static final String CA_CERT_ALIAS_DELIMITER = " "; 39 | 40 | private static final String INTERFACE_DESCRIPTOR = 41 | "vendor.xiaomi.hardware.mlipay@1.0::IMlipayService"; 42 | private static final String SERVICE_NAME = 43 | "vendor.xiaomi.hardware.mlipay@1.0::IMlipayService"; 44 | private static final String TAG = "IfaaManagerImpl"; 45 | 46 | private static final String mIfaaActName = "org.ifaa.android.manager.IFAAService"; 47 | private static final String mIfaaInterfaceDesc = "org.ifaa.android.manager.IIFAAService"; 48 | private static final String mIfaaPackName = "com.tencent.soter.soterserver"; 49 | 50 | private static IBinder mService = null; 51 | private String mDevModel = null; 52 | private static Context mContext = null; 53 | 54 | private static ServiceConnection ifaaconn = new ServiceConnection() { 55 | public void onServiceConnected(ComponentName name, IBinder service) { 56 | mService = service; 57 | try { 58 | mService.linkToDeath(mDeathRecipient, 0); 59 | } catch (RemoteException e) { 60 | Slog.e(TAG, "linkToDeath fail.", e); 61 | } 62 | } 63 | 64 | public void onServiceDisconnected(ComponentName name) { 65 | if (mContext != null) { 66 | Slog.i(TAG, "re-bind the service."); 67 | initService(); 68 | } 69 | } 70 | }; 71 | 72 | private static DeathRecipient mDeathRecipient = new DeathRecipient() { 73 | public void binderDied() { 74 | if (mService != null) { 75 | Slog.d(TAG, "binderDied, unlink the service."); 76 | mService.unlinkToDeath(mDeathRecipient, 0); 77 | } 78 | } 79 | }; 80 | 81 | public static IFAAManagerV4 getInstance(Context context) { 82 | if (INSTANCE == null) { 83 | synchronized (IFAAManagerImpl.class) { 84 | if (INSTANCE == null) { 85 | INSTANCE = new IFAAManagerImpl(); 86 | if (VERSION.SDK_INT >= 28) { 87 | mContext = context; 88 | initService(); 89 | } 90 | } 91 | } 92 | } 93 | 94 | return INSTANCE; 95 | } 96 | 97 | private String initExtString() { 98 | String extStr = ""; 99 | JSONObject obj = new JSONObject(); 100 | JSONObject keyInfo = new JSONObject(); 101 | String xy = ""; 102 | String wh = ""; 103 | 104 | if (VERSION.SDK_INT >= 28) { 105 | xy = SystemProperties.get("persist.vendor.sys.fp.fod.location.X_Y", ""); 106 | wh = SystemProperties.get("persist.vendor.sys.fp.fod.size.width_height", ""); 107 | } else { 108 | xy = SystemProperties.get("persist.sys.fp.fod.location.X_Y", ""); 109 | wh = SystemProperties.get("persist.sys.fp.fod.size.width_height", ""); 110 | } 111 | 112 | try { 113 | if (validateVal(xy) && validateVal(wh)) { 114 | String[] splitXy = xy.split(","); 115 | String[] splitWh = wh.split(","); 116 | keyInfo.put("startX", Integer.parseInt(splitXy[0])); 117 | keyInfo.put("startY", Integer.parseInt(splitXy[1])); 118 | keyInfo.put("width", Integer.parseInt(splitWh[0])); 119 | keyInfo.put("height", Integer.parseInt(splitWh[1])); 120 | keyInfo.put("navConflict", true); 121 | obj.put("type", 0); 122 | obj.put("fullView", keyInfo); 123 | extStr = obj.toString(); 124 | } else { 125 | Slog.e(TAG, "initExtString invalidate, xy:" + xy + " wh:" + wh); 126 | } 127 | } catch (Exception e) { 128 | Slog.e(TAG, "Exception , xy:" + xy + " wh:" + wh, e); 129 | } 130 | 131 | return extStr; 132 | } 133 | 134 | private static void initService() { 135 | Intent ifaaIntent = new Intent(); 136 | ifaaIntent.setClassName(mIfaaPackName, mIfaaActName); 137 | if (!mContext.bindService(ifaaIntent, ifaaconn, 1)) { 138 | Slog.e(TAG, "cannot bind service org.ifaa.android.manager.IFAAService"); 139 | } 140 | } 141 | 142 | private boolean validateVal(String value) { 143 | return !"".equalsIgnoreCase(value) && value.contains(","); 144 | } 145 | 146 | public String getDeviceModel() { 147 | if (mDevModel == null) { 148 | mDevModel = Build.MANUFACTURER + "-" + Build.DEVICE; 149 | } 150 | 151 | Slog.i(TAG, "getDeviceModel deviceModel:" + mDevModel); 152 | return mDevModel; 153 | } 154 | 155 | public int getEnabled(int bioType) { 156 | return 1 == bioType ? 1000 : 1003; 157 | } 158 | 159 | public String getExtInfo(int authType, String keyExtInfo) { 160 | Slog.i(TAG, "getExtInfo:" + authType + CA_CERT_ALIAS_DELIMITER + keyExtInfo); 161 | return initExtString(); 162 | } 163 | 164 | public int[] getIDList(int bioType) { 165 | int[] idList = new int[]{0}; 166 | if (1 == bioType) { 167 | int retry_count = 10; 168 | while (true) { 169 | int retry_count2 = retry_count - 1; 170 | if (retry_count <= 0) { 171 | break; 172 | } 173 | if (mService == null || !mService.pingBinder()) { 174 | try { 175 | Thread.sleep(30); 176 | } catch (InterruptedException e) { 177 | Slog.e(TAG, "getIDList InterruptedException while waiting: " + e, e); 178 | } 179 | } else { 180 | Parcel data = Parcel.obtain(); 181 | Parcel reply = Parcel.obtain(); 182 | try { 183 | data.writeInterfaceToken(mIfaaInterfaceDesc); 184 | data.writeInt(bioType); 185 | mService.transact(CODE_GETIDLIST_CMD, data, reply, 0); 186 | reply.readException(); 187 | idList = reply.createIntArray(); 188 | } catch (RemoteException e) { 189 | Slog.e(TAG, "getIDList transact failed. ", e); 190 | } catch (Throwable th) { 191 | data.recycle(); 192 | reply.recycle(); 193 | } 194 | data.recycle(); 195 | reply.recycle(); 196 | } 197 | retry_count = retry_count2; 198 | } 199 | } 200 | return idList; 201 | } 202 | 203 | public int getSupportBIOTypes(Context context) { 204 | int ifaaProp; 205 | String fpVendor = ""; 206 | 207 | if (VERSION.SDK_INT >= 28) { 208 | ifaaProp = SystemProperties.getInt("persist.vendor.sys.pay.ifaa", 0); 209 | fpVendor = SystemProperties.get("persist.vendor.sys.fp.vendor", ""); 210 | } else { 211 | ifaaProp = SystemProperties.getInt("persist.sys.ifaa", 0); 212 | fpVendor = SystemProperties.get("persist.sys.fp.vendor", ""); 213 | } 214 | 215 | int res = "none".equalsIgnoreCase(fpVendor) ? 216 | ifaaProp & IFAA_TYPE_IRIS : ifaaProp & (IFAA_TYPE_FINGER | IFAA_TYPE_IRIS); 217 | 218 | if ((res & IFAA_TYPE_FINGER) == IFAA_TYPE_FINGER && sIsFod) { 219 | res |= IFAA_TYPE_SENSOR_FOD; 220 | } 221 | 222 | Slog.i(TAG, "getSupportBIOTypes:" + ifaaProp + ", " + sIsFod + ", " + fpVendor + 223 | ", res:" + res); 224 | return res; 225 | } 226 | 227 | public int getVersion() { 228 | Slog.i(TAG, "getVersion sdk:" + VERSION.SDK_INT + " ifaaVer:" + sIfaaVer); 229 | return sIfaaVer; 230 | } 231 | 232 | public byte[] processCmdV2(Context context, byte[] param) { 233 | Slog.i(TAG, "processCmdV2 sdk:" + VERSION.SDK_INT); 234 | 235 | if (VERSION.SDK_INT >= 28) { 236 | int retry_count = 10; 237 | 238 | while (true) { 239 | int retry_count2 = retry_count - 1; 240 | if (retry_count <= 0) { 241 | break; 242 | } 243 | if (mService == null || !mService.pingBinder()) { 244 | Slog.i(TAG, "processCmdV2 waiting ifaaService, remain: " + retry_count2 + 245 | " time(s)"); 246 | try { 247 | Thread.sleep(30); 248 | } catch (InterruptedException e) { 249 | Slog.e(TAG, "processCmdV2 InterruptedException while waiting: " + e, e); 250 | } 251 | } else { 252 | Parcel data = Parcel.obtain(); 253 | Parcel reply = Parcel.obtain(); 254 | try { 255 | data.writeInterfaceToken(mIfaaInterfaceDesc); 256 | data.writeByteArray(param); 257 | mService.transact(CODE_PROCESS_CMD, data, reply, 0); 258 | reply.readException(); 259 | return reply.createByteArray(); 260 | } catch (RemoteException e) { 261 | Slog.e(TAG, "processCmdV2 transact failed. ", e); 262 | retry_count = retry_count2; 263 | } finally { 264 | data.recycle(); 265 | reply.recycle(); 266 | } 267 | } 268 | retry_count = retry_count2; 269 | } 270 | 271 | Slog.e(TAG, "processCmdV2, return null"); 272 | return null; 273 | } 274 | 275 | HwParcel hidl_reply = new HwParcel(); 276 | try { 277 | IHwBinder hwService = HwBinder.getService(SERVICE_NAME, "default"); 278 | if (hwService != null) { 279 | HwParcel hidl_request = new HwParcel(); 280 | hidl_request.writeInterfaceToken(INTERFACE_DESCRIPTOR); 281 | ArrayList sbuf = new ArrayList(Arrays.asList(HwBlob.wrapArray(param))); 282 | hidl_request.writeInt8Vector(sbuf); 283 | hidl_request.writeInt32(sbuf.size()); 284 | hwService.transact(CODE_PROCESS_CMD, hidl_request, hidl_reply, 0); 285 | hidl_reply.verifySuccess(); 286 | hidl_request.releaseTemporaryStorage(); 287 | ArrayList val = hidl_reply.readInt8Vector(); 288 | byte[] array = new byte[val.size()]; 289 | for (int i = 0; i < val.size(); i++) { 290 | array[i] = ((Byte) val.get(i)).byteValue(); 291 | } 292 | hidl_reply.release(); 293 | return array; 294 | } 295 | } catch (RemoteException e) { 296 | Slog.e(TAG, "transact failed. ", e); 297 | } catch (Throwable th) { 298 | hidl_reply.release(); 299 | } 300 | 301 | hidl_reply.release(); 302 | Slog.e(TAG, "processCmdV2, return null"); 303 | return null; 304 | } 305 | 306 | public void setExtInfo(int authType, String keyExtInfo, String valExtInfo) { 307 | } 308 | 309 | public int startBIOManager(Context context, int authType) { 310 | int res = ACTIVITY_START_FAILED; 311 | 312 | if (authType == IFAA_TYPE_FINGER) { 313 | Intent intent = new Intent("android.settings.SECURITY_SETTINGS"); 314 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 315 | context.startActivity(intent); 316 | res = ACTIVITY_START_SUCCESS; 317 | } 318 | 319 | Slog.i(TAG, "startBIOManager authType:" + authType + " res:" + res); 320 | return res; 321 | } 322 | } 323 | --------------------------------------------------------------------------------