From c23929c3a34eb12663278fa323d3252a1ac3e57b Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Fri, 7 Feb 2014 14:47:47 -0500 Subject: Example controller app for system ui demo mode. Demo mode is protected behind a system setting. To enable: $ adb shell settings put global sysui_demo_allowed 1 Change-Id: I2248e27a253bf9eac176e8be9153a2b147cefa40 --- tests/SystemUIDemoModeController/Android.mk | 10 + .../SystemUIDemoModeController/AndroidManifest.xml | 39 +++ .../res/values/strings.xml | 22 ++ .../demomodecontroller/DemoModeController.java | 340 +++++++++++++++++++++ 4 files changed, 411 insertions(+) create mode 100644 tests/SystemUIDemoModeController/Android.mk create mode 100644 tests/SystemUIDemoModeController/AndroidManifest.xml create mode 100644 tests/SystemUIDemoModeController/res/values/strings.xml create mode 100644 tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java (limited to 'tests') diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk new file mode 100644 index 0000000..64ea63c --- /dev/null +++ b/tests/SystemUIDemoModeController/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := DemoModeController + +include $(BUILD_PACKAGE) diff --git a/tests/SystemUIDemoModeController/AndroidManifest.xml b/tests/SystemUIDemoModeController/AndroidManifest.xml new file mode 100644 index 0000000..2e97932 --- /dev/null +++ b/tests/SystemUIDemoModeController/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + diff --git a/tests/SystemUIDemoModeController/res/values/strings.xml b/tests/SystemUIDemoModeController/res/values/strings.xml new file mode 100644 index 0000000..257a353 --- /dev/null +++ b/tests/SystemUIDemoModeController/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + + + Demo Mode Controller + "Drag: control icon states\nLong-press + drag: control background color\nDouble-tap: toggle bar mode + + diff --git a/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java new file mode 100644 index 0000000..b177d7e --- /dev/null +++ b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.demomodecontroller; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.graphics.PointF; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.SystemClock; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; +import android.view.ViewConfiguration; +import android.view.WindowManager; +import android.widget.Toast; + +public class DemoModeController extends Activity implements OnTouchListener { + private static final String TAG = DemoModeController.class.getSimpleName(); + private static final boolean DEBUG = false; + + private final Context mContext = this; + private final Handler mHandler = new Handler(); + private final PointF mLastDown = new PointF(); + + private View mContent; + private Handler mBackground; + private int mTouchSlop; + private long mLastDownTime; + private boolean mControllingColor; + private Toast mToast; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS // so WM gives us enough room + | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); + getActionBar().hide(); + mContent = new View(mContext); + mContent.setBackgroundColor(0xff33b5e5); + mContent.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + mContent.setOnTouchListener(this); + setContentView(mContent); + mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + + final HandlerThread background = new HandlerThread("background"); + background.start(); + mBackground = new Handler(background.getLooper()); + updateMode(); + } + + @Override + protected void onPause() { + super.onPause(); + exitDemoMode(); + } + + @Override + protected void onResume() { + super.onResume(); + exitDemoMode(); + mToast = Toast.makeText(mContext, R.string.help_text, Toast.LENGTH_LONG); + mToast.show(); + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + if (mToast != null) { + mToast.cancel(); + mToast = null; + } + final int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + if (DEBUG) Log.d(TAG, "down"); + mHandler.postDelayed(mLongPressCheck, 500); + final long now = SystemClock.uptimeMillis(); + if (now - mLastDownTime < 200) { + toggleMode(); + } + mLastDownTime = now; + mLastDown.x = event.getX(); + mLastDown.y = event.getY(); + return true; + } + if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + if (DEBUG) Log.d(TAG, "upOrCancel"); + mControllingColor = false; + mHandler.removeCallbacks(mLongPressCheck); + } + if (action != MotionEvent.ACTION_MOVE) return false; + + float x = event.getX(); + float y = event.getY(); + if (Math.abs(mLastDown.x - x) > mTouchSlop || Math.abs(mLastDown.y - y) > mTouchSlop) { + mHandler.removeCallbacks(mLongPressCheck); + } + x = Math.max(x, 0); + y = Math.max(y, 0); + final int h = mContent.getMeasuredHeight(); + final int w = mContent.getMeasuredWidth(); + x = Math.min(x, w); + y = Math.min(y, h); + + y = h - y; + x = w - x; + + if (mControllingColor) { + final float hue = y / (h / 360); + final float sat = 1 - (x / (float)w); + final float val = x / (float)w; + final int color = Color.HSVToColor(new float[]{hue, sat, val}); + if (DEBUG) Log.d(TAG, String.format("hsv=(%s,%s,%s) argb=#%08x", hue, sat, val, color)); + mContent.setBackgroundColor(color); + return true; + } + + final int hh = (int)x / (w / 12); + if (hh != mHH) { + mHH = hh; + mBackground.removeCallbacks(mUpdateClock); + mBackground.post(mUpdateClock); + } + + final int mm = (int)y / (h / 60); + if (mm != mMM) { + mMM = mm; + mBackground.removeCallbacks(mUpdateClock); + mBackground.post(mUpdateClock); + } + + final int batteryLevel = (int)y / (h / 101); + if (batteryLevel != mBatteryLevel) { + mBatteryLevel = batteryLevel; + mBackground.removeCallbacks(mUpdateBattery); + mBackground.post(mUpdateBattery); + } + + final boolean batteryPlugged = x >= w / 2; + if (batteryPlugged != mBatteryPlugged) { + mBatteryPlugged = batteryPlugged; + mBackground.removeCallbacks(mUpdateBattery); + mBackground.post(mUpdateBattery); + } + + final int mobileLevel = (int)y / (h / 10); + if (mobileLevel != mMobileLevel) { + mMobileLevel = mobileLevel; + mBackground.removeCallbacks(mUpdateMobile); + mBackground.post(mUpdateMobile); + } + + final int wifiLevel = (int)y / (h / 10); + if (wifiLevel != mWifiLevel) { + mWifiLevel = wifiLevel; + mBackground.removeCallbacks(mUpdateWifi); + mBackground.post(mUpdateWifi); + } + + final int statusSlots = (int)x / (w / 13); + if (statusSlots != mStatusSlots) { + mStatusSlots = statusSlots; + mBackground.removeCallbacks(mUpdateStatus); + mBackground.post(mUpdateStatus); + } + + final int networkIcons = (int)x / (w / 4); + if (networkIcons != mNetworkIcons) { + mNetworkIcons = networkIcons; + mBackground.removeCallbacks(mUpdateNetwork); + mBackground.post(mUpdateNetwork); + } + + final int mobileDataType = (int)y / (h / 9); + if (mobileDataType != mMobileDataType) { + mMobileDataType = mobileDataType; + mBackground.removeCallbacks(mUpdateMobile); + mBackground.post(mUpdateMobile); + } + return true; + } + + private void toggleMode() { + if (DEBUG) Log.d(TAG, "toggleMode"); + mBarMode = (mBarMode + 1) % 3; + updateMode(); + } + + private void updateMode() { + mBackground.removeCallbacks(mUpdateBarMode); + mBackground.post(mUpdateBarMode); + } + + private final Runnable mLongPressCheck = new Runnable() { + @Override + public void run() { + if (DEBUG) Log.d(TAG, "mControllingColor = true"); + mControllingColor = true; + + } + }; + + private void exitDemoMode() { + if (DEBUG) Log.d(TAG, "exitDemoMode"); + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "exit"); + mContext.sendBroadcast(intent); + } + + private int mStatusSlots; // 0 - 12 + private final Runnable mUpdateStatus = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "status"); + intent.putExtra("volume", mStatusSlots < 1 ? "hide" + : mStatusSlots < 2 ? "silent" : "vibrate"); + intent.putExtra("bluetooth", mStatusSlots < 3 ? "hide" + : mStatusSlots < 4 ? "disconnected" : "connected"); + intent.putExtra("location", mStatusSlots < 5 ? "hide" : "show"); + intent.putExtra("alarm", mStatusSlots < 6 ? "hide" : "show"); + intent.putExtra("sync", mStatusSlots < 7 ? "hide" : "show"); + intent.putExtra("tty", mStatusSlots < 8 ? "hide" : "show"); + intent.putExtra("eri", mStatusSlots < 9 ? "hide" : "show"); + intent.putExtra("secure", mStatusSlots < 10 ? "hide" : "show"); + intent.putExtra("mute", mStatusSlots < 11 ? "hide" : "show"); + intent.putExtra("speakerphone", mStatusSlots < 12 ? "hide" : "show"); + mContext.sendBroadcast(intent); + } + }; + + private int mNetworkIcons; // 0:airplane 1:mobile 2:airplane+wifi 3:mobile+wifi + private final Runnable mUpdateNetwork = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "network"); + intent.putExtra("airplane", mNetworkIcons % 2 == 0 ? "show" : "hide"); + intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide"); + intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide"); + mContext.sendBroadcast(intent); + } + }; + + private int mWifiLevel; // 0 - 4, 5 - 9, fully + private final Runnable mUpdateWifi = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "network"); + intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide"); + intent.putExtra("level", Integer.toString(mWifiLevel % 5)); + intent.putExtra("fully", Boolean.toString(mWifiLevel > 4)); + mContext.sendBroadcast(intent); + } + }; + + private int mMobileLevel; // 0 - 4, 5 - 9, fully + private int mMobileDataType; // 0 - 8 + private static final String getDataType(int dataType) { + if (dataType == 1) return "1x"; + if (dataType == 2) return "3g"; + if (dataType == 3) return "4g"; + if (dataType == 4) return "e"; + if (dataType == 5) return "g"; + if (dataType == 6) return "h"; + if (dataType == 7) return "lte"; + if (dataType == 8) return "roam"; + return ""; + } + private final Runnable mUpdateMobile = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "network"); + intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide"); + intent.putExtra("level", Integer.toString(mMobileLevel % 5)); + intent.putExtra("fully", Boolean.toString(mMobileLevel > 4)); + intent.putExtra("datatype", getDataType(mMobileDataType)); + mContext.sendBroadcast(intent); + } + }; + + private boolean mBatteryPlugged; + private int mBatteryLevel; // 0 - 100 + private final Runnable mUpdateBattery = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "battery"); + intent.putExtra("level", Integer.toString(mBatteryLevel)); + intent.putExtra("plugged", Boolean.toString(mBatteryPlugged)); + mContext.sendBroadcast(intent); + } + }; + + private int mHH; // 0 - 11 + private int mMM; // 0 - 59 + private final Runnable mUpdateClock = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "clock"); + intent.putExtra("hhmm", String.format("%02d%02d", mHH + 1, mMM)); + mContext.sendBroadcast(intent); + } + }; + + private int mBarMode; // 0 - 2 (opaque, semi-transparent, translucent) + private final Runnable mUpdateBarMode = new Runnable() { + @Override + public void run() { + final Intent intent = new Intent("com.android.systemui.demo"); + intent.putExtra("command", "bars"); + intent.putExtra("mode", mBarMode == 1 ? "semi-transparent" + : mBarMode == 2 ? "translucent" : "opaque"); + mContext.sendBroadcast(intent); + } + }; +} -- cgit v1.1