title: AccessibilityService: Is possible draw password on remote smartphone screen with mouse?
body: <p>I'm working in a project similar to <a href="https://play.google.com/store/apps/details?id=com.teamviewer.quicksupport.market&amp;hl=pt_BR" rel="nofollow noreferrer">Team View QuickSupport</a> and i want know if <a href="https://developer.android.com/reference/android/accessibilityservice/AccessibilityService" rel="nofollow noreferrer"><code>AccessibilityService</code></a> allow perform a swipe on a remote screen that can be able to draw the password that protect device?</p>
  
  <p><a href="https://i.stack.imgur.com/subeh.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/subeh.png" alt="enter image description here"></a></p>
  
  <p>I comes trying the following code, but without success. Until now all that happens is a exception on android code that says:</p>
  
  <blockquote>
    <p>java.lang.IllegalStateException: <strong>Attempting to add too many strokes to a gesture</strong></p>
  </blockquote>
  
  <p>here:</p>
  
  <pre><code>gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 0, time));
  </code></pre>
  
  <p>The current Java code is this:</p>
  
  <pre><code>    if (xline.contains("mouseswipescreen")) {
  
       String coords = xline.replace("mouseswipescreen", "");
  
       String[] tokens = coords.split(Pattern.quote("&lt;|&gt;"));
  
                 float x = parseFloat(tokens[0]);
                 float y = parseFloat(tokens[1]);
                 String cmd = tokens[2];
  
       MyAccessibility.instance.Swipte((int) x, (int) y, 50, cmd);
   }
  </code></pre>
  
  <hr>
  
  <pre><code>GestureDescription.Builder gestureBuilder;
  Path path;
  
  public void Swipte(int x, int y, int time, String command) {
  
      if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.N) {
          System.out.println(" ======= Swipte =======");
  
          if (command.equalsIgnoreCase("start")) {
  
              gestureBuilder = new GestureDescription.Builder();
              path = new Path();
  
              path.moveTo(x, y);
  
          } else if (command.equalsIgnoreCase("move")) {
  
              path.lineTo(x, y);
              gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 0, time));
  
          } else if (command.equalsIgnoreCase("dispatch")) {
  
              dispatchGesture(gestureBuilder.build(), new GestureResultCallback() {
                  @Override
                  public void onCompleted(GestureDescription gestureDescription) {
                      System.out.println("SWIPTE Gesture Completed :D");
                      super.onCompleted(gestureDescription);
                  }
              }, null);
          }
      }
  
  }
  </code></pre>
  
  <p>Now changing this code to perform a swipe screen that stays this way:</p>
  
  <pre><code>public void Swipte(int x1, int y1, int x2, int y2, int time){
  
          if (android.os.Build.VERSION.SDK_INT &gt;= android.os.Build.VERSION_CODES.N) {
  
              System.out.println(" ======= Swipte =======");
  
              GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
              Path path = new Path();
              path.moveTo(x1,y1); // "mousedown"
              path.lineTo(x2,y2); // until last position found in "mousemove"
  
              gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 0, time));
              dispatchGesture(gestureBuilder.build(), new GestureResultCallback() {
                  @Override
                  public void onCompleted(GestureDescription gestureDescription) {
                      System.out.println("SWIPTE Gesture Completed :D");
                      super.onCompleted(gestureDescription);
                  }
              }, null);
          }
  
      }
  </code></pre>
  
  <p>The result is this:</p>
  
  <p><a href="https://i.stack.imgur.com/FIBHT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FIBHT.png" alt="enter image description here"></a></p>
  
  <p>See that is drawn a wrong password.</p>
  
  <p>Lastly follows the code (Delphi) that send the coordenates (<a href="https://stackoverflow.com/a/17976508/9672569"><em>reference</em></a>) based in first Java code above:</p>
  
  <pre><code> private
      { Private declarations }
      fDown: Boolean;
      fPO: TPoint;
    public
      { Public declarations }
    end;
  
    ...
  
  procedure TForm2.Image1MouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  var
    Index, XTouch, YTouch, RXCoord, RYCoord: Integer;
    List: TStrings;
    RScreen, Start: String;
  begin
    Index := Form1.ListView1.ItemIndex;
    if Index = -1 then
      Exit;
  
      List := TStringList.Create;
      RScreen := Form1.ListView1.Selected.SubItems[6]; // Remote screen resolution
  
      try
        ExtractStrings(['x'], [], PChar(RScreen), List); // Ex: my smartphone is 1920x1080
        RYCoord := StrToInt(List[0]);                    // 1920 (height)
        RXCoord := StrToInt(List[1]);                    // 1080 (width)
      finally
        List.Free;
      end;
  
      XTouch := Round((X / Image1.Width) * RXCoord);
      YTouch := Round((Y / Image1.Height) * RYCoord);
  
      fPO := Point(XTouch, YTouch);
      Start := 'start';
      fDown := true;
  
      Form1.ServerSocket1.Socket.Connections[Index].SendText(format('mouseswipescreen%d&lt;|&gt;%d&lt;|&gt;%s'#13#10, [fPO.X, fPO.Y, Start]));
  
    end;
  end;
  
  procedure TForm2.Image1MouseMove(Sender: TObject; Shift: TShiftState;
    X, Y: Integer);
  var
    Index, XTouch, YTouch, RXCoord, RYCoord: Integer;
    List: TStrings;
    RScreen, Move: String;
  begin
  
    Index := Form1.ListView1.ItemIndex;
    if Index = -1 then
      Exit;
  
    List := TStringList.Create;
    RScreen := Form1.ListView1.Selected.SubItems[6]; // Remote screen resolution
  
    try
      ExtractStrings(['x'], [], PChar(RScreen), List); // Ex: my smartphone is 1920x1080
      RYCoord := StrToInt(List[0]);                    // 1920 (height)
      RXCoord := StrToInt(List[1]);                    // 1080 (width)
    finally
      List.Free;
    end;
  
    XTouch := Round((X / Image1.Width) * RXCoord);
    YTouch := Round((Y / Image1.Height) * RYCoord);
  
    if fDown then
    begin
  
      Move := 'move';
  
      Form1.ServerSocket1.Socket.Connections[Index].SendText(format('mouseswipescreen%d&lt;|&gt;%d&lt;|&gt;%s'#13#10, [fPO.X, fPO.Y, Move]));
  
      fPO := Point(XTouch, YTouch);
  
    end;
  
  end;
  
  procedure TForm2.Image1MouseUp(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
  begin
    if fDown then
      fDown := false;
  end;
  </code></pre>