diff --git a/patches_treble_td/platform_frameworks_base/0032-FOD-support-for-Asus-ZF8-and-Samsung-devices.patch b/patches_treble_td/platform_frameworks_base/0032-FOD-support-for-Asus-ZF8-and-Samsung-devices.patch deleted file mode 100644 index f3b86c2..0000000 --- a/patches_treble_td/platform_frameworks_base/0032-FOD-support-for-Asus-ZF8-and-Samsung-devices.patch +++ /dev/null @@ -1,566 +0,0 @@ -From 9608e159585b0fad82cede7fd9dca5e50a71672b Mon Sep 17 00:00:00 2001 -From: Pierre-Hugues Husson -Date: Sun, 18 Dec 2022 18:20:40 -0500 -Subject: [PATCH 32/40] FOD support for Asus ZF8 and Samsung devices - -Thanks Asus for providing a free device to make this support -And thanks @davigamer987 for donating enough to get a Samsung FOD device -to make this - -Change-Id: Ib328f39217c3f9b42e13e186496b3f6391643637 ---- - packages/SystemUI/Android.bp | 1 + - packages/SystemUI/res/values/config.xml | 2 +- - .../biometrics/UdfpsControllerOverlay.kt | 7 +- - .../android/systemui/biometrics/UdfpsView.kt | 138 ++++++++++ - services/core/Android.bp | 7 +- - .../server/biometrics/AuthService.java | 238 +++++++++++++++++- - 6 files changed, 388 insertions(+), 5 deletions(-) - -diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp -index b4027197344d..0637dd4b4471 100644 ---- a/packages/SystemUI/Android.bp -+++ b/packages/SystemUI/Android.bp -@@ -178,6 +178,7 @@ android_library { - "LowLightDreamLib", - "motion_tool_lib", - "vendor.lineage.powershare-V1.0-java", -+ "vendor.goodix.hardware.biometrics.fingerprint-V2.1-java", - ], - manifest: "AndroidManifest.xml", - additional_manifests: ["LineageManifest.xml"], -diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml -index 0743bcdde621..99f21ed21d15 100644 ---- a/packages/SystemUI/res/values/config.xml -+++ b/packages/SystemUI/res/values/config.xml -@@ -585,7 +585,7 @@ - - - -- 70 -+ 50 - - - -diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt -index b6b5d26b398c..88c2976d81ab 100644 ---- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt -+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt -@@ -120,7 +120,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor( - gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT - layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS - flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or -- WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) -+ WindowManager.LayoutParams.FLAG_SPLIT_TOUCH) or -+ WindowManager.LayoutParams.FLAG_DIM_BEHIND -+ dimAmount = 0.0f - privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY - // Avoid announcing window title. - accessibilityTitle = " " -@@ -189,6 +191,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor( - windowManager.addView(this, coreLayoutParams.updateDimensions(animation)) - sensorRect = sensorBounds - touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled -+ dimUpdate = { -+ windowManager.updateViewLayout(this, coreLayoutParams.updateDimensions(animation).apply { dimAmount = it }) -+ } - overlayTouchListener = TouchExplorationStateChangeListener { - if (accessibilityManager.isTouchExplorationEnabled) { - setOnHoverListener { v, event -> onTouch(v, event, true) } -diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt -index e61c614f0292..cdaad81b9222 100644 ---- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt -+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt -@@ -19,18 +19,27 @@ import android.content.Context - import android.graphics.Canvas - import android.graphics.Color - import android.graphics.Paint -+import android.graphics.PixelFormat - import android.graphics.PointF - import android.graphics.Rect - import android.graphics.RectF -+import android.os.FileObserver - import android.util.AttributeSet - import android.util.Log - import android.view.MotionEvent -+import android.view.SurfaceHolder -+import android.view.SurfaceView -+import android.view.ViewGroup - import android.widget.FrameLayout - import com.android.systemui.R - import com.android.systemui.doze.DozeReceiver -+import java.io.File -+ -+import vendor.goodix.hardware.biometrics.fingerprint.V2_1.IGoodixFingerprintDaemon - - private const val TAG = "UdfpsView" - -+ - /** - * The main view group containing all UDFPS animations. - */ -@@ -38,6 +47,54 @@ class UdfpsView( - context: Context, - attrs: AttributeSet? - ) : FrameLayout(context, attrs), DozeReceiver { -+ private var currentOnIlluminatedRunnable: Runnable? = null -+ private val mySurfaceView = SurfaceView(context) -+ init { -+ mySurfaceView.setVisibility(INVISIBLE) -+ mySurfaceView.setZOrderOnTop(true) -+ addView(mySurfaceView, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)) -+ mySurfaceView.holder.addCallback(object: SurfaceHolder.Callback{ -+ override fun surfaceCreated(p0: SurfaceHolder) { -+ Log.d("PHH", "Surface created!") -+ val paint = Paint(0 /* flags */); -+ paint.setAntiAlias(true); -+ paint.setStyle(Paint.Style.FILL); -+ val colorStr = android.os.SystemProperties.get("persist.sys.phh.fod_color", "00ff00"); -+ try { -+ val parsedColor = Color.parseColor("#" + colorStr); -+ val r = (parsedColor shr 16) and 0xff; -+ val g = (parsedColor shr 8) and 0xff; -+ val b = (parsedColor shr 0) and 0xff; -+ paint.setARGB(255, r, g, b); -+ } catch(t: Throwable) { -+ Log.d("PHH", "Failed parsing color #" + colorStr, t); -+ } -+ var canvas: Canvas? = null -+ try { -+ canvas = p0.lockCanvas(); -+Log.d("PHH", "Surface dimensions ${canvas.getWidth()*1.0f} ${canvas.getHeight()*1.0f}") -+ canvas.drawOval(RectF(0.0f, 0.0f, canvas.getWidth()*1.0f, canvas.getHeight()*1.0f), paint); -+ } finally { -+ // Make sure the surface is never left in a bad state. -+ if (canvas != null) { -+ p0.unlockCanvasAndPost(canvas); -+ } -+ } -+ -+ currentOnIlluminatedRunnable?.run() -+ } -+ -+ override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) { -+Log.d("PHH", "Got surface size $p1 $p2 $p3") -+ } -+ -+ override fun surfaceDestroyed(p0: SurfaceHolder) { -+Log.d("PHH", "Surface destroyed!") -+ } -+ }) -+ mySurfaceView.holder.setFormat(PixelFormat.RGBA_8888) -+ -+ } - - // Use expanded overlay when feature flag is true, set by UdfpsViewController - var useExpandedOverlay: Boolean = false -@@ -66,6 +123,8 @@ class UdfpsView( - /** Parameters that affect the position and size of the overlay. */ - var overlayParams = UdfpsOverlayParams() - -+ var dimUpdate: (Float) -> Unit = {} -+ - /** Debug message. */ - var debugMessage: String? = null - set(value) { -@@ -146,15 +205,94 @@ class UdfpsView( - !(animationViewController?.shouldPauseAuth() ?: false) - } - -+ fun goodixCmd(id: Int) { -+ val goodixSvc = IGoodixFingerprintDaemon.getService() -+ if(goodixSvc != null) { -+ goodixSvc.sendCommand(id, ArrayList(), { returnCode, resultData -> { -+ Log.e("PHH-Enroll", "Goodix send command returned code "+ returnCode); -+ }}); -+ } -+ } -+ -+ val asusGhbmOnAchieved = "/sys/class/drm/ghbm_on_achieved" -+ var hasAsusGhbm = File(asusGhbmOnAchieved).exists() -+ var samsungActualMaskBrightness = "/sys/class/lcd/panel/actual_mask_brightness" -+ val hasSamsungMask = File(samsungActualMaskBrightness).exists() -+ var fodFileObserver: FileObserver? = null -+ - fun configureDisplay(onDisplayConfigured: Runnable) { - isDisplayConfigured = true - animationViewController?.onDisplayConfiguring() - mUdfpsDisplayMode?.enable(onDisplayConfigured) -+ -+ mySurfaceView.setVisibility(VISIBLE) -+ Log.d("PHH", "setting surface visible!") -+ -+ val brightness = File("/sys/class/backlight/panel0-backlight/brightness").readText().toDouble() -+ val maxBrightness = File("/sys/class/backlight/panel0-backlight/max_brightness").readText().toDouble() -+ -+ // Assume HBM is max brightness -+ val dim = 1.0 - Math.pow( (brightness / maxBrightness), 1/2.3); -+ Log.d("PHH-Enroll", "Brightness is $brightness / $maxBrightness, setting dim to $dim") -+ if (hasAsusGhbm) { -+ dimUpdate(dim.toFloat()) -+ } -+ if (hasSamsungMask) { -+ dimUpdate(dim.toFloat()) -+ } -+ -+ if(android.os.SystemProperties.get("ro.vendor.build.fingerprint").contains("ASUS")) { -+ goodixCmd(200001) -+ } - } - - fun unconfigureDisplay() { - isDisplayConfigured = false - animationViewController?.onDisplayUnconfigured() - mUdfpsDisplayMode?.disable(null /* onDisabled */) -+ -+ if (hasAsusGhbm) { -+ fodFileObserver = object: FileObserver(asusGhbmOnAchieved, FileObserver.MODIFY) { -+ override fun onEvent(event: Int, path: String): Unit { -+ Log.d("PHH-Enroll", "Asus ghbm event") -+ try { -+ val spotOn = File(asusGhbmOnAchieved).readText().toInt() -+ if(spotOn == 0) { -+ dimUpdate(0.0f) -+ fodFileObserver?.stopWatching() -+ fodFileObserver = null -+ } -+ } catch(e: Exception) { -+ Log.d("PHH-Enroll", "Failed dimpdate off", e) -+ } -+ } -+ }; -+ fodFileObserver?.startWatching(); -+ } else if (hasSamsungMask) { -+ fodFileObserver = object: FileObserver(asusGhbmOnAchieved, FileObserver.MODIFY) { -+ override fun onEvent(event: Int, path: String): Unit { -+ Log.d("PHH-Enroll", "samsung mask brightness event") -+ try { -+ val spotOn = File(samsungActualMaskBrightness).readText().toInt() -+ if(spotOn == 0) { -+ dimUpdate(0.0f) -+ fodFileObserver?.stopWatching() -+ fodFileObserver = null -+ } -+ } catch(e: Exception) { -+ Log.d("PHH-Enroll", "Failed dimpdate off", e) -+ } -+ } -+ }; -+ fodFileObserver?.startWatching(); -+ } else { -+ dimUpdate(0.0f) -+ } -+ -+ mySurfaceView.setVisibility(INVISIBLE) -+ Log.d("PHH", "setting surface invisible!") -+ if(android.os.SystemProperties.get("ro.vendor.build.fingerprint").contains("ASUS")) { -+ goodixCmd(200003) -+ } - } - } -diff --git a/services/core/Android.bp b/services/core/Android.bp -index ebd4373e25c1..c4c8ee1f565a 100644 ---- a/services/core/Android.bp -+++ b/services/core/Android.bp -@@ -174,7 +174,12 @@ java_library_static { - "motorola.hardware.health-V1.0-java", - "overlayable_policy_aidl-java", - "com.android.sysprop.watchdog", -- "vendor.samsung.hardware.sysinput-V1.2-java", // HIDL -+ // HIDL -+ "vendor.samsung.hardware.sysinput-V1.2-java", -+ "vendor.goodix.hardware.biometrics.fingerprint-V2.1-java", -+ "vendor.samsung.hardware.biometrics.fingerprint-V3.0-java", -+ "vendor.oplus.hardware.biometrics.fingerprint-V2.1-java", -+ "vendor.oppo.hardware.biometrics.fingerprint-V2.1-java", - ], - javac_shard_size: 50, - } -diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java -index 7e6f35acc398..063e3599d6cd 100644 ---- a/services/core/java/com/android/server/biometrics/AuthService.java -+++ b/services/core/java/com/android/server/biometrics/AuthService.java -@@ -77,6 +77,22 @@ import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; - -+import android.hardware.display.DisplayManager; -+ -+import android.graphics.Point; -+import android.util.DisplayMetrics; -+import java.io.BufferedReader; -+import java.io.File; -+import java.io.FileReader; -+import java.io.PrintWriter; -+ -+import android.os.FileObserver; -+import android.os.Build; -+ -+import vendor.samsung.hardware.biometrics.fingerprint.V3_0.ISehBiometricsFingerprint; -+import vendor.goodix.hardware.biometrics.fingerprint.V2_1.IGoodixFingerprintDaemon; -+import vendor.samsung.hardware.sysinput.V1_0.ISehSysInputDev; -+ - /** - * System service that provides an interface for authenticating with biometrics and - * PIN/pattern/password to BiometricPrompt and lock screen. -@@ -95,6 +111,9 @@ public class AuthService extends SystemService { - @VisibleForTesting - final IAuthService.Stub mImpl; - -+ private FileObserver fodFileObserver = null; -+ private ISehBiometricsFingerprint mSamsungFingerprint = null; -+ - /** - * Class for injecting dependencies into AuthService. - * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger). -@@ -652,6 +671,72 @@ public class AuthService extends SystemService { - registerAuthenticators(hidlConfigs); - - mInjector.publishBinderService(this, mImpl); -+ try { -+ mSamsungFingerprint = ISehBiometricsFingerprint.getService(); -+ android.util.Log.e("PHH", "Got samsung fingerprint HAL"); -+ } catch(Exception e) { -+ android.util.Log.e("PHH", "Failed getting Samsung fingerprint HAL", e); -+ } -+ if(samsungHasCmd("fod_enable") && mSamsungFingerprint != null) { -+ samsungCmd("fod_enable,1,1,0"); -+ String actualMaskBrightnessPath = "/sys/class/lcd/panel/actual_mask_brightness"; -+ android.util.Log.e("PHH-Enroll", "Reading actual brightness file gives " + readFile(actualMaskBrightnessPath)); -+ fodFileObserver = new FileObserver(actualMaskBrightnessPath, FileObserver.MODIFY) { -+ @Override -+ public void onEvent(int event, String path) { -+ String actualMask = readFile(actualMaskBrightnessPath); -+ try { -+ mSamsungFingerprint = ISehBiometricsFingerprint.getService(); -+ } catch(Exception e) {} -+ Slog.d("PHH-Enroll", "New actual mask brightness is " + actualMask); -+ try { -+ int eventReq = 0; -+ if("0".equals(actualMask)) { -+ eventReq = 1; //released -+ } else { -+ eventReq = 2; //pressed -+ } -+ if(mSamsungFingerprint != null) { -+ mSamsungFingerprint.sehRequest(22 /* SEM_FINGER_STATE */, eventReq, new java.util.ArrayList(), -+ (int retval, java.util.ArrayList out) -> {} ); -+ } -+ } catch(Exception e) { -+ Slog.d("PHH-Enroll", "Failed setting samsung event for mask observer", e); -+ } -+ } -+ }; -+ fodFileObserver.startWatching(); -+ } -+ -+ String asusGhbmOnAchieved = "/sys/class/drm/ghbm_on_achieved"; -+ if( (new File(asusGhbmOnAchieved)).exists()) { -+ fodFileObserver = new FileObserver(asusGhbmOnAchieved, FileObserver.MODIFY) { -+ boolean wasOn = false; -+ @Override -+ public void onEvent(int event, String path) { -+ String spotOn = readFile(asusGhbmOnAchieved); -+ if("1".equals(spotOn)) { -+ if(!wasOn) { -+ try { -+ IGoodixFingerprintDaemon goodixDaemon = IGoodixFingerprintDaemon.getService(); -+ -+ //Send UI ready -+ goodixDaemon.sendCommand(200002, new java.util.ArrayList(), (returnCode, resultData) -> { -+ Slog.e(TAG, "Goodix send command touch pressed returned code "+ returnCode); -+ }); -+ } catch(Throwable t) { -+ Slog.d("PHH-Enroll", "Failed sending goodix command", t); -+ } -+ } -+ wasOn = true; -+ } else { -+ wasOn = false; -+ } -+ } -+ }; -+ fodFileObserver.startWatching(); -+ } -+ - } - - /** -@@ -775,18 +860,104 @@ public class AuthService extends SystemService { - ? modality : (modality & ~BiometricAuthenticator.TYPE_CREDENTIAL); - } - -+ private int[] dynamicUdfpsProps() { -+ DisplayManager mDM = (DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE); -+ Point displayRealSize = new Point(); -+ DisplayMetrics displayMetrics = new DisplayMetrics(); -+ mDM.getDisplay(0).getRealSize(displayRealSize); -+ mDM.getDisplay(0).getMetrics(displayMetrics); -+ -+ if(readFile("/sys/class/fingerprint/fingerprint/position") != null) { -+ try { -+ ISehSysInputDev s = ISehSysInputDev.getService(); -+ s.getTspFodInformation(0, (a, b) -> { -+ Slog.d("PHH-Enroll", "TspFod info " + a + ", " + b); -+ }); -+ s.getTspFodPosition(0, (a, b) -> { -+ Slog.d("PHH-Enroll", "TspFod info " + a + ", " + b); -+ }); -+ }catch(Throwable t) { -+ Slog.d("PHH-Enroll", "heya ", t); -+ } -+ -+ -+ android.util.Log.d("PHH", "Samsung fingerprint"); -+ String[] fodPositionArray = readFile("/sys/class/fingerprint/fingerprint/position").split(","); -+ float bottomMM = Float.parseFloat(fodPositionArray[0]); -+ float areaSizeMM = Float.parseFloat(fodPositionArray[5]); -+ float heightMM = Float.parseFloat(fodPositionArray[2]); -+ float bottomInch = bottomMM * 0.0393700787f; -+ float areaSizeInch = areaSizeMM * 0.0393700787f; -+ float heightInch = heightMM * 0.0393700787f; -+ int bottomPx = (int)(bottomInch * displayMetrics.ydpi); -+ int areaSizePx = (int)(areaSizeInch * displayMetrics.ydpi); -+ int midDistPx = (int)(areaSizeInch * displayMetrics.ydpi / 2.0f); -+ -+ float mW = areaSizePx/2; -+ float mH = areaSizePx/2; -+ float mX = displayRealSize.x/2; -+ //float mY = displayRealSize.y - bottomPx - midDistPx; -+ float mY = displayRealSize.y - (bottomInch * displayMetrics.ydpi) - (areaSizeInch * displayMetrics.ydpi / 2.0f); -+ -+ samsungCmd(String.format("fod_rect,%d,%d,%d,%d", (int)(mX - mW/2), (int)(mY - mW/2), (int)(mX + mW/2), (int)(mY + mW/2))); -+ Slog.d("PHH-Enroll", "Display real size is " + displayRealSize.y + ", dpy " + displayMetrics.ydpi); -+ -+ int udfpsProps[] = new int[3]; -+ udfpsProps[0] = (int)mX; -+ udfpsProps[1] = (int)mY; -+ udfpsProps[2] = (int)mW; -+ -+ try { -+ mSamsungFingerprint = ISehBiometricsFingerprint.getService(); -+ Slog.d("PHH-Enroll", "Samsung ask for sensor status"); -+ mSamsungFingerprint.sehRequest(6, 0, new java.util.ArrayList(), (int retval, java.util.ArrayList out) -> { -+ Slog.d("PHH-Enroll", "Result is " + retval); -+ for(int i=0; i out) -> { -+ Slog.d("PHH-Enroll", "Result is " + retval); -+ for(int i=0; i workaroundLocations = - getWorkaroundSensorProps(getContext()); - -- final boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps); -+ boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps); -+ if(!isUdfps) udfpsProps = dynamicUdfpsProps(); -+ isUdfps = !ArrayUtils.isEmpty(udfpsProps); -+ -+ if(udfpsProps.length > 0) { -+ Slog.d("PHH-Enroll", "Got udfps infos " + udfpsProps[0] + ", " + udfpsProps[1] + ", " + udfpsProps[2]); -+ } - - // config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor. - final boolean isPowerbuttonFps = getContext().getResources().getBoolean( -@@ -854,4 +1025,67 @@ public class AuthService extends SystemService { - componentInfo, resetLockoutRequiresHardwareAuthToken, - resetLockoutRequiresChallenge); - } -+ -+ private static boolean samsungHasCmd(String cmd) { -+ try { -+ File f = new File("/sys/devices/virtual/sec/tsp/cmd_list"); -+ if(!f.exists()) return false; -+ -+ android.util.Log.d("PHH", "Managed to grab cmd list, checking..."); -+ BufferedReader b = new BufferedReader(new FileReader(f)); -+ String line = null; -+ while( (line = b.readLine()) != null) { -+ if(line.equals(cmd)) return true; -+ } -+ android.util.Log.d("PHH", "... nope"); -+ return false; -+ } catch(Exception e) { -+ android.util.Log.d("PHH", "Failed reading cmd_list", e); -+ return false; -+ } -+ } -+ -+ public static void samsungCmd(String cmd) { -+ try { -+ writeFile("/sys/devices/virtual/sec/tsp/cmd", cmd); -+ -+ String status = readFile("/sys/devices/virtual/sec/tsp/cmd_status"); -+ String ret = readFile("/sys/devices/virtual/sec/tsp/cmd_result"); -+ -+ android.util.Log.d("PHH", "Sending command " + cmd + " returned " + ret + ":" + status); -+ } catch(Exception e) { -+ android.util.Log.d("PHH", "Failed sending command " + cmd, e); -+ } -+ } -+ -+ private static void writeFile(String path, String value) { -+ try { -+ PrintWriter writer = new PrintWriter(path, "UTF-8"); -+ writer.println(value); -+ writer.close(); -+ } catch(Exception e) { -+ android.util.Log.d("PHH", "Failed writing to " + path + ": " + value); -+ } -+ } -+ -+ private static void writeFile(File file, String value) { -+ try { -+ PrintWriter writer = new PrintWriter(file, "UTF-8"); -+ writer.println(value); -+ writer.close(); -+ } catch(Exception e) { -+ android.util.Log.d("PHH", "Failed writing to " + file + ": " + value); -+ } -+ } -+ -+ private static String readFile(String path) { -+ try { -+ File f = new File(path); -+ -+ BufferedReader b = new BufferedReader(new FileReader(f)); -+ return b.readLine(); -+ } catch(Exception e) { -+ return null; -+ } -+ } - } --- -2.34.1 -