diff options
Diffstat (limited to 'apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java')
-rwxr-xr-x | apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java | 338 |
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) {} + } +} |