|
|
@@ -0,0 +1,116 @@
|
|
|
+package info.knacki.pass.services;
|
|
|
+
|
|
|
+import android.graphics.PixelFormat;
|
|
|
+import android.os.Build;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.os.Handler;
|
|
|
+import android.view.Gravity;
|
|
|
+import android.view.LayoutInflater;
|
|
|
+import android.view.View;
|
|
|
+import android.view.WindowManager;
|
|
|
+import android.view.accessibility.AccessibilityEvent;
|
|
|
+import android.view.accessibility.AccessibilityNodeInfo;
|
|
|
+import android.widget.Toast;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.util.logging.Logger;
|
|
|
+
|
|
|
+import info.knacki.pass.R;
|
|
|
+
|
|
|
+public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
|
|
|
+ private boolean fManagingEvent;
|
|
|
+ private View fOpenWindow;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onServiceConnected() {
|
|
|
+ super.onServiceConnected();
|
|
|
+ fManagingEvent = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onAccessibilityEvent(AccessibilityEvent event) {
|
|
|
+ synchronized (AccessibilityService.class) {
|
|
|
+ if (fManagingEvent)
|
|
|
+ return;
|
|
|
+ if (event.isPassword())
|
|
|
+ fManagingEvent = DisplayPasswordList(event.getSource());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean DisplayPasswordList(AccessibilityNodeInfo source) {
|
|
|
+ WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
|
|
+ WindowManager.LayoutParams.MATCH_PARENT,
|
|
|
+ WindowManager.LayoutParams.WRAP_CONTENT,
|
|
|
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE,
|
|
|
+ 0,
|
|
|
+ PixelFormat.TRANSLUCENT);
|
|
|
+ params.gravity = Gravity.START | Gravity.BOTTOM;
|
|
|
+ params.setTitle("Load Average");
|
|
|
+
|
|
|
+ try {
|
|
|
+ WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
|
|
|
+ fOpenWindow = LayoutInflater.from(this).inflate(R.layout.activity_accessibility, null, false);
|
|
|
+ wm.addView(fOpenWindow, params);
|
|
|
+ ((AccessibilityView) fOpenWindow).init(this, new AccessibilityView.AccessibilityViewListener() {
|
|
|
+ @Override
|
|
|
+ public void OnPasswordClicked(File f) {
|
|
|
+ new Handler(getMainLooper()).post(() -> {
|
|
|
+ CloseOpenWindow();
|
|
|
+ LoadFile(f, source);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void cancel() {
|
|
|
+ new Handler(getMainLooper()).post(() -> {
|
|
|
+ CloseOpenWindow();
|
|
|
+ fManagingEvent = false;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ catch (WindowManager.BadTokenException e) {
|
|
|
+ Toast.makeText(this, getResources().getString(R.string.app_name) +": " +getResources().getString(R.string.unauthorized_draw_over), Toast.LENGTH_LONG).show();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CloseOpenWindow() {
|
|
|
+ if (fOpenWindow != null) {
|
|
|
+ WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
|
|
|
+ wm.removeViewImmediate(fOpenWindow);
|
|
|
+ fOpenWindow = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void LoadFile(File f, AccessibilityNodeInfo source) {
|
|
|
+ fManagingEvent = false;
|
|
|
+ Logger.getAnonymousLogger().severe("Loading " +f.getName());
|
|
|
+ //SendPassword(source, ""))
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SendPassword(AccessibilityNodeInfo accessibilityNode, String password) {
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
|
+ Bundle passContent = new Bundle();
|
|
|
+ passContent.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, password);
|
|
|
+ try {
|
|
|
+ accessibilityNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, passContent);
|
|
|
+ } catch (Throwable e) {
|
|
|
+ LegacySendPassword(password);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ LegacySendPassword(password);
|
|
|
+ }
|
|
|
+ fManagingEvent = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void LegacySendPassword(String password) {
|
|
|
+ // FIXME
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onInterrupt() {
|
|
|
+ new Handler(getMainLooper()).post(this::CloseOpenWindow);
|
|
|
+ }
|
|
|
+}
|