OSDN Git Service

Add Shell commands to list and reset auto-fill sessions.
authorFelipe Leme <felipeal@google.com>
Thu, 9 Feb 2017 17:40:15 +0000 (09:40 -0800)
committerFelipe Leme <felipeal@google.com>
Fri, 10 Feb 2017 21:06:05 +0000 (13:06 -0800)
These commands are useful during development and CTS tests (for
example, the test can assert there is no dangling session after it's
finished).

BUG: 33802548

Test: manual verification
Change-Id: I61f96e30d07642fa2165df9b982c6bf32a4e8716

services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java

index 631fb53..c16a51c 100644 (file)
@@ -34,6 +34,7 @@ import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -54,12 +55,14 @@ import android.view.autofill.AutoFillValue;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.SomeArgs;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -77,6 +80,10 @@ public final class AutoFillManagerService extends SystemService {
     private static final int MSG_UPDATE_SESSION = 2;
     private static final int MSG_FINISH_SESSION = 3;
     private static final int MSG_REQUEST_SAVE_FOR_USER = 4;
+    private static final int MSG_LIST_SESSIONS = 5;
+    private static final int MSG_RESET = 6;
+
+    static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
 
     private final Context mContext;
     private final AutoFillUI mUi;
@@ -111,6 +118,12 @@ public final class AutoFillManagerService extends SystemService {
                 final int flags = args.argi6;
                 handleUpdateSession(userId, activityToken, autoFillId, bounds, value, flags);
                 return;
+            } case MSG_LIST_SESSIONS: {
+                handleListForUser(msg.arg1, (IResultReceiver) msg.obj);
+                return;
+            } case MSG_RESET: {
+                handleReset();
+                return;
             } default: {
                 Slog.w(TAG, "Invalid message: " + msg);
             }
@@ -203,12 +216,29 @@ public final class AutoFillManagerService extends SystemService {
         return service;
     }
 
+    // Called by Shell command.
     void requestSaveForUser(int userId) {
+        Slog.i(TAG, "requestSaveForUser(): " + userId);
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
         mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageI(
                 MSG_REQUEST_SAVE_FOR_USER, userId));
     }
 
+    // Called by Shell command.
+    void listSessions(int userId, IResultReceiver receiver) {
+        Slog.i(TAG, "listSessions() for userId " + userId);
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+        mHandlerCaller.sendMessage(
+                mHandlerCaller.obtainMessageIO(MSG_LIST_SESSIONS, userId, receiver));
+    }
+
+    // Called by Shell command.
+    void reset() {
+        Slog.i(TAG, "reset()");
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+        mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_RESET));
+    }
+
     /**
      * Removes a cached service for a given user.
      */
@@ -279,6 +309,39 @@ public final class AutoFillManagerService extends SystemService {
         }
     }
 
+    private void handleListForUser(int userId, IResultReceiver receiver) {
+        final Bundle resultData = new Bundle();
+        final ArrayList<String> sessions = new ArrayList<>();
+
+        synchronized (mLock) {
+            if (userId != UserHandle.USER_ALL) {
+                mServicesCache.get(userId).listSessionsLocked(sessions);
+            } else {
+                final int size = mServicesCache.size();
+                for (int i = 0; i < size; i++) {
+                    mServicesCache.valueAt(i).listSessionsLocked(sessions);
+                }
+            }
+        }
+
+        resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions);
+        try {
+            receiver.send(0, resultData);
+        } catch (RemoteException e) {
+            // Just ignore it...
+        }
+    }
+
+    private void handleReset() {
+        synchronized (mLock) {
+            final int size = mServicesCache.size();
+            for (int i = 0; i < size; i++) {
+                mServicesCache.valueAt(i).destroyLocked();
+            }
+            mServicesCache.clear();
+        }
+    }
+
     final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
 
         @Override
index 9e0b31a..2891518 100644 (file)
@@ -70,6 +70,7 @@ import com.android.internal.os.IResultReceiver;
 import com.android.server.FgThread;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -330,6 +331,12 @@ final class AutoFillManagerServiceImpl {
         }
     }
 
+    void listSessionsLocked(ArrayList<String> output) {
+        for (IBinder activityToken : mSessions.keySet()) {
+            output.add(mComponentName + ":" + activityToken);
+        }
+    }
+
     @Override
     public String toString() {
         return "AutoFillManagerServiceImpl: [userId=" + mUserId
index 3318b2b..cfa4a1d 100644 (file)
 
 package com.android.server.autofill;
 
+import static com.android.server.autofill.AutoFillManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
+
 import android.app.ActivityManager;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ShellCommand;
 import android.os.UserHandle;
 
+import com.android.internal.os.IResultReceiver;
+
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public final class AutoFillManagerServiceShellCommand extends ShellCommand {
 
@@ -37,17 +45,16 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand {
             return handleDefaultCommands(cmd);
         }
         final PrintWriter pw = getOutPrintWriter();
-        try {
-            switch (cmd) {
-                case "save":
-                    return requestSave();
-                default:
-                    return handleDefaultCommands(cmd);
-            }
-        } catch (RemoteException e) {
-            pw.println("error: " + e);
+        switch (cmd) {
+            case "save":
+                return requestSave();
+            case "list":
+                return requestList(pw);
+            case "reset":
+                return requestReset();
+            default:
+                return handleDefaultCommands(cmd);
         }
-        return -1;
     }
 
     @Override
@@ -57,22 +64,79 @@ public final class AutoFillManagerServiceShellCommand extends ShellCommand {
             pw.println("  help");
             pw.println("    Prints this help text.");
             pw.println("");
+            pw.println("  list sessions [--user USER_ID]");
+            pw.println("    List all pending sessions.");
+            pw.println("");
             pw.println("  save [--user USER_ID]");
             pw.println("    Request provider to save contents of the top activity. ");
             pw.println("");
+            pw.println("  reset");
+            pw.println("    Reset all pending sessions and cached service connections.");
+            pw.println("");
         }
     }
 
-    private int requestSave() throws RemoteException {
-        final int userId = getUserIdFromArgs();
+    private int requestSave() {
+        final int userId = getUserIdFromArgsOrCurrentUser();
         mService.requestSaveForUser(userId);
         return 0;
     }
 
-    private int getUserIdFromArgs() {
+    private int requestList(PrintWriter pw) {
+        final String type = getNextArgRequired();
+        if (!type.equals("sessions")) {
+            pw.println("Error: invalid list type");
+            return -1;
+
+        }
+        final int userId = getUserIdFromArgsOrAllUsers();
+        final CountDownLatch latch = new CountDownLatch(1);
+        final IResultReceiver receiver = new IResultReceiver.Stub() {
+
+            @Override
+            public void send(int resultCode, Bundle resultData) throws RemoteException {
+                final ArrayList<String> sessions = resultData
+                        .getStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS);
+
+                for (String session : sessions) {
+                    pw.println(session);
+                }
+                latch.countDown();
+            }
+        };
+
+        mService.listSessions(userId, receiver);
+
+        try {
+            final boolean received = latch.await(5, TimeUnit.SECONDS);
+            if (!received) {
+                pw.println("Timed out after 5 seconds");
+                return -1;
+            }
+        } catch (InterruptedException e) {
+            pw.println("System call interrupted");
+            Thread.currentThread().interrupt();
+            return -1;
+        }
+        return 0;
+    }
+
+    private int requestReset() {
+        mService.reset();
+        return 0;
+    }
+
+    private int getUserIdFromArgsOrCurrentUser() {
         if ("--user".equals(getNextArg())) {
             return UserHandle.parseUserArg(getNextArgRequired());
         }
         return ActivityManager.getCurrentUser();
     }
+
+    private int getUserIdFromArgsOrAllUsers() {
+        if ("--user".equals(getNextArg())) {
+            return UserHandle.parseUserArg(getNextArgRequired());
+        }
+        return UserHandle.USER_ALL;
+    }
 }