aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/ui/hideable/AutoHideScheduler.java
blob: 7585979200787ad1761d43faa9bb1d3a1b93890f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package com.android.tv.ui.hideable;

import android.content.Context;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.support.annotation.VisibleForTesting;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import com.android.tv.common.WeakHandler;

/**
 * Schedules a view element to be hidden after a delay.
 *
 * <p>When accessibility is turned on elements are not automatically hidden.
 *
 * <p>Users of this class must pass it to {@link
 * AccessibilityManager#addAccessibilityStateChangeListener(AccessibilityStateChangeListener)} and
 * {@link
 * AccessibilityManager#removeAccessibilityStateChangeListener(AccessibilityStateChangeListener)}
 * during the appropriate live cycle event, or handle calling {@link
 * #onAccessibilityStateChanged(boolean)}.
 */
@UiThread
public final class AutoHideScheduler implements AccessibilityStateChangeListener {
    private static final int MSG_HIDE = 1;

    private final HideHandler mHandler;
    private final Runnable mRunnable;

    public AutoHideScheduler(Context context, Runnable runnable) {
        this(
                runnable,
                context.getSystemService(AccessibilityManager.class),
                Looper.getMainLooper());
    }

    @VisibleForTesting
    AutoHideScheduler(Runnable runnable, AccessibilityManager accessibilityManager, Looper looper) {
        // Keep a reference here because HideHandler only has a weak reference to it.
        mRunnable = runnable;
        mHandler = new HideHandler(looper, mRunnable);
        mHandler.setAllowAutoHide(!accessibilityManager.isEnabled());
    }

    public void cancel() {
        mHandler.removeMessages(MSG_HIDE);
    }

    public void schedule(long delayMs) {
        cancel();
        if (mHandler.mAllowAutoHide) {
            mHandler.sendEmptyMessageDelayed(MSG_HIDE, delayMs);
        }
    }

    @Override
    public void onAccessibilityStateChanged(boolean enabled) {
        mHandler.onAccessibilityStateChanged(enabled);
    }

    public boolean isScheduled() {
        return mHandler.hasMessages(MSG_HIDE);
    }

    private static class HideHandler extends WeakHandler<Runnable>
            implements AccessibilityStateChangeListener {

        private boolean mAllowAutoHide;

        public HideHandler(Looper looper, Runnable hideRunner) {
            super(looper, hideRunner);
        }

        @Override
        protected void handleMessage(Message msg, @NonNull Runnable runnable) {
            switch (msg.what) {
                case MSG_HIDE:
                    if (mAllowAutoHide) {
                        runnable.run();
                    }
                    break;
                default:
                    // do nothing
            }
        }

        public void setAllowAutoHide(boolean mAllowAutoHide) {
            this.mAllowAutoHide = mAllowAutoHide;
        }

        @Override
        public void onAccessibilityStateChanged(boolean enabled) {
            mAllowAutoHide = !enabled;
        }
    }
}