Home | History | Annotate | Download | only in demomodecontroller
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.demomodecontroller;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.graphics.Color;
     23 import android.graphics.PointF;
     24 import android.os.Bundle;
     25 import android.os.Handler;
     26 import android.os.HandlerThread;
     27 import android.os.SystemClock;
     28 import android.util.Log;
     29 import android.view.MotionEvent;
     30 import android.view.View;
     31 import android.view.View.OnTouchListener;
     32 import android.view.ViewConfiguration;
     33 import android.view.WindowManager;
     34 import android.widget.Toast;
     35 
     36 public class DemoModeController extends Activity implements OnTouchListener {
     37     private static final String TAG = DemoModeController.class.getSimpleName();
     38     private static final boolean DEBUG = false;
     39 
     40     private final Context mContext = this;
     41     private final Handler mHandler = new Handler();
     42     private final PointF mLastDown = new PointF();
     43 
     44     private View mContent;
     45     private Handler mBackground;
     46     private int mTouchSlop;
     47     private long mLastDownTime;
     48     private boolean mControllingColor;
     49     private Toast mToast;
     50 
     51     @Override
     52     protected void onCreate(Bundle savedInstanceState) {
     53         super.onCreate(savedInstanceState);
     54         getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
     55                 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS  // so WM gives us enough room
     56                 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
     57         getActionBar().hide();
     58         mContent = new View(mContext);
     59         mContent.setBackgroundColor(0xff33b5e5);
     60         mContent.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
     61                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
     62                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
     63         mContent.setOnTouchListener(this);
     64         setContentView(mContent);
     65         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
     66 
     67         final HandlerThread background = new HandlerThread("background");
     68         background.start();
     69         mBackground = new Handler(background.getLooper());
     70         updateMode();
     71     }
     72 
     73     @Override
     74     protected void onPause() {
     75         super.onPause();
     76         exitDemoMode();
     77     }
     78 
     79     @Override
     80     protected void onResume() {
     81         super.onResume();
     82         exitDemoMode();
     83         mToast = Toast.makeText(mContext, R.string.help_text, Toast.LENGTH_LONG);
     84         mToast.show();
     85     }
     86 
     87     @Override
     88     public boolean onTouch(View v, MotionEvent event) {
     89         if (mToast != null) {
     90             mToast.cancel();
     91             mToast = null;
     92         }
     93         final int action = event.getAction();
     94         if (action == MotionEvent.ACTION_DOWN) {
     95             if (DEBUG) Log.d(TAG, "down");
     96             mHandler.postDelayed(mLongPressCheck, 500);
     97             final long now = SystemClock.uptimeMillis();
     98             if (now - mLastDownTime < 200) {
     99                 toggleMode();
    100             }
    101             mLastDownTime = now;
    102             mLastDown.x = event.getX();
    103             mLastDown.y = event.getY();
    104             return true;
    105         }
    106         if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
    107             if (DEBUG) Log.d(TAG, "upOrCancel");
    108             mControllingColor = false;
    109             mHandler.removeCallbacks(mLongPressCheck);
    110         }
    111         if (action != MotionEvent.ACTION_MOVE) return false;
    112 
    113         float x = event.getX();
    114         float y = event.getY();
    115         if (Math.abs(mLastDown.x - x) > mTouchSlop || Math.abs(mLastDown.y - y) > mTouchSlop) {
    116             mHandler.removeCallbacks(mLongPressCheck);
    117         }
    118         x = Math.max(x, 0);
    119         y = Math.max(y, 0);
    120         final int h = mContent.getMeasuredHeight();
    121         final int w = mContent.getMeasuredWidth();
    122         x = Math.min(x, w);
    123         y = Math.min(y, h);
    124 
    125         y = h - y;
    126         x = w - x;
    127 
    128         if (mControllingColor) {
    129             final float hue = y / (h / 360);
    130             final float sat = 1 - (x / (float)w);
    131             final float val = x / (float)w;
    132             final int color = Color.HSVToColor(new float[]{hue, sat, val});
    133             if (DEBUG) Log.d(TAG, String.format("hsv=(%s,%s,%s) argb=#%08x", hue, sat, val, color));
    134             mContent.setBackgroundColor(color);
    135             return true;
    136         }
    137 
    138         final int hh = (int)x / (w / 12);
    139         if (hh != mHH) {
    140             mHH = hh;
    141             mBackground.removeCallbacks(mUpdateClock);
    142             mBackground.post(mUpdateClock);
    143         }
    144 
    145         final int mm = (int)y / (h / 60);
    146         if (mm != mMM) {
    147             mMM = mm;
    148             mBackground.removeCallbacks(mUpdateClock);
    149             mBackground.post(mUpdateClock);
    150         }
    151 
    152         final int batteryLevel = (int)y / (h / 101);
    153         if (batteryLevel != mBatteryLevel) {
    154             mBatteryLevel = batteryLevel;
    155             mBackground.removeCallbacks(mUpdateBattery);
    156             mBackground.post(mUpdateBattery);
    157         }
    158 
    159         final boolean batteryPlugged = x >= w / 2;
    160         if (batteryPlugged != mBatteryPlugged) {
    161             mBatteryPlugged = batteryPlugged;
    162             mBackground.removeCallbacks(mUpdateBattery);
    163             mBackground.post(mUpdateBattery);
    164         }
    165 
    166         final int mobileLevel = (int)y / (h / 10);
    167         if (mobileLevel != mMobileLevel) {
    168             mMobileLevel = mobileLevel;
    169             mBackground.removeCallbacks(mUpdateMobile);
    170             mBackground.post(mUpdateMobile);
    171         }
    172 
    173         final int wifiLevel = (int)y / (h / 10);
    174         if (wifiLevel != mWifiLevel) {
    175             mWifiLevel = wifiLevel;
    176             mBackground.removeCallbacks(mUpdateWifi);
    177             mBackground.post(mUpdateWifi);
    178         }
    179 
    180         final int statusSlots = (int)x / (w / 13);
    181         if (statusSlots != mStatusSlots) {
    182             mStatusSlots = statusSlots;
    183             mBackground.removeCallbacks(mUpdateStatus);
    184             mBackground.post(mUpdateStatus);
    185         }
    186 
    187         final int networkIcons = (int)x / (w / 4);
    188         if (networkIcons != mNetworkIcons) {
    189             mNetworkIcons = networkIcons;
    190             mBackground.removeCallbacks(mUpdateNetwork);
    191             mBackground.post(mUpdateNetwork);
    192         }
    193 
    194         final int mobileDataType = (int)y / (h / 9);
    195         if (mobileDataType != mMobileDataType) {
    196             mMobileDataType = mobileDataType;
    197             mBackground.removeCallbacks(mUpdateMobile);
    198             mBackground.post(mUpdateMobile);
    199         }
    200         return true;
    201     }
    202 
    203     private void toggleMode() {
    204         if (DEBUG) Log.d(TAG, "toggleMode");
    205         mBarMode = (mBarMode + 1) % 3;
    206         updateMode();
    207     }
    208 
    209     private void updateMode() {
    210         mBackground.removeCallbacks(mUpdateBarMode);
    211         mBackground.post(mUpdateBarMode);
    212     }
    213 
    214     private final Runnable mLongPressCheck = new Runnable() {
    215         @Override
    216         public void run() {
    217             if (DEBUG) Log.d(TAG, "mControllingColor = true");
    218             mControllingColor = true;
    219 
    220         }
    221     };
    222 
    223     private void exitDemoMode() {
    224         if (DEBUG) Log.d(TAG, "exitDemoMode");
    225         final Intent intent = new Intent("com.android.systemui.demo");
    226         intent.putExtra("command", "exit");
    227         mContext.sendBroadcast(intent);
    228     }
    229 
    230     private int mStatusSlots; // 0 - 12
    231     private final Runnable mUpdateStatus = new Runnable() {
    232         @Override
    233         public void run() {
    234             final Intent intent = new Intent("com.android.systemui.demo");
    235             intent.putExtra("command", "status");
    236             intent.putExtra("volume", mStatusSlots < 1 ? "hide"
    237                     : mStatusSlots < 2 ? "silent" : "vibrate");
    238             intent.putExtra("bluetooth", mStatusSlots < 3 ? "hide"
    239                     : mStatusSlots < 4 ? "disconnected" : "connected");
    240             intent.putExtra("location", mStatusSlots < 5 ? "hide" : "show");
    241             intent.putExtra("alarm", mStatusSlots < 6 ? "hide" : "show");
    242             intent.putExtra("sync", mStatusSlots < 7 ? "hide" : "show");
    243             intent.putExtra("tty", mStatusSlots < 8 ? "hide" : "show");
    244             intent.putExtra("eri", mStatusSlots < 9 ? "hide" : "show");
    245             intent.putExtra("secure", mStatusSlots < 10 ? "hide" : "show");
    246             intent.putExtra("mute", mStatusSlots < 11 ? "hide" : "show");
    247             intent.putExtra("speakerphone", mStatusSlots < 12 ? "hide" : "show");
    248             mContext.sendBroadcast(intent);
    249         }
    250     };
    251 
    252     private int mNetworkIcons;  // 0:airplane  1:mobile  2:airplane+wifi  3:mobile+wifi
    253     private final Runnable mUpdateNetwork = new Runnable() {
    254         @Override
    255         public void run() {
    256             final Intent intent = new Intent("com.android.systemui.demo");
    257             intent.putExtra("command", "network");
    258             intent.putExtra("airplane", mNetworkIcons % 2 == 0 ? "show" : "hide");
    259             intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
    260             intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
    261             mContext.sendBroadcast(intent);
    262         }
    263     };
    264 
    265     private int mWifiLevel; // 0 - 4, 5 - 9, fully
    266     private final Runnable mUpdateWifi = new Runnable() {
    267         @Override
    268         public void run() {
    269             final Intent intent = new Intent("com.android.systemui.demo");
    270             intent.putExtra("command", "network");
    271             intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
    272             intent.putExtra("level", Integer.toString(mWifiLevel % 5));
    273             intent.putExtra("fully", Boolean.toString(mWifiLevel > 4));
    274             mContext.sendBroadcast(intent);
    275         }
    276     };
    277 
    278     private int mMobileLevel; // 0 - 4, 5 - 9, fully
    279     private int mMobileDataType; // 0 - 8
    280     private static final String getDataType(int dataType) {
    281         if (dataType == 1) return "1x";
    282         if (dataType == 2) return "3g";
    283         if (dataType == 3) return "4g";
    284         if (dataType == 4) return "e";
    285         if (dataType == 5) return "g";
    286         if (dataType == 6) return "h";
    287         if (dataType == 7) return "lte";
    288         if (dataType == 8) return "roam";
    289         return "";
    290     }
    291     private final Runnable mUpdateMobile = new Runnable() {
    292         @Override
    293         public void run() {
    294             final Intent intent = new Intent("com.android.systemui.demo");
    295             intent.putExtra("command", "network");
    296             intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
    297             intent.putExtra("level", Integer.toString(mMobileLevel % 5));
    298             intent.putExtra("fully", Boolean.toString(mMobileLevel > 4));
    299             intent.putExtra("datatype", getDataType(mMobileDataType));
    300             mContext.sendBroadcast(intent);
    301         }
    302     };
    303 
    304     private boolean mBatteryPlugged;
    305     private int mBatteryLevel; // 0 - 100
    306     private final Runnable mUpdateBattery = new Runnable() {
    307         @Override
    308         public void run() {
    309             final Intent intent = new Intent("com.android.systemui.demo");
    310             intent.putExtra("command", "battery");
    311             intent.putExtra("level", Integer.toString(mBatteryLevel));
    312             intent.putExtra("plugged", Boolean.toString(mBatteryPlugged));
    313             mContext.sendBroadcast(intent);
    314         }
    315     };
    316 
    317     private int mHH; // 0 - 11
    318     private int mMM; // 0 - 59
    319     private final Runnable mUpdateClock = new Runnable() {
    320         @Override
    321         public void run() {
    322             final Intent intent = new Intent("com.android.systemui.demo");
    323             intent.putExtra("command", "clock");
    324             intent.putExtra("hhmm", String.format("%02d%02d", mHH + 1, mMM));
    325             mContext.sendBroadcast(intent);
    326         }
    327     };
    328 
    329     private int mBarMode; // 0 - 2  (opaque, semi-transparent, translucent)
    330     private final Runnable mUpdateBarMode = new Runnable() {
    331         @Override
    332         public void run() {
    333             final Intent intent = new Intent("com.android.systemui.demo");
    334             intent.putExtra("command", "bars");
    335             intent.putExtra("mode", mBarMode == 1 ? "semi-transparent"
    336                     : mBarMode == 2 ? "translucent" : "opaque");
    337             mContext.sendBroadcast(intent);
    338         }
    339     };
    340 }
    341