aboutsummaryrefslogtreecommitdiff
path: root/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java')
-rwxr-xr-xapps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java338
1 files changed, 338 insertions, 0 deletions
diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java
new file mode 100755
index 000000000..61c308152
--- /dev/null
+++ b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2012 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.android.tools.sdkcontroller.activities;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.os.Bundle;
+import android.os.Message;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.View.OnKeyListener;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+import com.android.tools.sdkcontroller.R;
+import com.android.tools.sdkcontroller.handlers.SensorChannel;
+import com.android.tools.sdkcontroller.handlers.SensorChannel.MonitoredSensor;
+import com.android.tools.sdkcontroller.lib.Channel;
+import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder;
+import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener;
+
+/**
+ * Activity that displays and controls the sensors from {@link SensorChannel}.
+ * For each sensor it displays a checkbox that is enabled if the sensor is supported
+ * by the emulator. The user can select whether the sensor is active. It also displays
+ * data from the sensor when available.
+ */
+public class SensorActivity extends BaseBindingActivity
+ implements android.os.Handler.Callback {
+
+ @SuppressWarnings("hiding")
+ public static String TAG = SensorActivity.class.getSimpleName();
+ private static boolean DEBUG = true;
+
+ private static final int MSG_UPDATE_ACTUAL_HZ = 0x31415;
+
+ private TableLayout mTableLayout;
+ private TextView mTextError;
+ private TextView mTextStatus;
+ private TextView mTextTargetHz;
+ private TextView mTextActualHz;
+ private SensorChannel mSensorHandler;
+
+ private final Map<MonitoredSensor, DisplayInfo> mDisplayedSensors =
+ new HashMap<SensorChannel.MonitoredSensor, SensorActivity.DisplayInfo>();
+ private final android.os.Handler mUiHandler = new android.os.Handler(this);
+ private int mTargetSampleRate;
+ private long mLastActualUpdateMs;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sensors);
+ mTableLayout = (TableLayout) findViewById(R.id.tableLayout);
+ mTextError = (TextView) findViewById(R.id.textError);
+ mTextStatus = (TextView) findViewById(R.id.textStatus);
+ mTextTargetHz = (TextView) findViewById(R.id.textSampleRate);
+ mTextActualHz = (TextView) findViewById(R.id.textActualRate);
+ updateStatus("Waiting for connection");
+
+ mTextTargetHz.setOnKeyListener(new OnKeyListener() {
+ @Override
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ updateSampleRate();
+ return false;
+ }
+ });
+ mTextTargetHz.setOnFocusChangeListener(new OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ updateSampleRate();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ if (DEBUG) Log.d(TAG, "onResume");
+ // BaseBindingActivity.onResume will bind to the service.
+ super.onResume();
+ updateError();
+ }
+
+ @Override
+ protected void onPause() {
+ if (DEBUG) Log.d(TAG, "onPause");
+ // BaseBindingActivity.onResume will unbind from (but not stop) the service.
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ if (DEBUG) Log.d(TAG, "onDestroy");
+ super.onDestroy();
+ removeSensorUi();
+ }
+
+ // ----------
+
+ @Override
+ protected void onServiceConnected() {
+ if (DEBUG) Log.d(TAG, "onServiceConnected");
+ createSensorUi();
+ }
+
+ @Override
+ protected void onServiceDisconnected() {
+ if (DEBUG) Log.d(TAG, "onServiceDisconnected");
+ removeSensorUi();
+ }
+
+ @Override
+ protected ControllerListener createControllerListener() {
+ return new SensorsControllerListener();
+ }
+
+ // ----------
+
+ private class SensorsControllerListener implements ControllerListener {
+ @Override
+ public void onErrorChanged() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ updateError();
+ }
+ });
+ }
+
+ @Override
+ public void onStatusChanged() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ControllerBinder binder = getServiceBinder();
+ if (binder != null) {
+ boolean connected = binder.isEmuConnected();
+ mTableLayout.setEnabled(connected);
+ updateStatus(connected ? "Emulated connected" : "Emulator disconnected");
+ }
+ }
+ });
+ }
+ }
+
+ private void createSensorUi() {
+ final LayoutInflater inflater = getLayoutInflater();
+
+ if (!mDisplayedSensors.isEmpty()) {
+ removeSensorUi();
+ }
+
+ mSensorHandler = (SensorChannel) getServiceBinder().getChannel(Channel.SENSOR_CHANNEL);
+ if (mSensorHandler != null) {
+ mSensorHandler.addUiHandler(mUiHandler);
+ mUiHandler.sendEmptyMessage(MSG_UPDATE_ACTUAL_HZ);
+
+ assert mDisplayedSensors.isEmpty();
+ List<MonitoredSensor> sensors = mSensorHandler.getSensors();
+ for (MonitoredSensor sensor : sensors) {
+ final TableRow row = (TableRow) inflater.inflate(R.layout.sensor_row,
+ mTableLayout,
+ false);
+ mTableLayout.addView(row);
+ mDisplayedSensors.put(sensor, new DisplayInfo(sensor, row));
+ }
+ }
+ }
+
+ private void removeSensorUi() {
+ if (mSensorHandler != null) {
+ mSensorHandler.removeUiHandler(mUiHandler);
+ mSensorHandler = null;
+ }
+ mTableLayout.removeAllViews();
+ for (DisplayInfo info : mDisplayedSensors.values()) {
+ info.release();
+ }
+ mDisplayedSensors.clear();
+ }
+
+ private class DisplayInfo implements CompoundButton.OnCheckedChangeListener {
+ private MonitoredSensor mSensor;
+ private CheckBox mChk;
+ private TextView mVal;
+
+ public DisplayInfo(MonitoredSensor sensor, TableRow row) {
+ mSensor = sensor;
+
+ // Initialize displayed checkbox for this sensor, and register
+ // checked state listener for it.
+ mChk = (CheckBox) row.findViewById(R.id.row_checkbox);
+ mChk.setText(sensor.getUiName());
+ mChk.setEnabled(sensor.isEnabledByEmulator());
+ mChk.setChecked(sensor.isEnabledByUser());
+ mChk.setOnCheckedChangeListener(this);
+
+ // Initialize displayed text box for this sensor.
+ mVal = (TextView) row.findViewById(R.id.row_textview);
+ mVal.setText(sensor.getValue());
+ }
+
+ /**
+ * Handles checked state change for the associated CheckBox. If check
+ * box is checked we will register sensor change listener. If it is
+ * unchecked, we will unregister sensor change listener.
+ */
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (mSensor != null) {
+ mSensor.onCheckedChanged(isChecked);
+ }
+ }
+
+ public void release() {
+ mChk = null;
+ mVal = null;
+ mSensor = null;
+
+ }
+
+ public void updateState() {
+ if (mChk != null && mSensor != null) {
+ mChk.setEnabled(mSensor.isEnabledByEmulator());
+ mChk.setChecked(mSensor.isEnabledByUser());
+ }
+ }
+
+ public void updateValue() {
+ if (mVal != null && mSensor != null) {
+ mVal.setText(mSensor.getValue());
+ }
+ }
+ }
+
+ /** Implementation of Handler.Callback */
+ @Override
+ public boolean handleMessage(Message msg) {
+ DisplayInfo info = null;
+ switch (msg.what) {
+ case SensorChannel.SENSOR_STATE_CHANGED:
+ info = mDisplayedSensors.get(msg.obj);
+ if (info != null) {
+ info.updateState();
+ }
+ break;
+ case SensorChannel.SENSOR_DISPLAY_MODIFIED:
+ info = mDisplayedSensors.get(msg.obj);
+ if (info != null) {
+ info.updateValue();
+ }
+ if (mSensorHandler != null) {
+ updateStatus(Integer.toString(mSensorHandler.getMsgSentCount()) + " events sent");
+
+ // Update the "actual rate" field if the value has changed
+ long ms = mSensorHandler.getActualUpdateMs();
+ if (ms != mLastActualUpdateMs) {
+ mLastActualUpdateMs = ms;
+ String hz = mLastActualUpdateMs <= 0 ? "--" :
+ Integer.toString((int) Math.ceil(1000. / ms));
+ mTextActualHz.setText(hz);
+ }
+ }
+ break;
+ case MSG_UPDATE_ACTUAL_HZ:
+ if (mSensorHandler != null) {
+ // Update the "actual rate" field if the value has changed
+ long ms = mSensorHandler.getActualUpdateMs();
+ if (ms != mLastActualUpdateMs) {
+ mLastActualUpdateMs = ms;
+ String hz = mLastActualUpdateMs <= 0 ? "--" :
+ Integer.toString((int) Math.ceil(1000. / ms));
+ mTextActualHz.setText(hz);
+ }
+ mUiHandler.sendEmptyMessageDelayed(MSG_UPDATE_ACTUAL_HZ, 1000 /*1s*/);
+ }
+ }
+ return true; // we consumed this message
+ }
+
+ private void updateStatus(String status) {
+ mTextStatus.setVisibility(status == null ? View.GONE : View.VISIBLE);
+ if (status != null) mTextStatus.setText(status);
+ }
+
+ private void updateError() {
+ ControllerBinder binder = getServiceBinder();
+ String error = binder == null ? "" : binder.getServiceError();
+ if (error == null) {
+ error = "";
+ }
+
+ mTextError.setVisibility(error.length() == 0 ? View.GONE : View.VISIBLE);
+ mTextError.setText(error);
+ }
+
+ private void updateSampleRate() {
+ String str = mTextTargetHz.getText().toString();
+ try {
+ int hz = Integer.parseInt(str.trim());
+
+ // Cap the value. 50 Hz is a reasonable max value for the emulator.
+ if (hz <= 0 || hz > 50) {
+ hz = 50;
+ }
+
+ if (hz != mTargetSampleRate) {
+ mTargetSampleRate = hz;
+ if (mSensorHandler != null) {
+ mSensorHandler.setUpdateTargetMs(hz <= 0 ? 0 : (int)(1000.0f / hz));
+ }
+ }
+ } catch (Exception ignore) {}
+ }
+}