Home | History | Annotate | Download | only in hideable
      1 package com.android.tv.ui.hideable;
      2 
      3 import android.content.Context;
      4 import android.os.Looper;
      5 import android.os.Message;
      6 import android.support.annotation.NonNull;
      7 import android.support.annotation.UiThread;
      8 import android.support.annotation.VisibleForTesting;
      9 import android.view.accessibility.AccessibilityManager;
     10 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
     11 import com.android.tv.common.WeakHandler;
     12 
     13 /**
     14  * Schedules a view element to be hidden after a delay.
     15  *
     16  * <p>When accessibility is turned on elements are not automatically hidden.
     17  *
     18  * <p>Users of this class must pass it to {@link
     19  * AccessibilityManager#addAccessibilityStateChangeListener(AccessibilityStateChangeListener)} and
     20  * {@link
     21  * AccessibilityManager#removeAccessibilityStateChangeListener(AccessibilityStateChangeListener)}
     22  * during the appropriate live cycle event, or handle calling {@link
     23  * #onAccessibilityStateChanged(boolean)}.
     24  */
     25 @UiThread
     26 public final class AutoHideScheduler implements AccessibilityStateChangeListener {
     27     private static final int MSG_HIDE = 1;
     28 
     29     private final HideHandler mHandler;
     30     private final Runnable mRunnable;
     31 
     32     public AutoHideScheduler(Context context, Runnable runnable) {
     33         this(
     34                 runnable,
     35                 context.getSystemService(AccessibilityManager.class),
     36                 Looper.getMainLooper());
     37     }
     38 
     39     @VisibleForTesting
     40     AutoHideScheduler(Runnable runnable, AccessibilityManager accessibilityManager, Looper looper) {
     41         // Keep a reference here because HideHandler only has a weak reference to it.
     42         mRunnable = runnable;
     43         mHandler = new HideHandler(looper, mRunnable);
     44         mHandler.setAllowAutoHide(!accessibilityManager.isEnabled());
     45     }
     46 
     47     public void cancel() {
     48         mHandler.removeMessages(MSG_HIDE);
     49     }
     50 
     51     public void schedule(long delayMs) {
     52         cancel();
     53         if (mHandler.mAllowAutoHide) {
     54             mHandler.sendEmptyMessageDelayed(MSG_HIDE, delayMs);
     55         }
     56     }
     57 
     58     @Override
     59     public void onAccessibilityStateChanged(boolean enabled) {
     60         mHandler.onAccessibilityStateChanged(enabled);
     61     }
     62 
     63     public boolean isScheduled() {
     64         return mHandler.hasMessages(MSG_HIDE);
     65     }
     66 
     67     private static class HideHandler extends WeakHandler<Runnable>
     68             implements AccessibilityStateChangeListener {
     69 
     70         private boolean mAllowAutoHide;
     71 
     72         public HideHandler(Looper looper, Runnable hideRunner) {
     73             super(looper, hideRunner);
     74         }
     75 
     76         @Override
     77         protected void handleMessage(Message msg, @NonNull Runnable runnable) {
     78             switch (msg.what) {
     79                 case MSG_HIDE:
     80                     if (mAllowAutoHide) {
     81                         runnable.run();
     82                     }
     83                     break;
     84                 default:
     85                     // do nothing
     86             }
     87         }
     88 
     89         public void setAllowAutoHide(boolean mAllowAutoHide) {
     90             this.mAllowAutoHide = mAllowAutoHide;
     91         }
     92 
     93         @Override
     94         public void onAccessibilityStateChanged(boolean enabled) {
     95             mAllowAutoHide = !enabled;
     96         }
     97     }
     98 }
     99