wayne-common: Access mlipay hal via a binder service

* Untrusted apps are no longer allowed to directly access hwbinder on
   Pie, implement a system service as a middleware between mlipay hal
   and untrusted apps.
 * Xiaomi uses similar solution for MIUI on Pie.

Change-Id: Ie52376b1f7bcd84d219fe73bceb4bdd6cc2b9980
This commit is contained in:
dianlujitao 2019-02-18 20:55:11 +08:00 committed by Max Weffers
parent 63ec762eee
commit 8ff49b15bd
No known key found for this signature in database
GPG key ID: 795F73D22FB93FAE
13 changed files with 303 additions and 158 deletions

View file

@ -19,10 +19,24 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
$(call all-Iaidl-files-under, lib) \
$(call all-java-files-under, lib)
LOCAL_MODULE := org.ifaa.android.manager
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
include $(BUILD_JAVA_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := org.ifaa.android.manager
LOCAL_MODULE_TAGS := optional
LOCAL_PACKAGE_NAME := IFAAService
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2019 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.ifaa.android.manager"
android:versionCode="1"
android:versionName="1"
android:sharedUserId="android.uid.system">
<uses-sdk
android:minSdkVersion="28"
android:targetSdkVersion="28" />
<application
android:label="IFAAService">
<service android:name=".IFAAService"
android:exported="true" />
</application>
</manifest>

View file

@ -4,6 +4,6 @@ import android.content.Context;
public class IFAAManagerFactory {
public static IFAAManager getIFAAManager(Context context, int authType) {
return IFAAManagerImpl.getInstance();
return IFAAManagerImpl.getInstance(context);
}
}

View file

@ -0,0 +1,180 @@
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.IBinder;
import android.os.IBinder.DeathRecipient;
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 IFAAManagerV3 {
private static final boolean DEBUG = false;
private static final int IFAA_TYPE_FINGER = 1;
private static final int IFAA_TYPE_IRIS = (1 << 1);
private static final int IFAA_TYPE_SENSOR_FOD = (1 << 4);
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 TAG = "IfaaManagerImpl";
private static ServiceConnection ifaaconn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IIFAAService.Stub.asInterface(service);
try {
mService.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "linkToDeath fail.", e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (mContext != null) {
if (DEBUG) Slog.i(TAG, "re-bind the service.");
initService();
}
}
};
private static Context mContext = null;
private static DeathRecipient mDeathRecipient = new DeathRecipient() {
@Override
public void binderDied() {
if (mService != null) {
if (DEBUG) Slog.d(TAG, "binderDied, unlink the service.");
mService.asBinder().unlinkToDeath(mDeathRecipient, 0);
}
}
};
private static final String mIfaaActName = "org.ifaa.android.manager.IFAAService";
private static final String mIfaaPackName = "org.ifaa.android.manager";
private static IIFAAService mService = null;
private static final String seperate = ",";
private String mDevModel = null;
public static IFAAManagerV3 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 str = "";
JSONObject location = new JSONObject();
JSONObject fullView = new JSONObject();
String xy = SystemProperties.get("persist.sys.fp.fod.location.X_Y", "");
String wh = SystemProperties.get("persist.sys.fp.fod.size.width_height", "");
try {
if (validateVal(xy) && validateVal(wh)) {
String[] splitXy = xy.split(seperate);
String[] splitWh = wh.split(seperate);
fullView.put("startX", Integer.parseInt(splitXy[0]));
fullView.put("startY", Integer.parseInt(splitXy[1]));
fullView.put("width", Integer.parseInt(splitWh[0]));
fullView.put("height", Integer.parseInt(splitWh[1]));
fullView.put("navConflict", true);
location.put("type", 0);
location.put("fullView", fullView);
str = location.toString();
} else {
if (DEBUG) Slog.e(TAG, "initExtString invalidate, xy:" + xy + " wh:" + wh);
}
} catch (Exception e) {
if (DEBUG) Slog.e(TAG, "Exception , xy:" + xy + " wh:" + wh, e);
}
return str;
}
private static void initService() {
Intent intent = new Intent();
intent.setClassName(mIfaaPackName, mIfaaActName);
if (!mContext.bindService(intent, ifaaconn, Context.BIND_AUTO_CREATE)) {
if (DEBUG) Slog.e(TAG, "cannot bind service org.ifaa.android.manager.IFAAService");
}
}
private boolean validateVal(String str) {
return !"".equalsIgnoreCase(str) && str.contains(",");
}
public String getDeviceModel() {
if (mDevModel == null) {
mDevModel ="xiaomi" + "-" + "wayne";
}
if (DEBUG) Slog.i(TAG, "getDeviceModel devcieModel:" + mDevModel);
return mDevModel;
}
public String getExtInfo(int authType, String keyExtInfo) {
return initExtString();
}
public int getSupportBIOTypes(Context context) {
int ifaaType = SystemProperties.getInt("persist.sys.ifaa", 0);
String fpVendor = SystemProperties.get("persist.sys.fp.vendor", "");
int supportBIOTypes = "none".equalsIgnoreCase(fpVendor) ? ifaaType & IFAA_TYPE_IRIS :
ifaaType & (IFAA_TYPE_FINGER | IFAA_TYPE_IRIS);
if ((supportBIOTypes & IFAA_TYPE_FINGER) == IFAA_TYPE_FINGER && sIsFod) {
supportBIOTypes |= IFAA_TYPE_SENSOR_FOD;
}
if (DEBUG) Slog.i(TAG, "getSupportBIOTypes:" + ifaaType + " " + sIsFod + " " + fpVendor +
" res:" + supportBIOTypes);
return supportBIOTypes;
}
public int getVersion() {
if (DEBUG) Slog.i(TAG, "getVersion sdk:" + VERSION.SDK_INT + " ifaaVer:" + sIfaaVer);
return sIfaaVer;
}
public byte[] processCmdV2(Context context, byte[] data) {
if (DEBUG) Slog.i(TAG, "processCmdV2 sdk:" + VERSION.SDK_INT);
try {
return mService.processCmd_v2(data);
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "processCmdV2 transact failed. " + e);
}
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;
}
if (DEBUG) Slog.i(TAG, "startBIOManager authType:" + authType + " res:" + res);
return res;
}
}

View file

@ -0,0 +1,5 @@
package org.ifaa.android.manager;
interface IIFAAService {
byte[] processCmd_v2(in byte[] param);
}

View file

@ -1,155 +0,0 @@
package org.ifaa.android.manager;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiEnterpriseConfig;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.HwBinder;
import android.os.HwBlob;
import android.os.HwParcel;
import android.os.IHwBinder;
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 IFAAManagerV3 {
private static final String TAG = "IfaaManagerImpl";
private static volatile IFAAManagerImpl INSTANCE = null;
private static final int IFAA_TYPE_FINGER = 0x01;
private static final int IFAA_TYPE_IRIS = 0x02;
private static final int IFAA_TYPE_SENSOR_FOD = 0x10;
private static final int ACTIVITY_START_SUCCESS = 0;
private static final int ACTIVITY_START_FAILED = -1;
private static final int CODE_PROCESS_CMD = 1;
private static final String INTERFACE_DESCRIPTOR = "vendor.xiaomi.hardware.mlipay@1.0::IMlipayService";
private static final String SERVICE_NAME = "vendor.xiaomi.hardware.mlipay@1.0::IMlipayService";
private static final String seperate = ",";
private String mDevModel = null;
private IHwBinder mService;
public static IFAAManagerV3 getInstance() {
if (INSTANCE == null) {
synchronized (IFAAManagerImpl.class) {
if (INSTANCE == null) {
INSTANCE = new IFAAManagerImpl();
}
}
}
return INSTANCE;
}
private String initExtString() {
String str = "";
JSONObject location = new JSONObject();
JSONObject fullView = new JSONObject();
String str2 = SystemProperties.get("persist.sys.fp.fod.location.X_Y", "");
String str3 = SystemProperties.get("persist.sys.fp.fod.size.width_height", "");
try {
if (validateVal(str2) && validateVal(str3)) {
String[] split = str2.split(seperate);
String[] split2 = str3.split(seperate);
fullView.put("startX", Integer.parseInt(split[0]));
fullView.put("startY", Integer.parseInt(split[1]));
fullView.put("width", Integer.parseInt(split2[0]));
fullView.put("height", Integer.parseInt(split2[1]));
fullView.put("navConflict", true);
location.put("type", 0);
location.put("fullView", fullView);
return location.toString();
}
Slog.e(TAG, "initExtString invalidate, xy:" + str2 + " wh:" + str3);
return str;
} catch (Exception e) {
Slog.e(TAG, "Exception , xy:" + str2 + " wh:" + str3, e);
return str;
}
}
private boolean validateVal(String str) {
return !"".equalsIgnoreCase(str) && str.contains(",");
}
public String getDeviceModel() {
mDevModel = "xiaomi" + "-" + "wayne";
Slog.i(TAG, "getDeviceModel deviceModel:" + mDevModel);
return mDevModel;
}
public String getExtInfo(int authType, String keyExtInfo) {
Slog.i(TAG, "getExtInfo:" + authType + WifiEnterpriseConfig.CA_CERT_ALIAS_DELIMITER + keyExtInfo);
return initExtString();
}
public int getSupportBIOTypes(Context context) {
int ifaaType = SystemProperties.getInt("persist.sys.ifaa", 0);
String fpVendor = SystemProperties.get("persist.sys.fp.vendor", "");
int supportBIOTypes = "none".equalsIgnoreCase(fpVendor) ? ifaaType & IFAA_TYPE_IRIS :
ifaaType & (IFAA_TYPE_FINGER | IFAA_TYPE_IRIS);
if ((supportBIOTypes & IFAA_TYPE_FINGER) == IFAA_TYPE_FINGER && sIsFod) {
supportBIOTypes |= IFAA_TYPE_SENSOR_FOD;
}
return supportBIOTypes;
}
public int getVersion() {
Slog.i(TAG, "getVersion sdk:" + VERSION.SDK_INT + " ifaaVer:" + sIfaaVer);
return sIfaaVer;
}
public byte[] processCmdV2(Context context, byte[] data) {
Slog.i(TAG, "processCmdV2 sdk:" + VERSION.SDK_INT);
HwParcel hwParcel = new HwParcel();
try {
if (mService == null) {
mService = HwBinder.getService(SERVICE_NAME, "default");
}
if (mService != null) {
HwParcel hwParcel2 = new HwParcel();
hwParcel2.writeInterfaceToken(INTERFACE_DESCRIPTOR);
ArrayList arrayList = new ArrayList(Arrays.asList(HwBlob.wrapArray(data)));
hwParcel2.writeInt8Vector(arrayList);
hwParcel2.writeInt32(arrayList.size());
mService.transact(CODE_PROCESS_CMD, hwParcel2, hwParcel, 0);
hwParcel.verifySuccess();
hwParcel2.releaseTemporaryStorage();
ArrayList readInt8Vector = hwParcel.readInt8Vector();
int size = readInt8Vector.size();
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
result[i] = ((Byte) readInt8Vector.get(i)).byteValue();
}
return result;
}
} catch (RemoteException e) {
Slog.e(TAG, "transact failed. " + e);
} finally {
hwParcel.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;
}
}

View file

@ -0,0 +1,67 @@
package org.ifaa.android.manager;
import android.app.Service;
import android.content.Intent;
import android.os.HwBinder;
import android.os.HwBlob;
import android.os.HwParcel;
import android.os.IBinder;
import android.os.IHwBinder;
import android.os.RemoteException;
import android.util.Slog;
import java.util.ArrayList;
import java.util.Arrays;
public class IFAAService extends Service {
private static final boolean DEBUG = false;
private static final String TAG = "IFAAService";
private final IBinder mIFAABinder = new IIFAAService.Stub() {
private static final String INTERFACE_DESCRIPTOR =
"vendor.xiaomi.hardware.mlipay@1.0::IMlipayService";
private static final String SERVICE_NAME =
"vendor.xiaomi.hardware.mlipay@1.0::IMlipayService";
private static final int CODE_PROCESS_CMD = 1;
private IHwBinder mService;
@Override
public byte[] processCmd_v2(byte[] param) {
HwParcel reply = new HwParcel();
try {
if (mService == null) {
mService = HwBinder.getService(SERVICE_NAME, "default");
}
if (mService != null) {
HwParcel data = new HwParcel();
data.writeInterfaceToken(INTERFACE_DESCRIPTOR);
ArrayList arrayList = new ArrayList(Arrays.asList(HwBlob.wrapArray(param)));
data.writeInt8Vector(arrayList);
data.writeInt32(arrayList.size());
mService.transact(CODE_PROCESS_CMD, data, reply, 0);
reply.verifySuccess();
data.releaseTemporaryStorage();
ArrayList readInt8Vector = reply.readInt8Vector();
int size = readInt8Vector.size();
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
result[i] = ((Byte) readInt8Vector.get(i)).byteValue();
}
return result;
}
} catch (RemoteException e) {
if (DEBUG) Slog.e(TAG, "transact failed. " + e);
} finally {
reply.release();
}
if (DEBUG) Slog.e(TAG, "processCmdV2, return null");
return null;
}
};
@Override
public IBinder onBind(Intent intent) {
return mIFAABinder;
}
}

View file

@ -1,2 +1,2 @@
type goodixhw_service, hwservice_manager_type;
type hal_mlipay_hwservice, hwservice_manager_type, untrusted_app_visible_hwservice;
type hal_mlipay_hwservice, hwservice_manager_type;

1
sepolicy/system_app.te Normal file
View file

@ -0,0 +1 @@
hal_client_domain(system_app, hal_mlipay)

View file

@ -139,6 +139,7 @@ PRODUCT_PACKAGES += \
android.hardware.biometrics.fingerprint@2.1-service.xiaomi_wayne
PRODUCT_PACKAGES += \
IFAAService \
org.ifaa.android.manager
PRODUCT_BOOT_JARS += \