Log window mode to tron.

Bug: 26013430
Change-Id: I45d397d956a66f407218047dc10581553f906077
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index be1fd58..90a5d3f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1434,6 +1434,7 @@
     static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
     static final int IDLE_UIDS_MSG = 60;
     static final int SYSTEM_USER_UNLOCK_MSG = 61;
+    static final int LOG_STACK_STATE = 62;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2143,6 +2144,11 @@
             case IDLE_UIDS_MSG: {
                 idleUids();
             } break;
+            case LOG_STACK_STATE: {
+                synchronized (ActivityManagerService.this) {
+                    mStackSupervisor.logStackState();
+                }
+            } break;
             }
         }
     };
@@ -10902,6 +10908,7 @@
 
     /** Notifies all listeners when the task stack has changed. */
     void notifyTaskStackChangedLocked() {
+        mHandler.sendEmptyMessage(LOG_STACK_STATE);
         mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
         Message nmsg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
         mHandler.sendMessageDelayed(nmsg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY);
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
new file mode 100644
index 0000000..64f423c
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -0,0 +1,72 @@
+package com.android.server.am;
+
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+
+import android.app.ActivityManager.StackId;
+import android.content.Context;
+import android.os.SystemClock;
+
+import com.android.internal.logging.MetricsLogger;
+
+/**
+ * Handles logging into Tron.
+ */
+class ActivityMetricsLogger {
+    // Window modes we are interested in logging. If we ever introduce a new type, we need to add
+    // a value here and increase the {@link #TRON_WINDOW_STATE_VARZ_STRINGS} array.
+    private static final int WINDOW_STATE_STANDARD = 0;
+    private static final int WINDOW_STATE_SIDE_BY_SIDE = 1;
+    private static final int WINDOW_STATE_FREEFORM = 2;
+    private static final int WINDOW_STATE_INVALID = -1;
+
+    // Preallocated strings we are sending to tron, so we don't have to allocate a new one every
+    // time we log.
+    private static final String[] TRON_WINDOW_STATE_VARZ_STRINGS = {
+            "tron_varz_window_time_0", "tron_varz_window_time_1", "tron_varz_window_time_2"};
+
+    private int mWindowState = WINDOW_STATE_STANDARD;
+    private long mLastLogTimeSecs;
+    private final ActivityStackSupervisor mSupervisor;
+    private final Context mContext;
+
+    ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context) {
+        mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
+        mSupervisor = supervisor;
+        mContext = context;
+    }
+
+    void logWindowState() {
+        final long now = SystemClock.elapsedRealtime() / 1000;
+        if (mWindowState != WINDOW_STATE_INVALID) {
+            // We log even if the window state hasn't changed, because the user might remain in
+            // home/fullscreen move forever and we would like to track this kind of behavior
+            // too.
+            MetricsLogger.count(mContext, TRON_WINDOW_STATE_VARZ_STRINGS[mWindowState],
+                    (int) (now - mLastLogTimeSecs));
+        }
+        mLastLogTimeSecs = now;
+
+        mWindowState = WINDOW_STATE_INVALID;
+        ActivityStack stack = mSupervisor.getStack(DOCKED_STACK_ID);
+        if (stack != null && stack.isStackVisibleLocked()) {
+            mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
+        }
+        if (mWindowState == WINDOW_STATE_INVALID) {
+            stack = mSupervisor.getFocusedStack();
+            if (stack.mStackId == HOME_STACK_ID
+                    || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+                mWindowState = WINDOW_STATE_STANDARD;
+            } else if (stack.mStackId == DOCKED_STACK_ID) {
+                throw new IllegalStateException("Docked stack shouldn't be the focused stack, "
+                        + "because it reported not being visible.");
+            } else if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+                mWindowState = WINDOW_STATE_FREEFORM;
+            } else if (StackId.isStaticStack(stack.mStackId)) {
+                throw new IllegalStateException("Unknown stack=" + stack);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ca9f28e..ffa6a4d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1334,7 +1334,7 @@
     }
 
     /** Returns true if the stack is considered visible. */
-    private boolean isStackVisibleLocked() {
+    boolean isStackVisibleLocked() {
         if (!isAttached()) {
             return false;
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 9fff0c8..119f42d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -34,7 +34,6 @@
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
 import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
@@ -76,7 +75,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
@@ -107,7 +105,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
-import android.os.storage.StorageManager;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -123,13 +120,11 @@
 import android.view.DisplayInfo;
 import android.view.InputEvent;
 import android.view.Surface;
-import android.widget.Toast;
 
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.content.ReferrerIntent;
 import com.android.internal.os.TransferPipe;
-import com.android.internal.R;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
@@ -374,6 +369,8 @@
     // Whether tasks have moved and we need to rank the tasks before next OOM scoring
     private boolean mTaskLayersChanged = true;
 
+    private final ActivityMetricsLogger mActivityMetricsLogger;
+
     /**
      * Description of a request to start a new activity, which has been held
      * due to app switches being disabled.
@@ -410,6 +407,7 @@
         mService = service;
         mRecentTasks = recentTasks;
         mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
+        mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
     }
 
     /**
@@ -3465,7 +3463,7 @@
         if (!r.info.supportsPip) {
             Slog.w(TAG,
                     "moveTopStackActivityToPinnedStackLocked: Picture-In-Picture not supported for "
-                    + " r=" + r);
+                            + " r=" + r);
             return false;
         }
 
@@ -4521,6 +4519,10 @@
         return mLockTaskModeState;
     }
 
+    void logStackState() {
+        mActivityMetricsLogger.logWindowState();
+    }
+
     private final class ActivityStackSupervisorHandler extends Handler {
 
         public ActivityStackSupervisorHandler(Looper looper) {