Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22783d83 authored by Daniel Hsieh's avatar Daniel Hsieh
Browse files

Logs the activated session duration for magnification. (2/2)

Uses the atom MagnificationFollowTypingFocusActivatedSessionReported in
westworld to log the activated session duration for the window magnifier
which its following typing focus is enabled.

The duration is accumulated by the time when the window magnifier and
the ime are all on. If one of them is off, we would pause the
accumulated timer. If a user moves the window magnifier to disables
this function, we would stop the accumulated timer and log the duration.

Bug: 216733714
Test: m statsd_testdrive & statsd_testdrive 453
      atest WindowMagnificationManagerTest
Change-Id: I994fc2a3ada8a90fde8b3a0b4f1cc8d7ec21638a
Merged-In: I994fc2a3ada8a90fde8b3a0b4f1cc8d7ec21638a
parent 7902b951
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -167,6 +167,17 @@ public final class AccessibilityStatsLogUtils {
                convertToLoggingMagnificationMode(mode));
    }

    /**
     * Logs the duration for the window magnifier's following typing focus session.
     *
     * @param duration The duration of a triple-tap-and-hold activation session.
     */
    public static void logMagnificationFollowTypingFocusSession(long duration) {
        FrameworkStatsLog.write(
                FrameworkStatsLog.MAGNIFICATION_FOLLOW_TYPING_FOCUS_ACTIVATED_SESSION_REPORTED,
                duration);
    }

    /**
     * Logs the duration for the magnification session which is activated by the triple tap and
     * hold gesture.
+82 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;
import android.view.accessibility.MagnificationAnimationCallback;

import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
@@ -54,6 +55,7 @@ import com.android.server.wm.WindowManagerInternal;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

/**
 * A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}
@@ -136,6 +138,7 @@ public class WindowMagnificationManager implements
    private SparseArray<WindowMagnifier> mWindowMagnifiers = new SparseArray<>();
    // Whether the following typing focus feature for magnification is enabled.
    private boolean mMagnificationFollowTypingEnabled = true;
    @GuardedBy("mLock")
    private final SparseBooleanArray mIsImeVisibleArray = new SparseBooleanArray();

    private boolean mReceiverRegistered = false;
@@ -465,18 +468,43 @@ public class WindowMagnificationManager implements
        }
    }

    private void pauseTrackingTypingFocusRecord(int displayId) {
        WindowMagnifier magnifier;
        synchronized (mLock) {
            magnifier = mWindowMagnifiers.get(displayId);
            if (magnifier == null) {
                return;
            }
        }
        magnifier.pauseTrackingTypingFocusRecord();
    }

    /**
     * Called when the IME window visibility changed.
     *
     * @param shown {@code true} means the IME window shows on the screen. Otherwise, it's hidden.
     */
    void onImeWindowVisibilityChanged(int displayId, boolean shown) {
        synchronized (mLock) {
            mIsImeVisibleArray.put(displayId, shown);
        }
        if (shown) {
            enableAllTrackingTypingFocus();
        } else {
            pauseTrackingTypingFocusRecord(displayId);
        }
    }

    boolean isImeVisible(int displayId) {
        synchronized (mLock) {
            return mIsImeVisibleArray.get(displayId);
        }
    }

    void logTrackingTypingFocus(long duration) {
        AccessibilityStatsLogUtils.logMagnificationFollowTypingFocusSession(duration);
    }

    @Override
    public boolean processScroll(int displayId, float distanceX, float distanceY) {
        moveWindowMagnification(displayId, -distanceX, -distanceY);
@@ -969,6 +997,12 @@ public class WindowMagnificationManager implements

        private boolean mTrackingTypingFocusEnabled = true;

        private volatile long mTrackingTypingFocusStartTime = 0;
        private static final AtomicLongFieldUpdater<WindowMagnifier> SUM_TIME_UPDATER =
                AtomicLongFieldUpdater.newUpdater(WindowMagnifier.class,
                        "mTrackingTypingFocusSumTime");
        private volatile long mTrackingTypingFocusSumTime = 0;

        WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) {
            mDisplayId = displayId;
            mWindowMagnificationManager = windowMagnificationManager;
@@ -1017,6 +1051,7 @@ public class WindowMagnificationManager implements
                mEnabled = false;
                mIdOfLastServiceToControl = INVALID_SERVICE_ID;
                mTrackingTypingFocusEnabled = false;
                pauseTrackingTypingFocusRecord();
                return true;
            }
            return false;
@@ -1069,6 +1104,14 @@ public class WindowMagnificationManager implements
        }

        void setTrackingTypingFocusEnabled(boolean trackingTypingFocusEnabled) {
            if (mWindowMagnificationManager.isWindowMagnifierEnabled(mDisplayId)
                    && mWindowMagnificationManager.isImeVisible(mDisplayId)
                    && trackingTypingFocusEnabled) {
                startTrackingTypingFocusRecord();
            }
            if (mTrackingTypingFocusEnabled && !trackingTypingFocusEnabled) {
                stopAndLogTrackingTypingFocusRecordIfNeeded();
            }
            mTrackingTypingFocusEnabled = trackingTypingFocusEnabled;
        }

@@ -1076,6 +1119,44 @@ public class WindowMagnificationManager implements
            return mTrackingTypingFocusEnabled;
        }

        void startTrackingTypingFocusRecord() {
            if (mTrackingTypingFocusStartTime == 0) {
                mTrackingTypingFocusStartTime = SystemClock.uptimeMillis();
                if (DBG) {
                    Slog.d(TAG, "start: mTrackingTypingFocusStartTime = "
                            + mTrackingTypingFocusStartTime);
                }
            }
        }

        void pauseTrackingTypingFocusRecord() {
            if (mTrackingTypingFocusStartTime != 0) {
                final long elapsed = (SystemClock.uptimeMillis() - mTrackingTypingFocusStartTime);
                // update mTrackingTypingFocusSumTime value in an atomic operation
                SUM_TIME_UPDATER.addAndGet(this, elapsed);
                mTrackingTypingFocusStartTime = 0;
                if (DBG) {
                    Slog.d(TAG, "pause: mTrackingTypingFocusSumTime = "
                            + mTrackingTypingFocusSumTime + ", elapsed = " + elapsed);
                }
            }
        }

        void stopAndLogTrackingTypingFocusRecordIfNeeded() {
            if (mTrackingTypingFocusStartTime != 0 || mTrackingTypingFocusSumTime != 0) {
                final long elapsed = mTrackingTypingFocusStartTime != 0
                        ? (SystemClock.uptimeMillis() - mTrackingTypingFocusStartTime) : 0;
                final long duration = mTrackingTypingFocusSumTime + elapsed;
                if (DBG) {
                    Slog.d(TAG, "stop and log: session duration = " + duration
                            + ", elapsed = " + elapsed);
                }
                mWindowMagnificationManager.logTrackingTypingFocus(duration);
                mTrackingTypingFocusStartTime = 0;
                mTrackingTypingFocusSumTime = 0;
            }
        }

        boolean isEnabled() {
            return mEnabled;
        }
+13 −0
Original line number Diff line number Diff line
@@ -23,10 +23,12 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
@@ -292,6 +294,17 @@ public class WindowMagnificationManagerTest {
                MagnificationScaleProvider.MAX_SCALE);
    }

    @Test
    public void logTrackingTypingFocus_processScroll_logDuration() {
        WindowMagnificationManager spyWindowMagnificationManager = spy(mWindowMagnificationManager);
        spyWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3.0f, 50f, 50f);
        spyWindowMagnificationManager.onImeWindowVisibilityChanged(TEST_DISPLAY, /* shown */ true);

        spyWindowMagnificationManager.processScroll(TEST_DISPLAY, 10f, 10f);

        verify(spyWindowMagnificationManager).logTrackingTypingFocus(anyLong());
    }

    @Test
    public void onRectangleOnScreenRequested_trackingDisabledByOnDrag_withoutMovingMagnifier()
            throws RemoteException {