Browse Source

Refs #27 Make cancel discard all future call from application for some seconds

isundil 7 years ago
parent
commit
c6f2799986

+ 55 - 6
app/src/main/java/info/knacki/pass/services/AccessibilityService.java

@@ -1,11 +1,11 @@
 package info.knacki.pass.services;
 
+import android.content.Intent;
 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;
@@ -13,31 +13,62 @@ import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Toast;
 
 import java.io.File;
+import java.util.Date;
 import java.util.logging.Logger;
 
 import info.knacki.pass.R;
 
 public class AccessibilityService extends android.accessibilityservice.AccessibilityService {
+    private final long CANCEL_DELAY_SEC = 10;
+    private static AccessibilityService fInstance;
     private boolean fManagingEvent;
     private View fOpenWindow;
 
+    private class LastCancellation {
+        public long lastCancelledTime;
+        public String lastCancelledPackage;
+
+        private LastCancellation() {
+            Clear();
+        }
+
+        public void Cancel(AccessibilityNodeInfo source) {
+            fLastCancellation.lastCancelledPackage = source.getPackageName().toString();
+            fLastCancellation.lastCancelledTime = new Date().getTime() / 1000;
+        }
+
+        public boolean IsCancelling(AccessibilityNodeInfo source, boolean clearCancelling) {
+            boolean cancelling = source.getPackageName().toString().equals(lastCancelledPackage) && (new Date().getTime() / 1000) -lastCancelledTime <= CANCEL_DELAY_SEC;
+            if (cancelling && clearCancelling)
+                this.Clear();
+            return cancelling;
+        }
+
+        public void Clear() {
+            this.lastCancelledPackage = null;
+            this.lastCancelledTime = 0;
+        }
+    }
+    protected LastCancellation fLastCancellation = new LastCancellation();
+
     @Override
     protected void onServiceConnected() {
         super.onServiceConnected();
+        fInstance = this;
         fManagingEvent = false;
     }
 
     @Override
     public void onAccessibilityEvent(AccessibilityEvent event) {
         synchronized (AccessibilityService.class) {
-            if (fManagingEvent)
+            if (fManagingEvent || fLastCancellation.IsCancelling(event.getSource(), true))
                 return;
             if (event.isPassword())
                 fManagingEvent = DisplayPasswordList(event.getSource());
         }
     }
 
-    private boolean DisplayPasswordList(AccessibilityNodeInfo source) {
+    private boolean DisplayPasswordList(final AccessibilityNodeInfo source) {
         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                 WindowManager.LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.WRAP_CONTENT,
@@ -46,8 +77,8 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
                 PixelFormat.TRANSLUCENT);
         params.gravity = Gravity.START | Gravity.BOTTOM;
 
-        fOpenWindow = ((AccessibilityView) LayoutInflater.from(this).inflate(R.layout.activity_accessibility, null, false))
-                .init(this, new AccessibilityView.AccessibilityViewListener() {
+        fOpenWindow = new AccessibilityView(this)
+                .Init(this, new AccessibilityView.AccessibilityViewListener() {
                     @Override
                     public void OnPasswordClicked(File f) {
                         new Handler(getMainLooper()).post(() -> {
@@ -59,12 +90,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
                     @Override
                     public void cancel() {
                         new Handler(getMainLooper()).post(() -> {
+                            fLastCancellation.Cancel(source);
                             CloseOpenWindow();
                             fManagingEvent = false;
+                            SetFocus(source);
                         });
                     }
                 })
-                .AddCancelButton(this);
+                .AddCancelButton();
 
         try {
             WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
@@ -107,6 +140,12 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
         fManagingEvent = false;
     }
 
+    private void SetFocus(AccessibilityNodeInfo source) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            source.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+        }
+    }
+
     private void LegacySendPassword(String password) {
         // FIXME
     }
@@ -115,4 +154,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
     public void onInterrupt() {
         new Handler(getMainLooper()).post(this::CloseOpenWindow);
     }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        fInstance = null;
+        return super.onUnbind(intent);
+    }
+
+    public static boolean IsRunning() {
+        return fInstance != null;
+    }
 }