diff options
author | Raphael Moll <ralf@android.com> | 2012-08-08 11:16:03 -0700 |
---|---|---|
committer | android code review <noreply-gerritcodereview@google.com> | 2012-08-08 11:16:04 -0700 |
commit | 24952281d4985f8cd5be0de36349c57e845c1a05 (patch) | |
tree | 0d9354ee017e1a62f4705527e8fa7b19355bacb6 | |
parent | 333e659cd078a0cf687973309ae2a4025b478d51 (diff) | |
parent | 3c7c9c4b0b75d8817951a2c0764c6837335cd5e9 (diff) | |
download | sdk-24952281d4985f8cd5be0de36349c57e845c1a05.zip sdk-24952281d4985f8cd5be0de36349c57e845c1a05.tar.gz sdk-24952281d4985f8cd5be0de36349c57e845c1a05.tar.bz2 |
Merge "Cleanup: dos2unix some files in SdkController."
18 files changed, 3357 insertions, 3357 deletions
diff --git a/apps/SdkController/AndroidManifest.xml b/apps/SdkController/AndroidManifest.xml index e6c876a..df7aa47 100755 --- a/apps/SdkController/AndroidManifest.xml +++ b/apps/SdkController/AndroidManifest.xml @@ -1,44 +1,44 @@ -<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tools.sdkcontroller"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="7"
- android:targetSdkVersion="15" />
-
- <uses-permission android:name="android.permission.INTERNET" />
-
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
-
- <activity
- android:name=".activities.MainActivity"
- android:label="@string/app_name"
- android:launchMode="singleInstance" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
- <activity
- android:name=".activities.SensorActivity"
- android:launchMode="singleInstance"
- android:windowSoftInputMode="stateUnchanged" android:label="@string/sensors_activity_title"/>
-
- <activity
- android:name=".activities.MultiTouchActivity"
- android:launchMode="singleInstance"
- android:screenOrientation="portrait"
- android:theme="@style/Theme.MultiTouch"
- android:windowSoftInputMode="stateHidden"/>
-
- <service
- android:name=".service.ControllerService"
- android:description="@string/service_description"
- android:icon="@drawable/ic_launcher" />
- </application>
-</manifest>
+<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tools.sdkcontroller" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="7" + android:targetSdkVersion="15" /> + + <uses-permission android:name="android.permission.INTERNET" /> + + <application + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" > + + <activity + android:name=".activities.MainActivity" + android:label="@string/app_name" + android:launchMode="singleInstance" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity + android:name=".activities.SensorActivity" + android:launchMode="singleInstance" + android:windowSoftInputMode="stateUnchanged" android:label="@string/sensors_activity_title"/> + + <activity + android:name=".activities.MultiTouchActivity" + android:launchMode="singleInstance" + android:screenOrientation="portrait" + android:theme="@style/Theme.MultiTouch" + android:windowSoftInputMode="stateHidden"/> + + <service + android:name=".service.ControllerService" + android:description="@string/service_description" + android:icon="@drawable/ic_launcher" /> + </application> +</manifest> diff --git a/apps/SdkController/res/layout-land/sensors.xml b/apps/SdkController/res/layout-land/sensors.xml index 2d14089..1f3e2f1 100755 --- a/apps/SdkController/res/layout-land/sensors.xml +++ b/apps/SdkController/res/layout-land/sensors.xml @@ -1,168 +1,168 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > -
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <TableRow
- android:id="@+id/row1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_sample_rate"
- android:gravity="right"
- android:layout_marginRight="8dp"
- />
-
- <EditText
- android:id="@+id/textSampleRate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ems="4"
- android:gravity="right"
- android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen|"
- android:inputType="number"
- android:text="@string/sensors_default_sample_rate"
- tools:ignore="HardcodedText" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_hz_per_sensor" />
-
- </TableRow>
-
- <TableRow
- android:id="@+id/row2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignBaseline="@+id/row1"
- >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="right"
- android:layout_marginRight="8dp"
- android:text="@string/sensors_actual_rate" />
-
- <TextView
- android:id="@+id/textActualRate"
- android:gravity="right"
- android:text="--"
- tools:ignore="HardcodedText"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_hz_average" />
-
- <!-- This 1-pixel wide invisible edit field makes sure that row1 and
- row2 have the same height and an equal baseline. This works around
- the fact that row2's attribute layout_alignBaseline=row1 is in fact
- ignored. -->
- <EditText
- android:layout_width="1px"
- android:layout_height="wrap_content"
- android:imeOptions="actionNone"
- android:focusable="false"
- android:focusableInTouchMode="false"
- android:visibility="invisible"
- />
-
- </TableRow>
-
- </RelativeLayout>
-
- <TableLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
+ + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + <TableRow + android:id="@+id/row1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_sample_rate" + android:gravity="right" + android:layout_marginRight="8dp" + /> + + <EditText + android:id="@+id/textSampleRate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ems="4" + android:gravity="right" + android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen|" + android:inputType="number" + android:text="@string/sensors_default_sample_rate" + tools:ignore="HardcodedText" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_hz_per_sensor" /> + + </TableRow> + + <TableRow + android:id="@+id/row2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_alignBaseline="@+id/row1" + > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="right" + android:layout_marginRight="8dp" + android:text="@string/sensors_actual_rate" /> + + <TextView + android:id="@+id/textActualRate" + android:gravity="right" + android:text="--" + tools:ignore="HardcodedText" + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_hz_average" /> + + <!-- This 1-pixel wide invisible edit field makes sure that row1 and + row2 have the same height and an equal baseline. This works around + the fact that row2's attribute layout_alignBaseline=row1 is in fact + ignored. --> + <EditText + android:layout_width="1px" + android:layout_height="wrap_content" + android:imeOptions="actionNone" + android:focusable="false" + android:focusableInTouchMode="false" + android:visibility="invisible" + /> + + </TableRow> + + </RelativeLayout> + + <TableLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" > -
- <TableRow
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- </TableRow>
-
- <TableRow
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- </TableRow>
-
- </TableLayout>
-
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:text="@string/sensors_top_description" />
-
- <ScrollView
- android:id="@+id/scrollView1"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
+ + <TableRow + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + </TableRow> + + <TableRow + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + </TableRow> + + </TableLayout> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:text="@string/sensors_top_description" /> + + <ScrollView + android:id="@+id/scrollView1" + android:layout_width="fill_parent" + android:layout_height="0dp" android:layout_weight="1" > -
- <TableLayout
- android:id="@+id/tableLayout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:saveEnabled="false" />
-
- </ScrollView>
-
- <!-- Placeholder status text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textStatus"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <!-- Placeholder error text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textError"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:background="#F00F"
- android:padding="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#FFF0" />
-
+ + <TableLayout + android:id="@+id/tableLayout" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:saveEnabled="false" /> + + </ScrollView> + + <!-- Placeholder status text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textStatus" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <!-- Placeholder error text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textError" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:background="#F00F" + android:padding="8dp" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="#FFF0" /> + </LinearLayout>
\ No newline at end of file diff --git a/apps/SdkController/res/layout/main.xml b/apps/SdkController/res/layout/main.xml index 1a98d9e..2e7a4bb 100755 --- a/apps/SdkController/res/layout/main.xml +++ b/apps/SdkController/res/layout/main.xml @@ -1,116 +1,116 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- >
-
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="8dp" >
-
- <ToggleButton
- android:id="@+id/toggleService"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- />
-
- <TextView
- android:id="@+id/labelService"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@+id/toggleService"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="20dp"
- android:text="@string/main_label_service"
- android:textAppearance="?android:attr/textAppearanceLarge" />
-
- <!-- Placeholder status text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textStatus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@+id/labelService"
- android:layout_marginLeft="8dp"
- android:layout_toRightOf="@+id/labelService"
- android:text="[status]"
- android:textAppearance="?android:attr/textAppearanceLarge"
- tools:ignore="HardcodedText" />
-
- <!-- Placeholder error text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textError"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_below="@+id/toggleService"
- android:layout_marginBottom="8dp"
- android:layout_marginTop="8dp"
- android:background="#F00F"
- android:gravity="center_horizontal"
- android:padding="8dp"
- android:text="[service errors]"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="#FFF0"
- tools:ignore="HardcodedText" />
-
- <TextView
- android:id="@+id/labelButtons"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/textError"
- android:layout_marginTop="16dp"
- android:text="@string/main_label_buttons"
- android:textAppearance="?android:attr/textAppearanceLarge" />
-
- <Button
- android:id="@+id/btnOpenMultitouch"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/labelButtons"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="16dp"
- android:text="@string/main_btn_open_multitouch" />
-
- <Button
- android:id="@+id/btnOpenSensors"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/btnOpenMultitouch"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="16dp"
- android:text="@string/main_btn_open_sensors" />
-
- <WebView
- android:id="@+id/webIntro"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/btnOpenSensors"
- android:layout_marginTop="16dp"
- android:background="@null"
- />
-
- </RelativeLayout>
-</ScrollView>
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> + +<ScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + > + + <RelativeLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:padding="8dp" > + + <ToggleButton + android:id="@+id/toggleService" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + /> + + <TextView + android:id="@+id/labelService" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBaseline="@+id/toggleService" + android:layout_alignParentLeft="true" + android:layout_marginTop="20dp" + android:text="@string/main_label_service" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + <!-- Placeholder status text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textStatus" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignBaseline="@+id/labelService" + android:layout_marginLeft="8dp" + android:layout_toRightOf="@+id/labelService" + android:text="[status]" + android:textAppearance="?android:attr/textAppearanceLarge" + tools:ignore="HardcodedText" /> + + <!-- Placeholder error text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textError" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_alignParentRight="true" + android:layout_below="@+id/toggleService" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:background="#F00F" + android:gravity="center_horizontal" + android:padding="8dp" + android:text="[service errors]" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="#FFF0" + tools:ignore="HardcodedText" /> + + <TextView + android:id="@+id/labelButtons" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/textError" + android:layout_marginTop="16dp" + android:text="@string/main_label_buttons" + android:textAppearance="?android:attr/textAppearanceLarge" /> + + <Button + android:id="@+id/btnOpenMultitouch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/labelButtons" + android:layout_centerHorizontal="true" + android:layout_marginTop="16dp" + android:text="@string/main_btn_open_multitouch" /> + + <Button + android:id="@+id/btnOpenSensors" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_below="@+id/btnOpenMultitouch" + android:layout_centerHorizontal="true" + android:layout_marginTop="16dp" + android:text="@string/main_btn_open_sensors" /> + + <WebView + android:id="@+id/webIntro" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_below="@+id/btnOpenSensors" + android:layout_marginTop="16dp" + android:background="@null" + /> + + </RelativeLayout> +</ScrollView> diff --git a/apps/SdkController/res/layout/sensor_row.xml b/apps/SdkController/res/layout/sensor_row.xml index e02bae7..16ffd42 100755 --- a/apps/SdkController/res/layout/sensor_row.xml +++ b/apps/SdkController/res/layout/sensor_row.xml @@ -1,42 +1,42 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2011 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.
- */
--->
-
-<!-- One row per sensor added to the TableLayout from layout/sensors.xml -->
-<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <CheckBox
- android:id="@+id/row_checkbox"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="10dp"
- android:saveEnabled="false"
- android:text="Some CheckBox"
- tools:ignore="HardcodedText" />
-
- <TextView
- android:id="@+id/row_textview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</TableRow>
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2011 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. + */ +--> + +<!-- One row per sensor added to the TableLayout from layout/sensors.xml --> +<TableRow xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" > + + <CheckBox + android:id="@+id/row_checkbox" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="10dp" + android:saveEnabled="false" + android:text="Some CheckBox" + tools:ignore="HardcodedText" /> + + <TextView + android:id="@+id/row_textview" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textAppearance="?android:attr/textAppearanceSmall" /> + +</TableRow> diff --git a/apps/SdkController/res/layout/sensors.xml b/apps/SdkController/res/layout/sensors.xml index 8f5df34..afdab02 100755 --- a/apps/SdkController/res/layout/sensors.xml +++ b/apps/SdkController/res/layout/sensors.xml @@ -1,130 +1,130 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" > -
- <TableLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
+ + <TableLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" > -
- <TableRow
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_sample_rate"
- android:gravity="right"
- android:layout_marginRight="8dp"
- />
- <EditText
- android:id="@+id/textSampleRate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:ems="4"
- android:gravity="right"
- android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen|"
- android:inputType="number"
- android:text="@string/sensors_default_sample_rate" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_hz_per_sensor" />
-
- </TableRow>
-
- <TableRow
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="right"
- android:layout_marginRight="8dp"
- android:text="@string/sensors_actual_rate" />
-
- <TextView
- android:id="@+id/textActualRate"
- android:gravity="right"
- android:text="--"
- tools:ignore="HardcodedText"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sensors_hz_average" />
-
- </TableRow>
-
- </TableLayout>
-
- <TextView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:text="@string/sensors_top_description" />
-
- <ScrollView
- android:id="@+id/scrollView1"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
+ + <TableRow + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_sample_rate" + android:gravity="right" + android:layout_marginRight="8dp" + />
+ <EditText + android:id="@+id/textSampleRate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ems="4" + android:gravity="right" + android:imeOptions="actionNone|flagNoExtractUi|flagNoFullscreen|" + android:inputType="number" + android:text="@string/sensors_default_sample_rate" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_hz_per_sensor" /> + + </TableRow> + + <TableRow + android:layout_width="wrap_content" + android:layout_height="wrap_content" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:gravity="right" + android:layout_marginRight="8dp" + android:text="@string/sensors_actual_rate" /> + + <TextView + android:id="@+id/textActualRate" + android:gravity="right" + android:text="--" + tools:ignore="HardcodedText" + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/sensors_hz_average" /> + + </TableRow> + + </TableLayout> + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:text="@string/sensors_top_description" /> + + <ScrollView + android:id="@+id/scrollView1" + android:layout_width="fill_parent" + android:layout_height="0dp" android:layout_weight="1" > -
- <TableLayout
- android:id="@+id/tableLayout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:saveEnabled="false" />
-
- </ScrollView>
-
- <!-- Placeholder status text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textStatus"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <!-- Placeholder error text. Becomes visibility=gone when empty. -->
- <TextView
- android:id="@+id/textError"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:background="#F00F"
- android:padding="8dp"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="#FFF0" />
-
+ + <TableLayout + android:id="@+id/tableLayout" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:saveEnabled="false" /> + + </ScrollView> + + <!-- Placeholder status text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textStatus" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textAppearance="?android:attr/textAppearanceSmall" /> + + <!-- Placeholder error text. Becomes visibility=gone when empty. --> + <TextView + android:id="@+id/textError" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:background="#F00F" + android:padding="8dp" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="#FFF0" /> + </LinearLayout>
\ No newline at end of file diff --git a/apps/SdkController/res/values-v11/styles_v11.xml b/apps/SdkController/res/values-v11/styles_v11.xml index 6f58f57..3d3860e 100755 --- a/apps/SdkController/res/values-v11/styles_v11.xml +++ b/apps/SdkController/res/values-v11/styles_v11.xml @@ -1,26 +1,26 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-
-<resources>
-
- <style name="Theme.MultiTouch" parent="android:Theme.Holo.NoActionBar.Fullscreen">
- <item name="android:windowBackground">@android:color/transparent</item>
- </style>
-
-</resources>
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> + +<resources> + + <style name="Theme.MultiTouch" parent="android:Theme.Holo.NoActionBar.Fullscreen"> + <item name="android:windowBackground">@android:color/transparent</item> + </style> + +</resources> diff --git a/apps/SdkController/res/values/strings.xml b/apps/SdkController/res/values/strings.xml index bb8a1c0..e4e1dbb 100755 --- a/apps/SdkController/res/values/strings.xml +++ b/apps/SdkController/res/values/strings.xml @@ -1,48 +1,48 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-
-<resources>
-
- <!-- Strings for manifest. -->
- <string name="app_name">SDK Controller</string>
- <string name="service_description">Background service for SDK Controller</string>
-
- <!-- Strings for service. -->
- <string name="service_notif_title">SDK Controller is running</string>
-
- <!-- Strings for layout/main -->
- <string name="main_label_service">Service:</string>
- <string name="main_label_buttons">What you can do:</string>
- <string name="main_btn_open_multitouch">Control Multi-touch</string>
- <string name="main_btn_open_sensors">Control Sensors</string>
- <string name="main_service_status_connected">Emulator Connected</string>
- <string name="main_service_status_disconnected">Emulator Connected</string>
-
- <!-- Strings for layout/sensors -->
- <string name="sensors_activity_title">SDK Controller > Sensors</string>
- <string name="sensors_top_description">Available Sensors:</string>
- <string name="sensors_sample_rate">Sample Rate</string>
- <string name="sensors_hz_per_sensor">Hz per sensor</string>
- <string name="sensors_actual_rate">Actual</string>
- <string name="sensors_hz_average">Hz average</string>
- <!-- Default sample rate for SensorsActivity UI.
- Should match the default for SensorsHandler.mUpdateTargetMs. -->
- <string name="sensors_default_sample_rate">20</string>
-
-</resources>
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> + +<resources> + + <!-- Strings for manifest. --> + <string name="app_name">SDK Controller</string> + <string name="service_description">Background service for SDK Controller</string> + + <!-- Strings for service. --> + <string name="service_notif_title">SDK Controller is running</string> + + <!-- Strings for layout/main --> + <string name="main_label_service">Service:</string> + <string name="main_label_buttons">What you can do:</string> + <string name="main_btn_open_multitouch">Control Multi-touch</string> + <string name="main_btn_open_sensors">Control Sensors</string> + <string name="main_service_status_connected">Emulator Connected</string> + <string name="main_service_status_disconnected">Emulator Connected</string> + + <!-- Strings for layout/sensors --> + <string name="sensors_activity_title">SDK Controller > Sensors</string> + <string name="sensors_top_description">Available Sensors:</string> + <string name="sensors_sample_rate">Sample Rate</string> + <string name="sensors_hz_per_sensor">Hz per sensor</string> + <string name="sensors_actual_rate">Actual</string> + <string name="sensors_hz_average">Hz average</string> + <!-- Default sample rate for SensorsActivity UI. + Should match the default for SensorsHandler.mUpdateTargetMs. --> + <string name="sensors_default_sample_rate">20</string> + +</resources> diff --git a/apps/SdkController/res/values/styles.xml b/apps/SdkController/res/values/styles.xml index 376a577..67c7278 100755 --- a/apps/SdkController/res/values/styles.xml +++ b/apps/SdkController/res/values/styles.xml @@ -1,26 +1,26 @@ -<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-
-<resources>
-
- <style name="Theme.MultiTouch" parent="android:Theme.NoTitleBar.Fullscreen">
- <item name="android:windowBackground">@android:color/transparent</item>
- </style>
-
-</resources>
+<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * 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. + */ +--> + +<resources> + + <style name="Theme.MultiTouch" parent="android:Theme.NoTitleBar.Fullscreen"> + <item name="android:windowBackground">@android:color/transparent</item> + </style> + +</resources> diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java index c0079d9..faba882 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java @@ -1,388 +1,388 @@ -/*
- * 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.io.ByteArrayInputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import android.graphics.Color;
-import android.os.Bundle;
-import android.os.Message;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.widget.TextView;
-
-import com.android.tools.sdkcontroller.R;
-import com.android.tools.sdkcontroller.handlers.MultiTouchChannel;
-import com.android.tools.sdkcontroller.lib.Channel;
-import com.android.tools.sdkcontroller.lib.ProtocolConstants;
-import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder;
-import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener;
-import com.android.tools.sdkcontroller.utils.ApiHelper;
-import com.android.tools.sdkcontroller.views.MultiTouchView;
-
-/**
- * Activity that controls and displays the {@link MultiTouchChannel}.
- */
-public class MultiTouchActivity extends BaseBindingActivity
- implements android.os.Handler.Callback {
-
- @SuppressWarnings("hiding")
- private static String TAG = MultiTouchActivity.class.getSimpleName();
- private static boolean DEBUG = true;
-
- private volatile MultiTouchChannel mHandler;
-
- private TextView mTextError;
- private TextView mTextStatus;
- private MultiTouchView mImageView;
- /** Width of the emulator's display. */
- private int mEmulatorWidth = 0;
- /** Height of the emulator's display. */
- private int mEmulatorHeight = 0;
- /** Bitmap storage. */
- private int[] mColors;
-
- private final TouchListener mTouchListener = new TouchListener();
- private final android.os.Handler mUiHandler = new android.os.Handler(this);
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.multitouch);
- mImageView = (MultiTouchView) findViewById(R.id.imageView);
- mTextError = (TextView) findViewById(R.id.textError);
- mTextStatus = (TextView) findViewById(R.id.textStatus);
- updateStatus("Waiting for connection");
-
- ApiHelper ah = ApiHelper.get();
- ah.View_setSystemUiVisibility(mImageView, View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
-
- @Override
- protected void onResume() {
- if (DEBUG) Log.d(TAG, "onResume");
- // BaseBindingActivity.onResume will bind to the service.
- // Note: any initialization related to the service or the handler should
- // go in onServiceConnected() since in this call the service may not be
- // bound yet.
- 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();
- mImageView.setEnabled(false);
- updateStatus("Paused");
- }
-
- // ----------
-
- @Override
- protected void onServiceConnected() {
- if (DEBUG) Log.d(TAG, "onServiceConnected");
- mHandler = (MultiTouchChannel) getServiceBinder().getChannel(Channel.MULTITOUCH_CHANNEL);
- if (mHandler != null) {
- mHandler.setViewSize(mImageView.getWidth(), mImageView.getHeight());
- mHandler.addUiHandler(mUiHandler);
- }
- }
-
- @Override
- protected void onServiceDisconnected() {
- if (DEBUG) Log.d(TAG, "onServiceDisconnected");
- if (mHandler != null) {
- mHandler.removeUiHandler(mUiHandler);
- mHandler = null;
- }
- }
-
- @Override
- protected ControllerListener createControllerListener() {
- return new MultiTouchControllerListener();
- }
-
- // ----------
-
- private class MultiTouchControllerListener 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();
- mImageView.setEnabled(connected);
- updateStatus(connected ? "Emulator connected" : "Emulator disconnected");
- }
- }
- });
- }
- }
-
- // ----------
-
- /**
- * Implements OnTouchListener interface that receives touch screen events,
- * and reports them to the emulator application.
- */
- class TouchListener implements OnTouchListener {
- /**
- * Touch screen event handler.
- */
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- ByteBuffer bb = null;
- final int action = event.getAction();
- final int action_code = action & MotionEvent.ACTION_MASK;
- final int action_pid_index = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
- int msg_type = 0;
- MultiTouchChannel h = mHandler;
-
- // Build message for the emulator.
- switch (action_code) {
- case MotionEvent.ACTION_MOVE:
- if (h != null) {
- bb = ByteBuffer.allocate(
- event.getPointerCount() * ProtocolConstants.MT_EVENT_ENTRY_SIZE);
- bb.order(h.getEndian());
- for (int n = 0; n < event.getPointerCount(); n++) {
- mImageView.constructEventMessage(bb, event, n);
- }
- msg_type = ProtocolConstants.MT_MOVE;
- }
- break;
- case MotionEvent.ACTION_DOWN:
- if (h != null) {
- bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
- bb.order(h.getEndian());
- mImageView.constructEventMessage(bb, event, action_pid_index);
- msg_type = ProtocolConstants.MT_FISRT_DOWN;
- }
- break;
- case MotionEvent.ACTION_UP:
- if (h != null) {
- bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
- bb.order(h.getEndian());
- bb.putInt(event.getPointerId(action_pid_index));
- msg_type = ProtocolConstants.MT_LAST_UP;
- }
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- if (h != null) {
- bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
- bb.order(h.getEndian());
- mImageView.constructEventMessage(bb, event, action_pid_index);
- msg_type = ProtocolConstants.MT_POINTER_DOWN;
- }
- break;
- case MotionEvent.ACTION_POINTER_UP:
- if (h != null) {
- bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
- bb.order(h.getEndian());
- bb.putInt(event.getPointerId(action_pid_index));
- msg_type = ProtocolConstants.MT_POINTER_UP;
- }
- break;
- default:
- Log.w(TAG, "Unknown action type: " + action_code);
- return true;
- }
-
- if (DEBUG && bb != null) Log.d(TAG, bb.toString());
-
- if (h != null && bb != null) {
- h.postMessage(msg_type, bb);
- }
- return true;
- }
- } // TouchListener
-
- /** Implementation of Handler.Callback */
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MultiTouchChannel.EVENT_MT_START:
- MultiTouchChannel h = mHandler;
- if (h != null) {
- mImageView.setEnabled(true);
- mImageView.setOnTouchListener(mTouchListener);
- }
- break;
- case MultiTouchChannel.EVENT_MT_STOP:
- mImageView.setOnTouchListener(null);
- break;
- case MultiTouchChannel.EVENT_FRAME_BUFFER:
- onFrameBuffer(((ByteBuffer) msg.obj).array());
- mHandler.postMessage(ProtocolConstants.MT_FB_HANDLED, (byte[]) null);
- break;
- }
- return true; // we consumed this message
- }
-
- /**
- * Called when a BLOB query is received from the emulator.
- * <p/>
- * This query is used to deliver framebuffer updates in the emulator. The
- * blob contains an update header, followed by the bitmap containing updated
- * rectangle. The header is defined as MTFrameHeader structure in
- * external/qemu/android/multitouch-port.h
- * <p/>
- * NOTE: This method is called from the I/O loop, so all communication with
- * the emulator will be "on hold" until this method returns.
- *
- * TODO ===> CHECK that we can consume that array from a different thread than the producer's.
- * E.g. does the produce reuse the same array or does it generate a new one each time?
- *
- * @param array contains BLOB data for the query.
- */
- private void onFrameBuffer(byte[] array) {
- final ByteBuffer bb = ByteBuffer.wrap(array);
- bb.order(ByteOrder.LITTLE_ENDIAN);
-
- // Read frame header.
- final int header_size = bb.getInt();
- final int disp_width = bb.getInt();
- final int disp_height = bb.getInt();
- final int x = bb.getInt();
- final int y = bb.getInt();
- final int w = bb.getInt();
- final int h = bb.getInt();
- final int bpl = bb.getInt();
- final int bpp = bb.getInt();
- final int format = bb.getInt();
-
- // Update application display.
- updateDisplay(disp_width, disp_height);
-
- if (format == ProtocolConstants.MT_FRAME_JPEG) {
- /*
- * Framebuffer is in JPEG format.
- */
-
- final ByteArrayInputStream jpg = new ByteArrayInputStream(bb.array());
- // Advance input stream to JPEG image.
- jpg.skip(header_size);
- // Draw the image.
- mImageView.drawJpeg(x, y, w, h, jpg);
- } else {
- /*
- * Framebuffer is in a raw RGB format.
- */
-
- final int pixel_num = h * w;
- // Advance stream to the beginning of framebuffer data.
- bb.position(header_size);
-
- // Make sure that mColors is large enough to contain the
- // update bitmap.
- if (mColors == null || mColors.length < pixel_num) {
- mColors = new int[pixel_num];
- }
-
- // Convert the blob bitmap into bitmap that we will display.
- if (format == ProtocolConstants.MT_FRAME_RGB565) {
- for (int n = 0; n < pixel_num; n++) {
- // Blob bitmap is in RGB565 format.
- final int color = bb.getShort();
- final int r = ((color & 0xf800) >> 8) | ((color & 0xf800) >> 14);
- final int g = ((color & 0x7e0) >> 3) | ((color & 0x7e0) >> 9);
- final int b = ((color & 0x1f) << 3) | ((color & 0x1f) >> 2);
- mColors[n] = Color.rgb(r, g, b);
- }
- } else if (format == ProtocolConstants.MT_FRAME_RGB888) {
- for (int n = 0; n < pixel_num; n++) {
- // Blob bitmap is in RGB565 format.
- final int r = bb.getChar();
- final int g = bb.getChar();
- final int b = bb.getChar();
- mColors[n] = Color.rgb(r, g, b);
- }
- } else {
- Log.w(TAG, "Invalid framebuffer format: " + format);
- return;
- }
- mImageView.drawBitmap(x, y, w, h, mColors);
- }
- }
-
- /**
- * Updates application's screen accordingly to the emulator screen.
- *
- * @param e_width Width of the emulator screen.
- * @param e_height Height of the emulator screen.
- */
- private void updateDisplay(int e_width, int e_height) {
- if (e_width != mEmulatorWidth || e_height != mEmulatorHeight) {
- mEmulatorWidth = e_width;
- mEmulatorHeight = e_height;
-
- boolean rotateDisplay = false;
- int w = mImageView.getWidth();
- int h = mImageView.getHeight();
- if (w > h != e_width > e_height) {
- rotateDisplay = true;
- int tmp = w;
- w = h;
- h = tmp;
- }
-
- float dx = (float) w / (float) e_width;
- float dy = (float) h / (float) e_height;
- mImageView.setDxDy(dx, dy, rotateDisplay);
- if (DEBUG) Log.d(TAG, "Dispay updated: " + e_width + " x " + e_height +
- " -> " + w + " x " + h + " ratio: " +
- dx + " x " + dy);
- }
- }
-
- // ----------
-
- 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);
- }
-}
+/* + * 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.io.ByteArrayInputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import android.graphics.Color; +import android.os.Bundle; +import android.os.Message; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; +import android.widget.TextView; + +import com.android.tools.sdkcontroller.R; +import com.android.tools.sdkcontroller.handlers.MultiTouchChannel; +import com.android.tools.sdkcontroller.lib.Channel; +import com.android.tools.sdkcontroller.lib.ProtocolConstants; +import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder; +import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener; +import com.android.tools.sdkcontroller.utils.ApiHelper; +import com.android.tools.sdkcontroller.views.MultiTouchView; + +/** + * Activity that controls and displays the {@link MultiTouchChannel}. + */ +public class MultiTouchActivity extends BaseBindingActivity + implements android.os.Handler.Callback { + + @SuppressWarnings("hiding") + private static String TAG = MultiTouchActivity.class.getSimpleName(); + private static boolean DEBUG = true; + + private volatile MultiTouchChannel mHandler; + + private TextView mTextError; + private TextView mTextStatus; + private MultiTouchView mImageView; + /** Width of the emulator's display. */ + private int mEmulatorWidth = 0; + /** Height of the emulator's display. */ + private int mEmulatorHeight = 0; + /** Bitmap storage. */ + private int[] mColors; + + private final TouchListener mTouchListener = new TouchListener(); + private final android.os.Handler mUiHandler = new android.os.Handler(this); + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.multitouch); + mImageView = (MultiTouchView) findViewById(R.id.imageView); + mTextError = (TextView) findViewById(R.id.textError); + mTextStatus = (TextView) findViewById(R.id.textStatus); + updateStatus("Waiting for connection"); + + ApiHelper ah = ApiHelper.get(); + ah.View_setSystemUiVisibility(mImageView, View.SYSTEM_UI_FLAG_LOW_PROFILE); + } + + @Override + protected void onResume() { + if (DEBUG) Log.d(TAG, "onResume"); + // BaseBindingActivity.onResume will bind to the service. + // Note: any initialization related to the service or the handler should + // go in onServiceConnected() since in this call the service may not be + // bound yet. + 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(); + mImageView.setEnabled(false); + updateStatus("Paused"); + } + + // ---------- + + @Override + protected void onServiceConnected() { + if (DEBUG) Log.d(TAG, "onServiceConnected"); + mHandler = (MultiTouchChannel) getServiceBinder().getChannel(Channel.MULTITOUCH_CHANNEL); + if (mHandler != null) { + mHandler.setViewSize(mImageView.getWidth(), mImageView.getHeight()); + mHandler.addUiHandler(mUiHandler); + } + } + + @Override + protected void onServiceDisconnected() { + if (DEBUG) Log.d(TAG, "onServiceDisconnected"); + if (mHandler != null) { + mHandler.removeUiHandler(mUiHandler); + mHandler = null; + } + } + + @Override + protected ControllerListener createControllerListener() { + return new MultiTouchControllerListener(); + } + + // ---------- + + private class MultiTouchControllerListener 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(); + mImageView.setEnabled(connected); + updateStatus(connected ? "Emulator connected" : "Emulator disconnected"); + } + } + }); + } + } + + // ---------- + + /** + * Implements OnTouchListener interface that receives touch screen events, + * and reports them to the emulator application. + */ + class TouchListener implements OnTouchListener { + /** + * Touch screen event handler. + */ + @Override + public boolean onTouch(View v, MotionEvent event) { + ByteBuffer bb = null; + final int action = event.getAction(); + final int action_code = action & MotionEvent.ACTION_MASK; + final int action_pid_index = action >> MotionEvent.ACTION_POINTER_ID_SHIFT; + int msg_type = 0; + MultiTouchChannel h = mHandler; + + // Build message for the emulator. + switch (action_code) { + case MotionEvent.ACTION_MOVE: + if (h != null) { + bb = ByteBuffer.allocate( + event.getPointerCount() * ProtocolConstants.MT_EVENT_ENTRY_SIZE); + bb.order(h.getEndian()); + for (int n = 0; n < event.getPointerCount(); n++) { + mImageView.constructEventMessage(bb, event, n); + } + msg_type = ProtocolConstants.MT_MOVE; + } + break; + case MotionEvent.ACTION_DOWN: + if (h != null) { + bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE); + bb.order(h.getEndian()); + mImageView.constructEventMessage(bb, event, action_pid_index); + msg_type = ProtocolConstants.MT_FISRT_DOWN; + } + break; + case MotionEvent.ACTION_UP: + if (h != null) { + bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE); + bb.order(h.getEndian()); + bb.putInt(event.getPointerId(action_pid_index)); + msg_type = ProtocolConstants.MT_LAST_UP; + } + break; + case MotionEvent.ACTION_POINTER_DOWN: + if (h != null) { + bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE); + bb.order(h.getEndian()); + mImageView.constructEventMessage(bb, event, action_pid_index); + msg_type = ProtocolConstants.MT_POINTER_DOWN; + } + break; + case MotionEvent.ACTION_POINTER_UP: + if (h != null) { + bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE); + bb.order(h.getEndian()); + bb.putInt(event.getPointerId(action_pid_index)); + msg_type = ProtocolConstants.MT_POINTER_UP; + } + break; + default: + Log.w(TAG, "Unknown action type: " + action_code); + return true; + } + + if (DEBUG && bb != null) Log.d(TAG, bb.toString()); + + if (h != null && bb != null) { + h.postMessage(msg_type, bb); + } + return true; + } + } // TouchListener + + /** Implementation of Handler.Callback */ + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MultiTouchChannel.EVENT_MT_START: + MultiTouchChannel h = mHandler; + if (h != null) { + mImageView.setEnabled(true); + mImageView.setOnTouchListener(mTouchListener); + } + break; + case MultiTouchChannel.EVENT_MT_STOP: + mImageView.setOnTouchListener(null); + break; + case MultiTouchChannel.EVENT_FRAME_BUFFER: + onFrameBuffer(((ByteBuffer) msg.obj).array()); + mHandler.postMessage(ProtocolConstants.MT_FB_HANDLED, (byte[]) null); + break; + } + return true; // we consumed this message + } + + /** + * Called when a BLOB query is received from the emulator. + * <p/> + * This query is used to deliver framebuffer updates in the emulator. The + * blob contains an update header, followed by the bitmap containing updated + * rectangle. The header is defined as MTFrameHeader structure in + * external/qemu/android/multitouch-port.h + * <p/> + * NOTE: This method is called from the I/O loop, so all communication with + * the emulator will be "on hold" until this method returns. + * + * TODO ===> CHECK that we can consume that array from a different thread than the producer's. + * E.g. does the produce reuse the same array or does it generate a new one each time? + * + * @param array contains BLOB data for the query. + */ + private void onFrameBuffer(byte[] array) { + final ByteBuffer bb = ByteBuffer.wrap(array); + bb.order(ByteOrder.LITTLE_ENDIAN); + + // Read frame header. + final int header_size = bb.getInt(); + final int disp_width = bb.getInt(); + final int disp_height = bb.getInt(); + final int x = bb.getInt(); + final int y = bb.getInt(); + final int w = bb.getInt(); + final int h = bb.getInt(); + final int bpl = bb.getInt(); + final int bpp = bb.getInt(); + final int format = bb.getInt(); + + // Update application display. + updateDisplay(disp_width, disp_height); + + if (format == ProtocolConstants.MT_FRAME_JPEG) { + /* + * Framebuffer is in JPEG format. + */ + + final ByteArrayInputStream jpg = new ByteArrayInputStream(bb.array()); + // Advance input stream to JPEG image. + jpg.skip(header_size); + // Draw the image. + mImageView.drawJpeg(x, y, w, h, jpg); + } else { + /* + * Framebuffer is in a raw RGB format. + */ + + final int pixel_num = h * w; + // Advance stream to the beginning of framebuffer data. + bb.position(header_size); + + // Make sure that mColors is large enough to contain the + // update bitmap. + if (mColors == null || mColors.length < pixel_num) { + mColors = new int[pixel_num]; + } + + // Convert the blob bitmap into bitmap that we will display. + if (format == ProtocolConstants.MT_FRAME_RGB565) { + for (int n = 0; n < pixel_num; n++) { + // Blob bitmap is in RGB565 format. + final int color = bb.getShort(); + final int r = ((color & 0xf800) >> 8) | ((color & 0xf800) >> 14); + final int g = ((color & 0x7e0) >> 3) | ((color & 0x7e0) >> 9); + final int b = ((color & 0x1f) << 3) | ((color & 0x1f) >> 2); + mColors[n] = Color.rgb(r, g, b); + } + } else if (format == ProtocolConstants.MT_FRAME_RGB888) { + for (int n = 0; n < pixel_num; n++) { + // Blob bitmap is in RGB565 format. + final int r = bb.getChar(); + final int g = bb.getChar(); + final int b = bb.getChar(); + mColors[n] = Color.rgb(r, g, b); + } + } else { + Log.w(TAG, "Invalid framebuffer format: " + format); + return; + } + mImageView.drawBitmap(x, y, w, h, mColors); + } + } + + /** + * Updates application's screen accordingly to the emulator screen. + * + * @param e_width Width of the emulator screen. + * @param e_height Height of the emulator screen. + */ + private void updateDisplay(int e_width, int e_height) { + if (e_width != mEmulatorWidth || e_height != mEmulatorHeight) { + mEmulatorWidth = e_width; + mEmulatorHeight = e_height; + + boolean rotateDisplay = false; + int w = mImageView.getWidth(); + int h = mImageView.getHeight(); + if (w > h != e_width > e_height) { + rotateDisplay = true; + int tmp = w; + w = h; + h = tmp; + } + + float dx = (float) w / (float) e_width; + float dy = (float) h / (float) e_height; + mImageView.setDxDy(dx, dy, rotateDisplay); + if (DEBUG) Log.d(TAG, "Dispay updated: " + e_width + " x " + e_height + + " -> " + w + " x " + h + " ratio: " + + dx + " x " + dy); + } + } + + // ---------- + + 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); + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java index 001398b..61c3081 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java @@ -1,338 +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) {}
- }
-}
+/* + * 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) {} + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/MultiTouchChannel.java b/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/MultiTouchChannel.java index 522a06e..ad00e92 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/MultiTouchChannel.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/MultiTouchChannel.java @@ -1,173 +1,173 @@ -/*
- * 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.handlers;
-
-import android.graphics.Point;
-import android.os.Message;
-import android.util.Log;
-
-import com.android.tools.sdkcontroller.lib.Channel;
-import com.android.tools.sdkcontroller.lib.ProtocolConstants;
-import com.android.tools.sdkcontroller.service.ControllerService;
-
-import java.nio.ByteBuffer;
-
-/**
- * Implements multi-touch emulation.
- */
-public class MultiTouchChannel extends Channel {
-
- @SuppressWarnings("hiding")
- private static final String TAG = MultiTouchChannel.class.getSimpleName();
- /**
- * A new frame buffer has been received from the emulator.
- * Parameter {@code obj} is a {@code byte[] array} containing the screen data.
- */
- public static final int EVENT_FRAME_BUFFER = 1;
- /**
- * A multi-touch "start" command has been received from the emulator.
- * Parameter {@code obj} is the string parameter from the start command.
- */
- public static final int EVENT_MT_START = 2;
- /**
- * A multi-touch "stop" command has been received from the emulator. There
- * is no {@code obj} parameter associated.
- */
- public static final int EVENT_MT_STOP = 3;
-
- private static final Point mViewSize = new Point(0, 0);
-
- /**
- * Constructs MultiTouchChannel instance.
- */
- public MultiTouchChannel(ControllerService service) {
- super(service, Channel.MULTITOUCH_CHANNEL);
- }
-
- /**
- * Sets size of the display view for emulated screen updates.
- *
- * @param width View width in pixels.
- * @param height View height in pixels.
- */
- public void setViewSize(int width, int height) {
- mViewSize.set(width, height);
- }
-
- /*
- * Channel abstract implementation.
- */
-
- /**
- * This method is invoked when this channel is fully connected with its
- * counterpart in the emulator.
- */
- @Override
- public void onEmulatorConnected() {
- if (hasUiHandler()) {
- enable();
- notifyUiHandlers(EVENT_MT_START);
- }
- }
-
- /**
- * This method is invoked when this channel loses connection with its
- * counterpart in the emulator.
- */
- @Override
- public void onEmulatorDisconnected() {
- if (hasUiHandler()) {
- disable();
- notifyUiHandlers(EVENT_MT_STOP);
- }
- }
-
- /**
- * A message has been received from the emulator.
- *
- * @param msg_type Message type.
- * @param msg_data Packet received from the emulator.
- */
- @Override
- public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) {
- switch (msg_type) {
- case ProtocolConstants.MT_FB_UPDATE:
- Message msg = Message.obtain();
- msg.what = EVENT_FRAME_BUFFER;
- msg.obj = msg_data;
- postMessage(ProtocolConstants.MT_FB_ACK, (byte[]) null);
- notifyUiHandlers(msg);
- break;
-
- default:
- Log.e(TAG, "Unknown message type " + msg_type);
- }
- }
-
- /**
- * A query has been received from the emulator.
- *
- * @param query_id Identifies the query. This ID must be used when replying
- * to the query.
- * @param query_type Query type.
- * @param query_data Query data.
- */
- @Override
- public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) {
- Loge("Unexpected query " + query_type + " in multi-touch");
- sendQueryResponse(query_id, (byte[]) null);
- }
-
- /**
- * Registers a new UI handler.
- *
- * @param uiHandler A non-null UI handler to register. Ignored if the UI
- * handler is null or already registered.
- */
- @Override
- public void addUiHandler(android.os.Handler uiHandler) {
- final boolean first_handler = !hasUiHandler();
- super.addUiHandler(uiHandler);
- if (first_handler && isConnected()) {
- enable();
- notifyUiHandlers(EVENT_MT_START);
- }
- }
-
- /**
- * Unregisters an UI handler.
- *
- * @param uiHandler A non-null UI listener to unregister. Ignored if the
- * listener is null or already registered.
- */
- @Override
- public void removeUiHandler(android.os.Handler uiHandler) {
- super.removeUiHandler(uiHandler);
- if (isConnected() && !hasUiHandler()) {
- disable();
- }
- }
-
- /***************************************************************************
- * Logging wrappers
- **************************************************************************/
-
- private void Loge(String log) {
- mService.addError(log);
- Log.e(TAG, log);
- }
-}
+/* + * 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.handlers; + +import android.graphics.Point; +import android.os.Message; +import android.util.Log; + +import com.android.tools.sdkcontroller.lib.Channel; +import com.android.tools.sdkcontroller.lib.ProtocolConstants; +import com.android.tools.sdkcontroller.service.ControllerService; + +import java.nio.ByteBuffer; + +/** + * Implements multi-touch emulation. + */ +public class MultiTouchChannel extends Channel { + + @SuppressWarnings("hiding") + private static final String TAG = MultiTouchChannel.class.getSimpleName(); + /** + * A new frame buffer has been received from the emulator. + * Parameter {@code obj} is a {@code byte[] array} containing the screen data. + */ + public static final int EVENT_FRAME_BUFFER = 1; + /** + * A multi-touch "start" command has been received from the emulator. + * Parameter {@code obj} is the string parameter from the start command. + */ + public static final int EVENT_MT_START = 2; + /** + * A multi-touch "stop" command has been received from the emulator. There + * is no {@code obj} parameter associated. + */ + public static final int EVENT_MT_STOP = 3; + + private static final Point mViewSize = new Point(0, 0); + + /** + * Constructs MultiTouchChannel instance. + */ + public MultiTouchChannel(ControllerService service) { + super(service, Channel.MULTITOUCH_CHANNEL); + } + + /** + * Sets size of the display view for emulated screen updates. + * + * @param width View width in pixels. + * @param height View height in pixels. + */ + public void setViewSize(int width, int height) { + mViewSize.set(width, height); + } + + /* + * Channel abstract implementation. + */ + + /** + * This method is invoked when this channel is fully connected with its + * counterpart in the emulator. + */ + @Override + public void onEmulatorConnected() { + if (hasUiHandler()) { + enable(); + notifyUiHandlers(EVENT_MT_START); + } + } + + /** + * This method is invoked when this channel loses connection with its + * counterpart in the emulator. + */ + @Override + public void onEmulatorDisconnected() { + if (hasUiHandler()) { + disable(); + notifyUiHandlers(EVENT_MT_STOP); + } + } + + /** + * A message has been received from the emulator. + * + * @param msg_type Message type. + * @param msg_data Packet received from the emulator. + */ + @Override + public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) { + switch (msg_type) { + case ProtocolConstants.MT_FB_UPDATE: + Message msg = Message.obtain(); + msg.what = EVENT_FRAME_BUFFER; + msg.obj = msg_data; + postMessage(ProtocolConstants.MT_FB_ACK, (byte[]) null); + notifyUiHandlers(msg); + break; + + default: + Log.e(TAG, "Unknown message type " + msg_type); + } + } + + /** + * A query has been received from the emulator. + * + * @param query_id Identifies the query. This ID must be used when replying + * to the query. + * @param query_type Query type. + * @param query_data Query data. + */ + @Override + public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) { + Loge("Unexpected query " + query_type + " in multi-touch"); + sendQueryResponse(query_id, (byte[]) null); + } + + /** + * Registers a new UI handler. + * + * @param uiHandler A non-null UI handler to register. Ignored if the UI + * handler is null or already registered. + */ + @Override + public void addUiHandler(android.os.Handler uiHandler) { + final boolean first_handler = !hasUiHandler(); + super.addUiHandler(uiHandler); + if (first_handler && isConnected()) { + enable(); + notifyUiHandlers(EVENT_MT_START); + } + } + + /** + * Unregisters an UI handler. + * + * @param uiHandler A non-null UI listener to unregister. Ignored if the + * listener is null or already registered. + */ + @Override + public void removeUiHandler(android.os.Handler uiHandler) { + super.removeUiHandler(uiHandler); + if (isConnected() && !hasUiHandler()) { + disable(); + } + } + + /*************************************************************************** + * Logging wrappers + **************************************************************************/ + + private void Loge(String log) { + mService.addError(log); + Log.e(TAG, log); + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/SensorChannel.java b/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/SensorChannel.java index d1ab836..ffc2fd0 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/SensorChannel.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/SensorChannel.java @@ -1,675 +1,675 @@ -/*
- * 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.handlers;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Message;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.tools.sdkcontroller.lib.Channel;
-import com.android.tools.sdkcontroller.lib.ProtocolConstants;
-import com.android.tools.sdkcontroller.service.ControllerService;
-
-/**
- * Implements sensors emulation.
- */
-public class SensorChannel extends Channel {
-
- @SuppressWarnings("hiding")
- private static String TAG = SensorChannel.class.getSimpleName();
- @SuppressWarnings("hiding")
- private static boolean DEBUG = false;
- /**
- * The target update time per sensor. Ignored if 0 or negative.
- * Sensor updates that arrive faster than this delay are ignored.
- * Ideally the emulator can be updated at up to 50 fps, however
- * for average power devices something like 20 fps is more
- * reasonable.
- * Default value should match res/values/strings.xml > sensors_default_sample_rate.
- */
- private long mUpdateTargetMs = 1000/20; // 20 fps in milliseconds
- /** Accumulates average update frequency. */
- private long mGlobalAvgUpdateMs = 0;
-
- /** Array containing monitored sensors. */
- private final List<MonitoredSensor> mSensors = new ArrayList<MonitoredSensor>();
- /** Sensor manager. */
- private SensorManager mSenMan;
-
- /*
- * Messages exchanged with the UI.
- */
-
- /**
- * Sensor "enabled by emulator" state has changed. Parameter {@code obj} is
- * the {@link MonitoredSensor}.
- */
- public static final int SENSOR_STATE_CHANGED = 1;
- /**
- * Sensor display value has changed. Parameter {@code obj} is the
- * {@link MonitoredSensor}.
- */
- public static final int SENSOR_DISPLAY_MODIFIED = 2;
-
- /**
- * Constructs SensorChannel instance.
- *
- * @param service Service context.
- */
- public SensorChannel(ControllerService service) {
- super(service, Channel.SENSOR_CHANNEL);
- mSenMan = (SensorManager) service.getSystemService(Context.SENSOR_SERVICE);
- // Iterate through the available sensors, adding them to the array.
- List<Sensor> sensors = mSenMan.getSensorList(Sensor.TYPE_ALL);
- int cur_index = 0;
- for (int n = 0; n < sensors.size(); n++) {
- Sensor avail_sensor = sensors.get(n);
-
- // There can be multiple sensors of the same type. We need only one.
- if (!isSensorTypeAlreadyMonitored(avail_sensor.getType())) {
- // The first sensor we've got for the given type is not
- // necessarily the right one. So, use the default sensor
- // for the given type.
- Sensor def_sens = mSenMan.getDefaultSensor(avail_sensor.getType());
- MonitoredSensor to_add = new MonitoredSensor(def_sens);
- cur_index++;
- mSensors.add(to_add);
- if (DEBUG)
- Log.d(TAG, String.format(
- "Monitoring sensor #%02d: Name = '%s', Type = 0x%x",
- cur_index, def_sens.getName(), def_sens.getType()));
- }
- }
- }
-
- /**
- * Returns the list of sensors found on the device.
- * The list is computed once by {@link #SensorChannel(ControllerService)}.
- *
- * @return A non-null possibly-empty list of sensors.
- */
- public List<MonitoredSensor> getSensors() {
- return mSensors;
- }
-
- /**
- * Set the target update delay throttling per-sensor, in milliseconds.
- * <p/>
- * For example setting it to 1000/50 means that updates for a <em>given</em> sensor
- * faster than 50 fps is discarded.
- *
- * @param updateTargetMs 0 to disable throttling, otherwise a > 0 millisecond minimum
- * between sensor updates.
- */
- public void setUpdateTargetMs(long updateTargetMs) {
- mUpdateTargetMs = updateTargetMs;
- }
-
- /**
- * Returns the actual average time in milliseconds between same-sensor updates.
- *
- * @return The actual average time in milliseconds between same-sensor updates or 0.
- */
- public long getActualUpdateMs() {
- return mGlobalAvgUpdateMs;
- }
-
- /*
- * Channel abstract implementation.
- */
-
- /**
- * This method is invoked when this channel is fully connected with its
- * counterpart in the emulator.
- */
- @Override
- public void onEmulatorConnected() {
- // Emulation is now possible. Note though that it will start only after
- // emulator tells us so with SENSORS_START command.
- enable();
- }
-
- /**
- * This method is invoked when this channel loses connection with its
- * counterpart in the emulator.
- */
- @Override
- public void onEmulatorDisconnected() {
- // Stop sensor event callbacks.
- stopSensors();
- }
-
- /**
- * A query has been received from the emulator.
- *
- * @param query_id Identifies the query. This ID should be used when
- * replying to the query.
- * @param query_type Query type.
- * @param query_data Query data.
- */
- @Override
- public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) {
- switch (query_type) {
- case ProtocolConstants.SENSORS_QUERY_LIST:
- // Preallocate large response buffer.
- ByteBuffer resp = ByteBuffer.allocate(1024);
- resp.order(getEndian());
- // Iterate through the list of monitored sensors, dumping them
- // into the response buffer.
- for (MonitoredSensor sensor : mSensors) {
- // Entry for each sensor must contain:
- // - an integer for its ID
- // - a zero-terminated emulator-friendly name.
- final byte[] name = sensor.getEmulatorFriendlyName().getBytes();
- final int required_size = 4 + name.length + 1;
- resp = ExpandIf(resp, required_size);
- resp.putInt(sensor.getType());
- resp.put(name);
- resp.put((byte) 0);
- }
- // Terminating entry contains single -1 integer.
- resp = ExpandIf(resp, 4);
- resp.putInt(-1);
- sendQueryResponse(query_id, resp);
- return;
-
- default:
- Loge("Unknown query " + query_type);
- return;
- }
- }
-
- /**
- * A message has been received from the emulator.
- *
- * @param msg_type Message type.
- * @param msg_data Packet received from the emulator.
- */
- @Override
- public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) {
- switch (msg_type) {
- case ProtocolConstants.SENSORS_START:
- Log.v(TAG, "Starting sensors emulation.");
- startSensors();
- break;
- case ProtocolConstants.SENSORS_STOP:
- Log.v(TAG, "Stopping sensors emulation.");
- stopSensors();
- break;
- case ProtocolConstants.SENSORS_ENABLE:
- String enable_name = new String(msg_data.array());
- Log.v(TAG, "Enabling sensor: " + enable_name);
- onEnableSensor(enable_name);
- break;
- case ProtocolConstants.SENSORS_DISABLE:
- String disable_name = new String(msg_data.array());
- Log.v(TAG, "Disabling sensor: " + disable_name);
- onDisableSensor(disable_name);
- break;
- default:
- Loge("Unknown message type " + msg_type);
- break;
- }
- }
-
- /**
- * Handles 'enable' message.
- *
- * @param name Emulator-friendly name of a sensor to enable, or "all" to
- * enable all sensors.
- */
- private void onEnableSensor(String name) {
- if (name.contentEquals("all")) {
- // Enable all sensors.
- for (MonitoredSensor sensor : mSensors) {
- sensor.enableSensor();
- }
- } else {
- // Lookup sensor by emulator-friendly name.
- final MonitoredSensor sensor = getSensorByEFN(name);
- if (sensor != null) {
- sensor.enableSensor();
- }
- }
- }
-
- /**
- * Handles 'disable' message.
- *
- * @param name Emulator-friendly name of a sensor to disable, or "all" to
- * disable all sensors.
- */
- private void onDisableSensor(String name) {
- if (name.contentEquals("all")) {
- // Disable all sensors.
- for (MonitoredSensor sensor : mSensors) {
- sensor.disableSensor();
- }
- } else {
- // Lookup sensor by emulator-friendly name.
- MonitoredSensor sensor = getSensorByEFN(name);
- if (sensor != null) {
- sensor.disableSensor();
- }
- }
- }
-
- /**
- * Start listening to all monitored sensors.
- */
- private void startSensors() {
- for (MonitoredSensor sensor : mSensors) {
- sensor.startListening();
- }
- }
-
- /**
- * Stop listening to all monitored sensors.
- */
- private void stopSensors() {
- for (MonitoredSensor sensor : mSensors) {
- sensor.stopListening();
- }
- }
-
- /***************************************************************************
- * Internals
- **************************************************************************/
-
- /**
- * Checks if a sensor for the given type is already monitored.
- *
- * @param type Sensor type (one of the Sensor.TYPE_XXX constants)
- * @return true if a sensor for the given type is already monitored, or
- * false if the sensor is not monitored.
- */
- private boolean isSensorTypeAlreadyMonitored(int type) {
- for (MonitoredSensor sensor : mSensors) {
- if (sensor.getType() == type) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Looks up a monitored sensor by its emulator-friendly name.
- *
- * @param name Emulator-friendly name to look up the monitored sensor for.
- * @return Monitored sensor for the fiven name, or null if sensor was not
- * found.
- */
- private MonitoredSensor getSensorByEFN(String name) {
- for (MonitoredSensor sensor : mSensors) {
- if (sensor.mEmulatorFriendlyName.contentEquals(name)) {
- return sensor;
- }
- }
- return null;
- }
-
- /**
- * Encapsulates a sensor that is being monitored. To monitor sensor changes
- * each monitored sensor registers with sensor manager as a sensor listener.
- * To control sensor monitoring from the UI, each monitored sensor has two
- * UI controls associated with it: - A check box (named after sensor) that
- * can be used to enable, or disable listening to the sensor changes. - A
- * text view where current sensor value is displayed.
- */
- public class MonitoredSensor {
- /** Sensor to monitor. */
- private final Sensor mSensor;
- /** The sensor name to display in the UI. */
- private String mUiName = "";
- /** Text view displaying the value of the sensor. */
- private String mValue = null;
- /** Emulator-friendly name for the sensor. */
- private String mEmulatorFriendlyName;
- /** Formats string to show in the TextView. */
- private String mTextFmt;
- /** Sensor values. */
- private float[] mValues = new float[3];
- /**
- * Enabled state. This state is controlled by the emulator, that
- * maintains its own list of sensors. So, if a sensor is missing, or is
- * disabled in the emulator, it should be disabled in this application.
- */
- private boolean mEnabledByEmulator = false;
- /** User-controlled enabled state. */
- private boolean mEnabledByUser = true;
- /** Sensor event listener for this sensor. */
- private final OurSensorEventListener mListener = new OurSensorEventListener();
-
- /**
- * Constructs MonitoredSensor instance, and register the listeners.
- *
- * @param sensor Sensor to monitor.
- */
- MonitoredSensor(Sensor sensor) {
- mSensor = sensor;
- mEnabledByUser = true;
-
- // Set appropriate sensor name depending on the type. Unfortunately,
- // we can't really use sensor.getName() here, since the value it
- // returns (although resembles the purpose) is a bit vaguer than it
- // should be. Also choose an appropriate format for the strings that
- // display sensor's value.
- switch (sensor.getType()) {
- case Sensor.TYPE_ACCELEROMETER:
- mUiName = "Accelerometer";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "acceleration";
- break;
- case 9: // Sensor.TYPE_GRAVITY is missing in API 7
- mUiName = "Gravity";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "gravity";
- break;
- case Sensor.TYPE_GYROSCOPE:
- mUiName = "Gyroscope";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "gyroscope";
- break;
- case Sensor.TYPE_LIGHT:
- mUiName = "Light";
- mTextFmt = "%.0f";
- mEmulatorFriendlyName = "light";
- break;
- case 10: // Sensor.TYPE_LINEAR_ACCELERATION is missing in API 7
- mUiName = "Linear acceleration";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "linear-acceleration";
- break;
- case Sensor.TYPE_MAGNETIC_FIELD:
- mUiName = "Magnetic field";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "magnetic-field";
- break;
- case Sensor.TYPE_ORIENTATION:
- mUiName = "Orientation";
- mTextFmt = "%+03.0f %+03.0f %+03.0f";
- mEmulatorFriendlyName = "orientation";
- break;
- case Sensor.TYPE_PRESSURE:
- mUiName = "Pressure";
- mTextFmt = "%.0f";
- mEmulatorFriendlyName = "pressure";
- break;
- case Sensor.TYPE_PROXIMITY:
- mUiName = "Proximity";
- mTextFmt = "%.0f";
- mEmulatorFriendlyName = "proximity";
- break;
- case 11: // Sensor.TYPE_ROTATION_VECTOR is missing in API 7
- mUiName = "Rotation";
- mTextFmt = "%+.2f %+.2f %+.2f";
- mEmulatorFriendlyName = "rotation";
- break;
- case Sensor.TYPE_TEMPERATURE:
- mUiName = "Temperature";
- mTextFmt = "%.0f";
- mEmulatorFriendlyName = "temperature";
- break;
- default:
- mUiName = "<Unknown>";
- mTextFmt = "N/A";
- mEmulatorFriendlyName = "unknown";
- if (DEBUG) Loge("Unknown sensor type " + mSensor.getType() +
- " for sensor " + mSensor.getName());
- break;
- }
- }
-
- /**
- * Get name for this sensor to display.
- *
- * @return Name for this sensor to display.
- */
- public String getUiName() {
- return mUiName;
- }
-
- /**
- * Gets current sensor value to display.
- *
- * @return Current sensor value to display.
- */
- public String getValue() {
- if (mValue == null) {
- float[] values = mValues;
- mValue = String.format(mTextFmt, values[0], values[1], values[2]);
- }
- return mValue == null ? "??" : mValue;
- }
-
- /**
- * Checks if monitoring of this this sensor has been enabled by
- * emulator.
- *
- * @return true if monitoring of this this sensor has been enabled by
- * emulator, or false if emulator didn't enable this sensor.
- */
- public boolean isEnabledByEmulator() {
- return mEnabledByEmulator;
- }
-
- /**
- * Checks if monitoring of this this sensor has been enabled by user.
- *
- * @return true if monitoring of this this sensor has been enabled by
- * user, or false if user didn't enable this sensor.
- */
- public boolean isEnabledByUser() {
- return mEnabledByUser;
- }
-
- /**
- * 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.
- */
- public void onCheckedChanged(boolean isChecked) {
- mEnabledByUser = isChecked;
- if (isChecked) {
- startListening();
- } else {
- stopListening();
- }
- }
-
- /**
- * Gets sensor type.
- *
- * @return Sensor type as one of the Sensor.TYPE_XXX constants.
- */
- private int getType() {
- return mSensor.getType();
- }
-
- /**
- * Gets sensor's emulator-friendly name.
- *
- * @return Sensor's emulator-friendly name.
- */
- private String getEmulatorFriendlyName() {
- return mEmulatorFriendlyName;
- }
-
- /**
- * Starts monitoring the sensor.
- * NOTE: This method is called from outside of the UI thread.
- */
- private void startListening() {
- if (mEnabledByEmulator && mEnabledByUser) {
- if (DEBUG) Log.d(TAG, "+++ Sensor " + getEmulatorFriendlyName() + " is started.");
- mSenMan.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_FASTEST);
- }
- }
-
- /**
- * Stops monitoring the sensor.
- * NOTE: This method is called from outside of the UI thread.
- */
- private void stopListening() {
- if (DEBUG) Log.d(TAG, "--- Sensor " + getEmulatorFriendlyName() + " is stopped.");
- mSenMan.unregisterListener(mListener);
- }
-
- /**
- * Enables sensor events.
- * NOTE: This method is called from outside of the UI thread.
- */
- private void enableSensor() {
- if (DEBUG) Log.d(TAG, ">>> Sensor " + getEmulatorFriendlyName() + " is enabled.");
- mEnabledByEmulator = true;
- mValue = null;
-
- Message msg = Message.obtain();
- msg.what = SENSOR_STATE_CHANGED;
- msg.obj = MonitoredSensor.this;
- notifyUiHandlers(msg);
- }
-
- /**
- * Disables sensor events.
- * NOTE: This method is called from outside of the UI thread.
- */
- private void disableSensor() {
- if (DEBUG) Log.w(TAG, "<<< Sensor " + getEmulatorFriendlyName() + " is disabled.");
- mEnabledByEmulator = false;
- mValue = "Disabled by emulator";
-
- Message msg = Message.obtain();
- msg.what = SENSOR_STATE_CHANGED;
- msg.obj = MonitoredSensor.this;
- notifyUiHandlers(msg);
- }
-
- private class OurSensorEventListener implements SensorEventListener {
- /** Last update's time-stamp in local thread millisecond time. */
- private long mLastUpdateTS = 0;
- /** Last display update time-stamp. */
- private long mLastDisplayTS = 0;
- /** Preallocated buffer for change notification message. */
- private final ByteBuffer mChangeMsg = ByteBuffer.allocate(64);
-
- /**
- * Handles "sensor changed" event.
- * This is an implementation of the SensorEventListener interface.
- */
- @Override
- public void onSensorChanged(SensorEvent event) {
- long now = SystemClock.elapsedRealtime();
-
- long deltaMs = 0;
- if (mLastUpdateTS != 0) {
- deltaMs = now - mLastUpdateTS;
- if (mUpdateTargetMs > 0 && deltaMs < mUpdateTargetMs) {
- // New sample is arriving too fast. Discard it.
- return;
- }
- }
-
- // Format and post message for the emulator.
- float[] values = event.values;
- final int len = values.length;
-
- mChangeMsg.order(getEndian());
- mChangeMsg.position(0);
- mChangeMsg.putInt(getType());
- mChangeMsg.putFloat(values[0]);
- if (len > 1) {
- mChangeMsg.putFloat(values[1]);
- if (len > 2) {
- mChangeMsg.putFloat(values[2]);
- }
- }
- postMessage(ProtocolConstants.SENSORS_SENSOR_EVENT, mChangeMsg);
-
- // Computes average update time for this sensor and average globally.
- if (mLastUpdateTS != 0) {
- if (mGlobalAvgUpdateMs != 0) {
- mGlobalAvgUpdateMs = (mGlobalAvgUpdateMs + deltaMs) / 2;
- } else {
- mGlobalAvgUpdateMs = deltaMs;
- }
- }
- mLastUpdateTS = now;
-
- // Update the UI for the sensor, with a static throttling of 10 fps max.
- if (hasUiHandler()) {
- if (mLastDisplayTS != 0) {
- long uiDeltaMs = now - mLastDisplayTS;
- if (uiDeltaMs < 1000 / 4 /* 4fps in ms */) {
- // Skip this UI update
- return;
- }
- }
- mLastDisplayTS = now;
-
- mValues[0] = values[0];
- if (len > 1) {
- mValues[1] = values[1];
- if (len > 2) {
- mValues[2] = values[2];
- }
- }
- mValue = null;
-
- Message msg = Message.obtain();
- msg.what = SENSOR_DISPLAY_MODIFIED;
- msg.obj = MonitoredSensor.this;
- notifyUiHandlers(msg);
- }
-
- if (DEBUG) {
- long now2 = SystemClock.elapsedRealtime();
- long processingTimeMs = now2 - now;
- Log.d(TAG, String.format("glob %d - local %d > target %d - processing %d -- %s",
- mGlobalAvgUpdateMs, deltaMs, mUpdateTargetMs, processingTimeMs,
- mSensor.getName()));
- }
- }
-
- /**
- * Handles "sensor accuracy changed" event.
- * This is an implementation of the SensorEventListener interface.
- */
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
- }
- } // MonitoredSensor
-
- /***************************************************************************
- * Logging wrappers
- **************************************************************************/
-
- private void Loge(String log) {
- mService.addError(log);
- Log.e(TAG, log);
- }
-}
+/* + * 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.handlers; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Message; +import android.os.SystemClock; +import android.util.Log; + +import com.android.tools.sdkcontroller.lib.Channel; +import com.android.tools.sdkcontroller.lib.ProtocolConstants; +import com.android.tools.sdkcontroller.service.ControllerService; + +/** + * Implements sensors emulation. + */ +public class SensorChannel extends Channel { + + @SuppressWarnings("hiding") + private static String TAG = SensorChannel.class.getSimpleName(); + @SuppressWarnings("hiding") + private static boolean DEBUG = false; + /** + * The target update time per sensor. Ignored if 0 or negative. + * Sensor updates that arrive faster than this delay are ignored. + * Ideally the emulator can be updated at up to 50 fps, however + * for average power devices something like 20 fps is more + * reasonable. + * Default value should match res/values/strings.xml > sensors_default_sample_rate. + */ + private long mUpdateTargetMs = 1000/20; // 20 fps in milliseconds + /** Accumulates average update frequency. */ + private long mGlobalAvgUpdateMs = 0; + + /** Array containing monitored sensors. */ + private final List<MonitoredSensor> mSensors = new ArrayList<MonitoredSensor>(); + /** Sensor manager. */ + private SensorManager mSenMan; + + /* + * Messages exchanged with the UI. + */ + + /** + * Sensor "enabled by emulator" state has changed. Parameter {@code obj} is + * the {@link MonitoredSensor}. + */ + public static final int SENSOR_STATE_CHANGED = 1; + /** + * Sensor display value has changed. Parameter {@code obj} is the + * {@link MonitoredSensor}. + */ + public static final int SENSOR_DISPLAY_MODIFIED = 2; + + /** + * Constructs SensorChannel instance. + * + * @param service Service context. + */ + public SensorChannel(ControllerService service) { + super(service, Channel.SENSOR_CHANNEL); + mSenMan = (SensorManager) service.getSystemService(Context.SENSOR_SERVICE); + // Iterate through the available sensors, adding them to the array. + List<Sensor> sensors = mSenMan.getSensorList(Sensor.TYPE_ALL); + int cur_index = 0; + for (int n = 0; n < sensors.size(); n++) { + Sensor avail_sensor = sensors.get(n); + + // There can be multiple sensors of the same type. We need only one. + if (!isSensorTypeAlreadyMonitored(avail_sensor.getType())) { + // The first sensor we've got for the given type is not + // necessarily the right one. So, use the default sensor + // for the given type. + Sensor def_sens = mSenMan.getDefaultSensor(avail_sensor.getType()); + MonitoredSensor to_add = new MonitoredSensor(def_sens); + cur_index++; + mSensors.add(to_add); + if (DEBUG) + Log.d(TAG, String.format( + "Monitoring sensor #%02d: Name = '%s', Type = 0x%x", + cur_index, def_sens.getName(), def_sens.getType())); + } + } + } + + /** + * Returns the list of sensors found on the device. + * The list is computed once by {@link #SensorChannel(ControllerService)}. + * + * @return A non-null possibly-empty list of sensors. + */ + public List<MonitoredSensor> getSensors() { + return mSensors; + } + + /** + * Set the target update delay throttling per-sensor, in milliseconds. + * <p/> + * For example setting it to 1000/50 means that updates for a <em>given</em> sensor + * faster than 50 fps is discarded. + * + * @param updateTargetMs 0 to disable throttling, otherwise a > 0 millisecond minimum + * between sensor updates. + */ + public void setUpdateTargetMs(long updateTargetMs) { + mUpdateTargetMs = updateTargetMs; + } + + /** + * Returns the actual average time in milliseconds between same-sensor updates. + * + * @return The actual average time in milliseconds between same-sensor updates or 0. + */ + public long getActualUpdateMs() { + return mGlobalAvgUpdateMs; + } + + /* + * Channel abstract implementation. + */ + + /** + * This method is invoked when this channel is fully connected with its + * counterpart in the emulator. + */ + @Override + public void onEmulatorConnected() { + // Emulation is now possible. Note though that it will start only after + // emulator tells us so with SENSORS_START command. + enable(); + } + + /** + * This method is invoked when this channel loses connection with its + * counterpart in the emulator. + */ + @Override + public void onEmulatorDisconnected() { + // Stop sensor event callbacks. + stopSensors(); + } + + /** + * A query has been received from the emulator. + * + * @param query_id Identifies the query. This ID should be used when + * replying to the query. + * @param query_type Query type. + * @param query_data Query data. + */ + @Override + public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) { + switch (query_type) { + case ProtocolConstants.SENSORS_QUERY_LIST: + // Preallocate large response buffer. + ByteBuffer resp = ByteBuffer.allocate(1024); + resp.order(getEndian()); + // Iterate through the list of monitored sensors, dumping them + // into the response buffer. + for (MonitoredSensor sensor : mSensors) { + // Entry for each sensor must contain: + // - an integer for its ID + // - a zero-terminated emulator-friendly name. + final byte[] name = sensor.getEmulatorFriendlyName().getBytes(); + final int required_size = 4 + name.length + 1; + resp = ExpandIf(resp, required_size); + resp.putInt(sensor.getType()); + resp.put(name); + resp.put((byte) 0); + } + // Terminating entry contains single -1 integer. + resp = ExpandIf(resp, 4); + resp.putInt(-1); + sendQueryResponse(query_id, resp); + return; + + default: + Loge("Unknown query " + query_type); + return; + } + } + + /** + * A message has been received from the emulator. + * + * @param msg_type Message type. + * @param msg_data Packet received from the emulator. + */ + @Override + public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) { + switch (msg_type) { + case ProtocolConstants.SENSORS_START: + Log.v(TAG, "Starting sensors emulation."); + startSensors(); + break; + case ProtocolConstants.SENSORS_STOP: + Log.v(TAG, "Stopping sensors emulation."); + stopSensors(); + break; + case ProtocolConstants.SENSORS_ENABLE: + String enable_name = new String(msg_data.array()); + Log.v(TAG, "Enabling sensor: " + enable_name); + onEnableSensor(enable_name); + break; + case ProtocolConstants.SENSORS_DISABLE: + String disable_name = new String(msg_data.array()); + Log.v(TAG, "Disabling sensor: " + disable_name); + onDisableSensor(disable_name); + break; + default: + Loge("Unknown message type " + msg_type); + break; + } + } + + /** + * Handles 'enable' message. + * + * @param name Emulator-friendly name of a sensor to enable, or "all" to + * enable all sensors. + */ + private void onEnableSensor(String name) { + if (name.contentEquals("all")) { + // Enable all sensors. + for (MonitoredSensor sensor : mSensors) { + sensor.enableSensor(); + } + } else { + // Lookup sensor by emulator-friendly name. + final MonitoredSensor sensor = getSensorByEFN(name); + if (sensor != null) { + sensor.enableSensor(); + } + } + } + + /** + * Handles 'disable' message. + * + * @param name Emulator-friendly name of a sensor to disable, or "all" to + * disable all sensors. + */ + private void onDisableSensor(String name) { + if (name.contentEquals("all")) { + // Disable all sensors. + for (MonitoredSensor sensor : mSensors) { + sensor.disableSensor(); + } + } else { + // Lookup sensor by emulator-friendly name. + MonitoredSensor sensor = getSensorByEFN(name); + if (sensor != null) { + sensor.disableSensor(); + } + } + } + + /** + * Start listening to all monitored sensors. + */ + private void startSensors() { + for (MonitoredSensor sensor : mSensors) { + sensor.startListening(); + } + } + + /** + * Stop listening to all monitored sensors. + */ + private void stopSensors() { + for (MonitoredSensor sensor : mSensors) { + sensor.stopListening(); + } + } + + /*************************************************************************** + * Internals + **************************************************************************/ + + /** + * Checks if a sensor for the given type is already monitored. + * + * @param type Sensor type (one of the Sensor.TYPE_XXX constants) + * @return true if a sensor for the given type is already monitored, or + * false if the sensor is not monitored. + */ + private boolean isSensorTypeAlreadyMonitored(int type) { + for (MonitoredSensor sensor : mSensors) { + if (sensor.getType() == type) { + return true; + } + } + return false; + } + + /** + * Looks up a monitored sensor by its emulator-friendly name. + * + * @param name Emulator-friendly name to look up the monitored sensor for. + * @return Monitored sensor for the fiven name, or null if sensor was not + * found. + */ + private MonitoredSensor getSensorByEFN(String name) { + for (MonitoredSensor sensor : mSensors) { + if (sensor.mEmulatorFriendlyName.contentEquals(name)) { + return sensor; + } + } + return null; + } + + /** + * Encapsulates a sensor that is being monitored. To monitor sensor changes + * each monitored sensor registers with sensor manager as a sensor listener. + * To control sensor monitoring from the UI, each monitored sensor has two + * UI controls associated with it: - A check box (named after sensor) that + * can be used to enable, or disable listening to the sensor changes. - A + * text view where current sensor value is displayed. + */ + public class MonitoredSensor { + /** Sensor to monitor. */ + private final Sensor mSensor; + /** The sensor name to display in the UI. */ + private String mUiName = ""; + /** Text view displaying the value of the sensor. */ + private String mValue = null; + /** Emulator-friendly name for the sensor. */ + private String mEmulatorFriendlyName; + /** Formats string to show in the TextView. */ + private String mTextFmt; + /** Sensor values. */ + private float[] mValues = new float[3]; + /** + * Enabled state. This state is controlled by the emulator, that + * maintains its own list of sensors. So, if a sensor is missing, or is + * disabled in the emulator, it should be disabled in this application. + */ + private boolean mEnabledByEmulator = false; + /** User-controlled enabled state. */ + private boolean mEnabledByUser = true; + /** Sensor event listener for this sensor. */ + private final OurSensorEventListener mListener = new OurSensorEventListener(); + + /** + * Constructs MonitoredSensor instance, and register the listeners. + * + * @param sensor Sensor to monitor. + */ + MonitoredSensor(Sensor sensor) { + mSensor = sensor; + mEnabledByUser = true; + + // Set appropriate sensor name depending on the type. Unfortunately, + // we can't really use sensor.getName() here, since the value it + // returns (although resembles the purpose) is a bit vaguer than it + // should be. Also choose an appropriate format for the strings that + // display sensor's value. + switch (sensor.getType()) { + case Sensor.TYPE_ACCELEROMETER: + mUiName = "Accelerometer"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "acceleration"; + break; + case 9: // Sensor.TYPE_GRAVITY is missing in API 7 + mUiName = "Gravity"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "gravity"; + break; + case Sensor.TYPE_GYROSCOPE: + mUiName = "Gyroscope"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "gyroscope"; + break; + case Sensor.TYPE_LIGHT: + mUiName = "Light"; + mTextFmt = "%.0f"; + mEmulatorFriendlyName = "light"; + break; + case 10: // Sensor.TYPE_LINEAR_ACCELERATION is missing in API 7 + mUiName = "Linear acceleration"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "linear-acceleration"; + break; + case Sensor.TYPE_MAGNETIC_FIELD: + mUiName = "Magnetic field"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "magnetic-field"; + break; + case Sensor.TYPE_ORIENTATION: + mUiName = "Orientation"; + mTextFmt = "%+03.0f %+03.0f %+03.0f"; + mEmulatorFriendlyName = "orientation"; + break; + case Sensor.TYPE_PRESSURE: + mUiName = "Pressure"; + mTextFmt = "%.0f"; + mEmulatorFriendlyName = "pressure"; + break; + case Sensor.TYPE_PROXIMITY: + mUiName = "Proximity"; + mTextFmt = "%.0f"; + mEmulatorFriendlyName = "proximity"; + break; + case 11: // Sensor.TYPE_ROTATION_VECTOR is missing in API 7 + mUiName = "Rotation"; + mTextFmt = "%+.2f %+.2f %+.2f"; + mEmulatorFriendlyName = "rotation"; + break; + case Sensor.TYPE_TEMPERATURE: + mUiName = "Temperature"; + mTextFmt = "%.0f"; + mEmulatorFriendlyName = "temperature"; + break; + default: + mUiName = "<Unknown>"; + mTextFmt = "N/A"; + mEmulatorFriendlyName = "unknown"; + if (DEBUG) Loge("Unknown sensor type " + mSensor.getType() + + " for sensor " + mSensor.getName()); + break; + } + } + + /** + * Get name for this sensor to display. + * + * @return Name for this sensor to display. + */ + public String getUiName() { + return mUiName; + } + + /** + * Gets current sensor value to display. + * + * @return Current sensor value to display. + */ + public String getValue() { + if (mValue == null) { + float[] values = mValues; + mValue = String.format(mTextFmt, values[0], values[1], values[2]); + } + return mValue == null ? "??" : mValue; + } + + /** + * Checks if monitoring of this this sensor has been enabled by + * emulator. + * + * @return true if monitoring of this this sensor has been enabled by + * emulator, or false if emulator didn't enable this sensor. + */ + public boolean isEnabledByEmulator() { + return mEnabledByEmulator; + } + + /** + * Checks if monitoring of this this sensor has been enabled by user. + * + * @return true if monitoring of this this sensor has been enabled by + * user, or false if user didn't enable this sensor. + */ + public boolean isEnabledByUser() { + return mEnabledByUser; + } + + /** + * 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. + */ + public void onCheckedChanged(boolean isChecked) { + mEnabledByUser = isChecked; + if (isChecked) { + startListening(); + } else { + stopListening(); + } + } + + /** + * Gets sensor type. + * + * @return Sensor type as one of the Sensor.TYPE_XXX constants. + */ + private int getType() { + return mSensor.getType(); + } + + /** + * Gets sensor's emulator-friendly name. + * + * @return Sensor's emulator-friendly name. + */ + private String getEmulatorFriendlyName() { + return mEmulatorFriendlyName; + } + + /** + * Starts monitoring the sensor. + * NOTE: This method is called from outside of the UI thread. + */ + private void startListening() { + if (mEnabledByEmulator && mEnabledByUser) { + if (DEBUG) Log.d(TAG, "+++ Sensor " + getEmulatorFriendlyName() + " is started."); + mSenMan.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_FASTEST); + } + } + + /** + * Stops monitoring the sensor. + * NOTE: This method is called from outside of the UI thread. + */ + private void stopListening() { + if (DEBUG) Log.d(TAG, "--- Sensor " + getEmulatorFriendlyName() + " is stopped."); + mSenMan.unregisterListener(mListener); + } + + /** + * Enables sensor events. + * NOTE: This method is called from outside of the UI thread. + */ + private void enableSensor() { + if (DEBUG) Log.d(TAG, ">>> Sensor " + getEmulatorFriendlyName() + " is enabled."); + mEnabledByEmulator = true; + mValue = null; + + Message msg = Message.obtain(); + msg.what = SENSOR_STATE_CHANGED; + msg.obj = MonitoredSensor.this; + notifyUiHandlers(msg); + } + + /** + * Disables sensor events. + * NOTE: This method is called from outside of the UI thread. + */ + private void disableSensor() { + if (DEBUG) Log.w(TAG, "<<< Sensor " + getEmulatorFriendlyName() + " is disabled."); + mEnabledByEmulator = false; + mValue = "Disabled by emulator"; + + Message msg = Message.obtain(); + msg.what = SENSOR_STATE_CHANGED; + msg.obj = MonitoredSensor.this; + notifyUiHandlers(msg); + } + + private class OurSensorEventListener implements SensorEventListener { + /** Last update's time-stamp in local thread millisecond time. */ + private long mLastUpdateTS = 0; + /** Last display update time-stamp. */ + private long mLastDisplayTS = 0; + /** Preallocated buffer for change notification message. */ + private final ByteBuffer mChangeMsg = ByteBuffer.allocate(64); + + /** + * Handles "sensor changed" event. + * This is an implementation of the SensorEventListener interface. + */ + @Override + public void onSensorChanged(SensorEvent event) { + long now = SystemClock.elapsedRealtime(); + + long deltaMs = 0; + if (mLastUpdateTS != 0) { + deltaMs = now - mLastUpdateTS; + if (mUpdateTargetMs > 0 && deltaMs < mUpdateTargetMs) { + // New sample is arriving too fast. Discard it. + return; + } + } + + // Format and post message for the emulator. + float[] values = event.values; + final int len = values.length; + + mChangeMsg.order(getEndian()); + mChangeMsg.position(0); + mChangeMsg.putInt(getType()); + mChangeMsg.putFloat(values[0]); + if (len > 1) { + mChangeMsg.putFloat(values[1]); + if (len > 2) { + mChangeMsg.putFloat(values[2]); + } + } + postMessage(ProtocolConstants.SENSORS_SENSOR_EVENT, mChangeMsg); + + // Computes average update time for this sensor and average globally. + if (mLastUpdateTS != 0) { + if (mGlobalAvgUpdateMs != 0) { + mGlobalAvgUpdateMs = (mGlobalAvgUpdateMs + deltaMs) / 2; + } else { + mGlobalAvgUpdateMs = deltaMs; + } + } + mLastUpdateTS = now; + + // Update the UI for the sensor, with a static throttling of 10 fps max. + if (hasUiHandler()) { + if (mLastDisplayTS != 0) { + long uiDeltaMs = now - mLastDisplayTS; + if (uiDeltaMs < 1000 / 4 /* 4fps in ms */) { + // Skip this UI update + return; + } + } + mLastDisplayTS = now; + + mValues[0] = values[0]; + if (len > 1) { + mValues[1] = values[1]; + if (len > 2) { + mValues[2] = values[2]; + } + } + mValue = null; + + Message msg = Message.obtain(); + msg.what = SENSOR_DISPLAY_MODIFIED; + msg.obj = MonitoredSensor.this; + notifyUiHandlers(msg); + } + + if (DEBUG) { + long now2 = SystemClock.elapsedRealtime(); + long processingTimeMs = now2 - now; + Log.d(TAG, String.format("glob %d - local %d > target %d - processing %d -- %s", + mGlobalAvgUpdateMs, deltaMs, mUpdateTargetMs, processingTimeMs, + mSensor.getName())); + } + } + + /** + * Handles "sensor accuracy changed" event. + * This is an implementation of the SensorEventListener interface. + */ + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + } + } // MonitoredSensor + + /*************************************************************************** + * Logging wrappers + **************************************************************************/ + + private void Loge(String log) { + mService.addError(log); + Log.e(TAG, log); + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/service/ControllerService.java b/apps/SdkController/src/com/android/tools/sdkcontroller/service/ControllerService.java index 705bd07..9a3408b 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/service/ControllerService.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/service/ControllerService.java @@ -1,319 +1,319 @@ -/*
- * 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.service;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.tools.sdkcontroller.R;
-import com.android.tools.sdkcontroller.activities.MainActivity;
-import com.android.tools.sdkcontroller.handlers.MultiTouchChannel;
-import com.android.tools.sdkcontroller.handlers.SensorChannel;
-import com.android.tools.sdkcontroller.lib.Connection;
-import com.android.tools.sdkcontroller.lib.Channel;
-
-/**
- * The background service of the SdkController.
- * There can be only one instance of this.
- * <p/>
- * The service manages a number of SDK controller channels which can be seen as
- * individual tasks that the user might want to accomplish, for example "sending
- * sensor data to the emulator" or "sending multi-touch data and displaying an
- * emulator screen".
- * <p/>
- * Each channel connects to the emulator via UNIX-domain socket that is bound to
- * "android.sdk.controller" port. Connection class provides a socket server that
- * listens to emulator connections on this port, and binds new connection with a
- * channel, based on channel name.
- * <p/>
- * All the channels are created when the service starts, and whether the emulator
- * connection is successful or not, and whether there's any UI to control it.
- * It's up to the channels to deal with these specific details. <br/>
- * For example the {@link SensorChannel} initializes its sensor list as soon as
- * created and then tries to send data as soon as there's an emulator
- * connection. On the other hand the {@link MultiTouchChannel} lays dormant till
- * there's an UI interacting with it.
- */
-public class ControllerService extends Service {
-
- /*
- * Implementation reference:
- * http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
- */
-
- /** Tag for logging messages. */
- public static String TAG = ControllerService.class.getSimpleName();
- /** Controls debug log. */
- private static boolean DEBUG = true;
- /** Identifier for the notification. */
- private static int NOTIF_ID = 'S' << 24 + 'd' << 16 + 'k' << 8 + 'C' << 0;
-
- /** Connection to the emulator. */
- public Connection mConnection;
-
-
- private final IBinder mBinder = new ControllerBinder();
-
- private List<ControllerListener> mListeners = new ArrayList<ControllerListener>();
-
- /**
- * Whether the service is running. Set to true in onCreate, false in onDestroy.
- */
- private static volatile boolean gServiceIsRunning = false;
-
- /** Internal error reported by the service. */
- private String mServiceError = "";
-
- /**
- * Interface that the service uses to notify binded activities.
- * <p/>
- * As a design rule, implementations of this listener should be aware that most calls
- * will NOT happen on the UI thread. Any access to the UI should be properly protected
- * by using {@link Activity#runOnUiThread(Runnable)}.
- */
- public interface ControllerListener {
- /**
- * The error string reported by the service has changed. <br/>
- * Note this may be called from a thread different than the UI thread.
- */
- void onErrorChanged();
-
- /**
- * The service status has changed (emulator connected/disconnected.)
- */
- void onStatusChanged();
- }
-
- /** Interface that callers can use to access the service. */
- public class ControllerBinder extends Binder {
-
- /**
- * Adds a new listener that will be notified when the service state changes.
- *
- * @param listener A non-null listener. Ignored if already listed.
- */
- public void addControllerListener(ControllerListener listener) {
- assert listener != null;
- if (listener != null) {
- synchronized (mListeners) {
- if (!mListeners.contains(listener)) {
- mListeners.add(listener);
- }
- }
- }
- }
-
- /**
- * Removes a listener.
- *
- * @param listener A listener to remove. Can be null.
- */
- public void removeControllerListener(ControllerListener listener) {
- assert listener != null;
- synchronized (mListeners) {
- mListeners.remove(listener);
- }
- }
-
- /**
- * Returns the error string accumulated by the service.
- * Typically these would relate to failures to establish the communication
- * channel(s) with the emulator, or unexpected disconnections.
- */
- public String getServiceError() {
- return mServiceError;
- }
-
- /**
- * Indicates when <em>any</all> of the SDK controller channels is connected
- * with the emulator.
- *
- * @return True if any of the SDK controller channels is connected with the
- * emulator.
- */
- public boolean isEmuConnected() {
- return mConnection.isEmulatorConnected();
- }
-
- /**
- * Returns the channel instance for the given type.
- *
- * @param name One of the channel names. Must not be null.
- * @return Null if the type is not found, otherwise the handler's unique instance.
- */
- public Channel getChannel(String name) {
- return mConnection.getChannel(name);
- }
- }
-
- /**
- * Whether the service is running. Set to true in onCreate, false in onDestroy.
- */
- public static boolean isServiceIsRunning() {
- return gServiceIsRunning;
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- if (DEBUG) Log.d(TAG, "Service onCreate");
- gServiceIsRunning = true;
- showNotification();
- onServiceStarted();
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- // We want this service to continue running until it is explicitly
- // stopped, so return sticky.
- if (DEBUG) Log.d(TAG, "Service onStartCommand");
- return START_STICKY;
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- if (DEBUG) Log.d(TAG, "Service onBind");
- return mBinder;
- }
-
- @Override
- public void onDestroy() {
- if (DEBUG) Log.d(TAG, "Service onDestroy");
- gServiceIsRunning = false;
- removeNotification();
- resetError();
- onServiceStopped();
- super.onDestroy();
- }
-
- private void disconnectAll() {
- if (mConnection != null) {
- mConnection.disconnect();
- }
- }
-
- /**
- * Called when the service has been created.
- */
- private void onServiceStarted() {
- try {
- disconnectAll();
-
- // Bind to SDK controller port, and start accepting emulator
- // connections.
- mConnection = new Connection(ControllerService.this);
- mConnection.connect();
-
- // Create and register sensors channel.
- mConnection.registerChannel(new SensorChannel(ControllerService.this));
- // Create and register multi-touch channel.
- mConnection.registerChannel(new MultiTouchChannel(ControllerService.this));
- } catch (Exception e) {
- addError("Connection failed: " + e.toString());
- }
- }
-
- /**
- * Called when the service is being destroyed.
- */
- private void onServiceStopped() {
- disconnectAll();
- }
-
- private void notifyErrorChanged() {
- synchronized (mListeners) {
- for (ControllerListener listener : mListeners) {
- listener.onErrorChanged();
- }
- }
- }
-
- public void notifyStatusChanged() {
- synchronized (mListeners) {
- for (ControllerListener listener : mListeners) {
- listener.onStatusChanged();
- }
- }
- }
-
- /**
- * Resets the error string and notify listeners.
- */
- private void resetError() {
- mServiceError = "";
-
- notifyErrorChanged();
- }
-
- /**
- * An internal utility method to add a line to the error string and notify listeners.
- * @param error A non-null non-empty error line. \n will be added automatically.
- */
- public void addError(String error) {
- Log.e(TAG, error);
- if (mServiceError.length() > 0) {
- mServiceError += "\n";
- }
- mServiceError += error;
-
- notifyErrorChanged();
- }
-
- /**
- * Displays a notification showing that the service is running.
- * When the user touches the notification, it opens the main activity
- * which allows the user to stop this service.
- */
- @SuppressWarnings("deprecated")
- private void showNotification() {
- NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
-
- String text = getString(R.string.service_notif_title);
-
- // Note: Notification is marked as deprecated -- in API 11+ there's a new Builder class
- // but we need to have API 7 compatibility so we ignore that warning.
-
- Notification n = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
- n.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
- Intent intent = new Intent(this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- PendingIntent pi = PendingIntent.getActivity(
- this, //context
- 0, //requestCode
- intent, //intent
- 0 //pending intent flags
- );
- n.setLatestEventInfo(this, text, text, pi);
-
- nm.notify(NOTIF_ID, n);
- }
-
- private void removeNotification() {
- NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- nm.cancel(NOTIF_ID);
- }
-}
+/* + * 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.service; + +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.util.Log; + +import com.android.tools.sdkcontroller.R; +import com.android.tools.sdkcontroller.activities.MainActivity; +import com.android.tools.sdkcontroller.handlers.MultiTouchChannel; +import com.android.tools.sdkcontroller.handlers.SensorChannel; +import com.android.tools.sdkcontroller.lib.Connection; +import com.android.tools.sdkcontroller.lib.Channel; + +/** + * The background service of the SdkController. + * There can be only one instance of this. + * <p/> + * The service manages a number of SDK controller channels which can be seen as + * individual tasks that the user might want to accomplish, for example "sending + * sensor data to the emulator" or "sending multi-touch data and displaying an + * emulator screen". + * <p/> + * Each channel connects to the emulator via UNIX-domain socket that is bound to + * "android.sdk.controller" port. Connection class provides a socket server that + * listens to emulator connections on this port, and binds new connection with a + * channel, based on channel name. + * <p/> + * All the channels are created when the service starts, and whether the emulator + * connection is successful or not, and whether there's any UI to control it. + * It's up to the channels to deal with these specific details. <br/> + * For example the {@link SensorChannel} initializes its sensor list as soon as + * created and then tries to send data as soon as there's an emulator + * connection. On the other hand the {@link MultiTouchChannel} lays dormant till + * there's an UI interacting with it. + */ +public class ControllerService extends Service { + + /* + * Implementation reference: + * http://developer.android.com/reference/android/app/Service.html#LocalServiceSample + */ + + /** Tag for logging messages. */ + public static String TAG = ControllerService.class.getSimpleName(); + /** Controls debug log. */ + private static boolean DEBUG = true; + /** Identifier for the notification. */ + private static int NOTIF_ID = 'S' << 24 + 'd' << 16 + 'k' << 8 + 'C' << 0; + + /** Connection to the emulator. */ + public Connection mConnection; + + + private final IBinder mBinder = new ControllerBinder(); + + private List<ControllerListener> mListeners = new ArrayList<ControllerListener>(); + + /** + * Whether the service is running. Set to true in onCreate, false in onDestroy. + */ + private static volatile boolean gServiceIsRunning = false; + + /** Internal error reported by the service. */ + private String mServiceError = ""; + + /** + * Interface that the service uses to notify binded activities. + * <p/> + * As a design rule, implementations of this listener should be aware that most calls + * will NOT happen on the UI thread. Any access to the UI should be properly protected + * by using {@link Activity#runOnUiThread(Runnable)}. + */ + public interface ControllerListener { + /** + * The error string reported by the service has changed. <br/> + * Note this may be called from a thread different than the UI thread. + */ + void onErrorChanged(); + + /** + * The service status has changed (emulator connected/disconnected.) + */ + void onStatusChanged(); + } + + /** Interface that callers can use to access the service. */ + public class ControllerBinder extends Binder { + + /** + * Adds a new listener that will be notified when the service state changes. + * + * @param listener A non-null listener. Ignored if already listed. + */ + public void addControllerListener(ControllerListener listener) { + assert listener != null; + if (listener != null) { + synchronized (mListeners) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } + } + } + } + + /** + * Removes a listener. + * + * @param listener A listener to remove. Can be null. + */ + public void removeControllerListener(ControllerListener listener) { + assert listener != null; + synchronized (mListeners) { + mListeners.remove(listener); + } + } + + /** + * Returns the error string accumulated by the service. + * Typically these would relate to failures to establish the communication + * channel(s) with the emulator, or unexpected disconnections. + */ + public String getServiceError() { + return mServiceError; + } + + /** + * Indicates when <em>any</all> of the SDK controller channels is connected + * with the emulator. + * + * @return True if any of the SDK controller channels is connected with the + * emulator. + */ + public boolean isEmuConnected() { + return mConnection.isEmulatorConnected(); + } + + /** + * Returns the channel instance for the given type. + * + * @param name One of the channel names. Must not be null. + * @return Null if the type is not found, otherwise the handler's unique instance. + */ + public Channel getChannel(String name) { + return mConnection.getChannel(name); + } + } + + /** + * Whether the service is running. Set to true in onCreate, false in onDestroy. + */ + public static boolean isServiceIsRunning() { + return gServiceIsRunning; + } + + @Override + public void onCreate() { + super.onCreate(); + if (DEBUG) Log.d(TAG, "Service onCreate"); + gServiceIsRunning = true; + showNotification(); + onServiceStarted(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // We want this service to continue running until it is explicitly + // stopped, so return sticky. + if (DEBUG) Log.d(TAG, "Service onStartCommand"); + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + if (DEBUG) Log.d(TAG, "Service onBind"); + return mBinder; + } + + @Override + public void onDestroy() { + if (DEBUG) Log.d(TAG, "Service onDestroy"); + gServiceIsRunning = false; + removeNotification(); + resetError(); + onServiceStopped(); + super.onDestroy(); + } + + private void disconnectAll() { + if (mConnection != null) { + mConnection.disconnect(); + } + } + + /** + * Called when the service has been created. + */ + private void onServiceStarted() { + try { + disconnectAll(); + + // Bind to SDK controller port, and start accepting emulator + // connections. + mConnection = new Connection(ControllerService.this); + mConnection.connect(); + + // Create and register sensors channel. + mConnection.registerChannel(new SensorChannel(ControllerService.this)); + // Create and register multi-touch channel. + mConnection.registerChannel(new MultiTouchChannel(ControllerService.this)); + } catch (Exception e) { + addError("Connection failed: " + e.toString()); + } + } + + /** + * Called when the service is being destroyed. + */ + private void onServiceStopped() { + disconnectAll(); + } + + private void notifyErrorChanged() { + synchronized (mListeners) { + for (ControllerListener listener : mListeners) { + listener.onErrorChanged(); + } + } + } + + public void notifyStatusChanged() { + synchronized (mListeners) { + for (ControllerListener listener : mListeners) { + listener.onStatusChanged(); + } + } + } + + /** + * Resets the error string and notify listeners. + */ + private void resetError() { + mServiceError = ""; + + notifyErrorChanged(); + } + + /** + * An internal utility method to add a line to the error string and notify listeners. + * @param error A non-null non-empty error line. \n will be added automatically. + */ + public void addError(String error) { + Log.e(TAG, error); + if (mServiceError.length() > 0) { + mServiceError += "\n"; + } + mServiceError += error; + + notifyErrorChanged(); + } + + /** + * Displays a notification showing that the service is running. + * When the user touches the notification, it opens the main activity + * which allows the user to stop this service. + */ + @SuppressWarnings("deprecated") + private void showNotification() { + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + String text = getString(R.string.service_notif_title); + + // Note: Notification is marked as deprecated -- in API 11+ there's a new Builder class + // but we need to have API 7 compatibility so we ignore that warning. + + Notification n = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis()); + n.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR; + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + PendingIntent pi = PendingIntent.getActivity( + this, //context + 0, //requestCode + intent, //intent + 0 //pending intent flags + ); + n.setLatestEventInfo(this, text, text, pi); + + nm.notify(NOTIF_ID, n); + } + + private void removeNotification() { + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + nm.cancel(NOTIF_ID); + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper.java b/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper.java index 956885b..66bce49 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper.java @@ -1,57 +1,57 @@ -/*
- * 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.utils;
-
-import android.annotation.TargetApi;
-import android.os.Build;
-import android.view.View;
-
-/**
- * Helper to deal with methods only available at certain API levels.
- * Users should get use {@link ApiHelper#get()} to retrieve a singleton
- * and then call the methods they desire. If the method is not available
- * on the current API level, a stub or a nop will be used instead.
- */
-@TargetApi(7)
-public class ApiHelper {
-
- private static ApiHelper sApiHelper = null;
-
- /** Creates a new ApiHelper adapted to the current runtime API level. */
- public static ApiHelper get() {
- if (sApiHelper == null) {
- if (Build.VERSION.SDK_INT >= 11) {
- sApiHelper = new ApiHelper_11();
- } else {
- sApiHelper = new ApiHelper();
- }
- }
-
- return sApiHelper;
- }
-
- protected ApiHelper() {
- }
-
- /**
- * Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11.
- * Does nothing for API < 11.
- */
- public void View_setSystemUiVisibility(View view, int visibility) {
- // nop
- }
-}
+/* + * 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.utils; + +import android.annotation.TargetApi; +import android.os.Build; +import android.view.View; + +/** + * Helper to deal with methods only available at certain API levels. + * Users should get use {@link ApiHelper#get()} to retrieve a singleton + * and then call the methods they desire. If the method is not available + * on the current API level, a stub or a nop will be used instead. + */ +@TargetApi(7) +public class ApiHelper { + + private static ApiHelper sApiHelper = null; + + /** Creates a new ApiHelper adapted to the current runtime API level. */ + public static ApiHelper get() { + if (sApiHelper == null) { + if (Build.VERSION.SDK_INT >= 11) { + sApiHelper = new ApiHelper_11(); + } else { + sApiHelper = new ApiHelper(); + } + } + + return sApiHelper; + } + + protected ApiHelper() { + } + + /** + * Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11. + * Does nothing for API < 11. + */ + public void View_setSystemUiVisibility(View view, int visibility) { + // nop + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper_11.java b/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper_11.java index fcbde6f..2d4e8cd 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper_11.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper_11.java @@ -1,36 +1,36 @@ -/*
- * 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.utils;
-
-import android.annotation.TargetApi;
-import android.view.View;
-
-/**
- * API 11: support View_setSystemUiVisibility
- */
-@TargetApi(11)
-class ApiHelper_11 extends ApiHelper {
-
- /**
- * Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11.
- * Does nothing for API < 11.
- */
- @Override
- public void View_setSystemUiVisibility(View view, int visibility) {
- view.setSystemUiVisibility(visibility);
- }
-}
+/* + * 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.utils; + +import android.annotation.TargetApi; +import android.view.View; + +/** + * API 11: support View_setSystemUiVisibility + */ +@TargetApi(11) +class ApiHelper_11 extends ApiHelper { + + /** + * Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11. + * Does nothing for API < 11. + */ + @Override + public void View_setSystemUiVisibility(View view, int visibility) { + view.setSystemUiVisibility(visibility); + } +} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/views/MultiTouchView.java b/apps/SdkController/src/com/android/tools/sdkcontroller/views/MultiTouchView.java index 30bccdc..0f185b1 100755 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/views/MultiTouchView.java +++ b/apps/SdkController/src/com/android/tools/sdkcontroller/views/MultiTouchView.java @@ -1,232 +1,232 @@ -/*
- * 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.views;
-
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * Implements a main view for the application providing multi-touch emulation.
- */
-public class MultiTouchView extends View {
- /** Tag for logging messages. */
- private static final String TAG = MultiTouchView.class.getSimpleName();
- /**
- * Back-end bitmap. Initialized in onSizeChanged(), updated in
- * onTouchEvent() and drawn in onDraw().
- */
- private Bitmap mBitmap;
- /** Default Paint instance for drawing the bitmap. */
- private final Paint mPaint = new Paint();
- /** Canvas instance for this view. */
- private Canvas mCanvas;
- /** Emulator screen width to this view width ratio. */
- private float mDx = 1;
- /** Emulator screen height to this view height ratio. */
- private float mDy = 1;
- /**
- * Flags whether or not image received from the emulator should be rotated.
- * Rotation is required when display orientation state of the emulator and
- * the device doesn't match.
- */
- private boolean mRotateDisplay;
- /** Base matrix that keep emulator->device display scaling */
- private Matrix mBaseMatrix = new Matrix();
- /** Matrix that is used to draw emulator's screen on the device. */
- private Matrix mDrawMatrix = new Matrix();
-
- /**
- * Simple constructor to use when creating a view from code.
- *
- * @see View#View(Context)
- */
- public MultiTouchView(Context context) {
- this(context, null);
- }
-
- /**
- * Constructor that is called when inflating a view from XML.
- *
- * @see View#View(Context, AttributeSet)
- */
- public MultiTouchView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- /**
- * Perform inflation from XML and apply a class-specific base style.
- *
- * @see View#View(Context, AttributeSet, int)
- */
- public MultiTouchView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- // TODO Add constructor-time code here.
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- mCanvas = new Canvas(mBitmap);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // Just draw the back-end bitmap without zooming or scaling.
- if (mBitmap != null) {
- canvas.drawBitmap(mBitmap, 0, 0, null);
- }
- }
-
- /**
- * Sets emulator screen width and height to this view width and height
- * ratio.
- *
- * @param dx Emulator screen width to this view width ratio.
- * @param dy Emulator screen height to this view height ratio.
- * @param rotateDisplay Flags whether image received from the emulator
- * should be rotated when drawn on the device.
- */
- public void setDxDy(float dx, float dy, boolean rotateDisplay) {
- mDx = dx;
- mDy = dy;
- mRotateDisplay = rotateDisplay;
-
- mBaseMatrix.setScale(dx, dy);
- if (mRotateDisplay) {
- mBaseMatrix.postRotate(90);
- mBaseMatrix.postTranslate(getWidth(), 0);
- }
- }
-
- /**
- * Computes draw matrix for the emulator screen update.
- *
- * @param x Left screen coordinate of the bitmap on emulator screen.
- * @param y Top screen coordinate of the bitmap on emulator screen.
- */
- private void computeDrawMatrix(int x, int y) {
- mDrawMatrix.set(mBaseMatrix);
- if (mRotateDisplay) {
- mDrawMatrix.postTranslate(-y * mDy, x * mDx);
- } else {
- mDrawMatrix.postTranslate(x * mDx, y * mDy);
- }
- }
-
- /**
- * Draws a bitmap on the screen.
- *
- * @param x Left screen coordinate of the bitmap on emulator screen.
- * @param y Top screen coordinate of the bitmap on emulator screen.
- * @param w Width of the bitmap on the emulator screen.
- * @param h Height of the bitmap on the emulator screen.
- * @param colors Bitmap to draw.
- */
- public void drawBitmap(int x, int y, int w, int h, int[] colors) {
- if (mCanvas != null) {
- final Bitmap bmp = Bitmap.createBitmap(colors, 0, w, w, h, Bitmap.Config.ARGB_8888);
-
- computeDrawMatrix(x, y);
-
- /* Draw the bitmap and invalidate the updated region. */
- mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint);
- invalidate();
- }
- }
-
- /**
- * Draws a JPEG bitmap on the screen.
- *
- * @param x Left screen coordinate of the bitmap on emulator screen.
- * @param y Top screen coordinate of the bitmap on emulator screen.
- * @param w Width of the bitmap on the emulator screen.
- * @param h Height of the bitmap on the emulator screen.
- * @param jpeg JPEG bitmap to draw.
- */
- public void drawJpeg(int x, int y, int w, int h, InputStream jpeg) {
- if (mCanvas != null) {
- final Bitmap bmp = BitmapFactory.decodeStream(jpeg);
-
- computeDrawMatrix(x, y);
-
- /* Draw the bitmap and invalidate the updated region. */
- mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint);
- invalidate();
- }
- }
-
- /**
- * Constructs touch event message to be send to emulator.
- *
- * @param bb ByteBuffer where to construct the message.
- * @param event Event for which to construct the message.
- * @param ptr_index Index of the motion pointer for which to construct the
- * message.
- */
- public void constructEventMessage(ByteBuffer bb, MotionEvent event, int ptr_index) {
- bb.putInt(event.getPointerId(ptr_index));
- if (mRotateDisplay == false) {
- bb.putInt((int) (event.getX(ptr_index) / mDx));
- bb.putInt((int) (event.getY(ptr_index) / mDy));
- } else {
- bb.putInt((int) (event.getY(ptr_index) / mDy));
- bb.putInt((int) (getWidth() - event.getX(ptr_index) / mDx));
- }
- // At the system level the input reader takes integers in the range
- // 0 - 100 for the pressure.
- int pressure = (int) (event.getPressure(ptr_index) * 100);
- // Make sure it doesn't exceed 100...
- if (pressure > 100) {
- pressure = 100;
- }
- bb.putInt(pressure);
- }
-
- /***************************************************************************
- * Logging wrappers
- **************************************************************************/
-
- @SuppressWarnings("unused")
- private void Loge(String log) {
- Log.e(TAG, log);
- }
-
- @SuppressWarnings("unused")
- private void Logw(String log) {
- Log.w(TAG, log);
- }
-
- @SuppressWarnings("unused")
- private void Logv(String log) {
- Log.v(TAG, log);
- }
-}
+/* + * 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.views; + +import java.io.InputStream; +import java.nio.ByteBuffer; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +/** + * Implements a main view for the application providing multi-touch emulation. + */ +public class MultiTouchView extends View { + /** Tag for logging messages. */ + private static final String TAG = MultiTouchView.class.getSimpleName(); + /** + * Back-end bitmap. Initialized in onSizeChanged(), updated in + * onTouchEvent() and drawn in onDraw(). + */ + private Bitmap mBitmap; + /** Default Paint instance for drawing the bitmap. */ + private final Paint mPaint = new Paint(); + /** Canvas instance for this view. */ + private Canvas mCanvas; + /** Emulator screen width to this view width ratio. */ + private float mDx = 1; + /** Emulator screen height to this view height ratio. */ + private float mDy = 1; + /** + * Flags whether or not image received from the emulator should be rotated. + * Rotation is required when display orientation state of the emulator and + * the device doesn't match. + */ + private boolean mRotateDisplay; + /** Base matrix that keep emulator->device display scaling */ + private Matrix mBaseMatrix = new Matrix(); + /** Matrix that is used to draw emulator's screen on the device. */ + private Matrix mDrawMatrix = new Matrix(); + + /** + * Simple constructor to use when creating a view from code. + * + * @see View#View(Context) + */ + public MultiTouchView(Context context) { + this(context, null); + } + + /** + * Constructor that is called when inflating a view from XML. + * + * @see View#View(Context, AttributeSet) + */ + public MultiTouchView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /** + * Perform inflation from XML and apply a class-specific base style. + * + * @see View#View(Context, AttributeSet, int) + */ + public MultiTouchView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + // TODO Add constructor-time code here. + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + mCanvas = new Canvas(mBitmap); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // Just draw the back-end bitmap without zooming or scaling. + if (mBitmap != null) { + canvas.drawBitmap(mBitmap, 0, 0, null); + } + } + + /** + * Sets emulator screen width and height to this view width and height + * ratio. + * + * @param dx Emulator screen width to this view width ratio. + * @param dy Emulator screen height to this view height ratio. + * @param rotateDisplay Flags whether image received from the emulator + * should be rotated when drawn on the device. + */ + public void setDxDy(float dx, float dy, boolean rotateDisplay) { + mDx = dx; + mDy = dy; + mRotateDisplay = rotateDisplay; + + mBaseMatrix.setScale(dx, dy); + if (mRotateDisplay) { + mBaseMatrix.postRotate(90); + mBaseMatrix.postTranslate(getWidth(), 0); + } + } + + /** + * Computes draw matrix for the emulator screen update. + * + * @param x Left screen coordinate of the bitmap on emulator screen. + * @param y Top screen coordinate of the bitmap on emulator screen. + */ + private void computeDrawMatrix(int x, int y) { + mDrawMatrix.set(mBaseMatrix); + if (mRotateDisplay) { + mDrawMatrix.postTranslate(-y * mDy, x * mDx); + } else { + mDrawMatrix.postTranslate(x * mDx, y * mDy); + } + } + + /** + * Draws a bitmap on the screen. + * + * @param x Left screen coordinate of the bitmap on emulator screen. + * @param y Top screen coordinate of the bitmap on emulator screen. + * @param w Width of the bitmap on the emulator screen. + * @param h Height of the bitmap on the emulator screen. + * @param colors Bitmap to draw. + */ + public void drawBitmap(int x, int y, int w, int h, int[] colors) { + if (mCanvas != null) { + final Bitmap bmp = Bitmap.createBitmap(colors, 0, w, w, h, Bitmap.Config.ARGB_8888); + + computeDrawMatrix(x, y); + + /* Draw the bitmap and invalidate the updated region. */ + mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint); + invalidate(); + } + } + + /** + * Draws a JPEG bitmap on the screen. + * + * @param x Left screen coordinate of the bitmap on emulator screen. + * @param y Top screen coordinate of the bitmap on emulator screen. + * @param w Width of the bitmap on the emulator screen. + * @param h Height of the bitmap on the emulator screen. + * @param jpeg JPEG bitmap to draw. + */ + public void drawJpeg(int x, int y, int w, int h, InputStream jpeg) { + if (mCanvas != null) { + final Bitmap bmp = BitmapFactory.decodeStream(jpeg); + + computeDrawMatrix(x, y); + + /* Draw the bitmap and invalidate the updated region. */ + mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint); + invalidate(); + } + } + + /** + * Constructs touch event message to be send to emulator. + * + * @param bb ByteBuffer where to construct the message. + * @param event Event for which to construct the message. + * @param ptr_index Index of the motion pointer for which to construct the + * message. + */ + public void constructEventMessage(ByteBuffer bb, MotionEvent event, int ptr_index) { + bb.putInt(event.getPointerId(ptr_index)); + if (mRotateDisplay == false) { + bb.putInt((int) (event.getX(ptr_index) / mDx)); + bb.putInt((int) (event.getY(ptr_index) / mDy)); + } else { + bb.putInt((int) (event.getY(ptr_index) / mDy)); + bb.putInt((int) (getWidth() - event.getX(ptr_index) / mDx)); + } + // At the system level the input reader takes integers in the range + // 0 - 100 for the pressure. + int pressure = (int) (event.getPressure(ptr_index) * 100); + // Make sure it doesn't exceed 100... + if (pressure > 100) { + pressure = 100; + } + bb.putInt(pressure); + } + + /*************************************************************************** + * Logging wrappers + **************************************************************************/ + + @SuppressWarnings("unused") + private void Loge(String log) { + Log.e(TAG, log); + } + + @SuppressWarnings("unused") + private void Logw(String log) { + Log.w(TAG, log); + } + + @SuppressWarnings("unused") + private void Logv(String log) { + Log.v(TAG, log); + } +} diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_1.xml b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_1.xml index aa209d3..7e2bc36 100755 --- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_1.xml +++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_1.xml @@ -1,165 +1,165 @@ -<?xml version="1.0"?>
-<!--
- * Copyright (C) 2009 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.
--->
-<sdk:sdk-repository
- xmlns:sdk="http://schemas.android.com/sdk/android/repository/1">
-
- <!-- Define a couple of licenses. These will be referenced by uses-license later. -->
-
- <sdk:license type="text" id="license1">
- This is the license
- for this platform.
- </sdk:license>
-
- <sdk:license id="license2">
- Licenses are only of type 'text' right now, so this is implied.
- </sdk:license>
-
- <!-- Inner elements must be either platform, add-on, doc or tool.
- There can be 0 or more of each, in any order. -->
-
- <sdk:platform>
- <sdk:version>1.0</sdk:version>
- <sdk:api-level>1</sdk:api-level>
- <sdk:revision>3</sdk:revision>
- <sdk:uses-license ref="license1" />
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
- <sdk:release-note>This is an optional release note
- for this package. It's a free multi-line text.
- </sdk:release-note>
- <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url>
- <sdk:min-tools-rev>2</sdk:min-tools-rev>
- <!-- The archives node is mandatory and it cannot be empty. -->
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:platform>
-
- <sdk:doc>
- <sdk:api-level>1</sdk:api-level>
- <sdk:revision>1</sdk:revision>
- <!-- the license element is not mandatory. -->
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url>
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:doc>
-
- <sdk:add-on>
- <sdk:name>My First add-on</sdk:name>
- <sdk:api-level>1</sdk:api-level>
- <sdk:vendor>John Doe</sdk:vendor>
- <sdk:revision>1</sdk:revision>
- <sdk:uses-license ref="license2" />
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url>
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <!-- The libs node is mandatory, however it can be empty. -->
- <sdk:libs>
- <sdk:lib>
- <sdk:name>android.blah.somelib</sdk:name>
- <sdk:description>The description for this library.</sdk:description>
- </sdk:lib>
- <sdk:lib>
- <!-- sdk:description is optional, name is not -->
- <sdk:name>com.android.mymaps</sdk:name>
- </sdk:lib>
- </sdk:libs>
- </sdk:add-on>
-
- <sdk:platform>
- <sdk:version>1.1</sdk:version>
- <sdk:api-level>2</sdk:api-level>
- <sdk:revision>12</sdk:revision>
- <sdk:uses-license ref="license1" />
- <!-- sdk:description and sdk:desc-url are optional -->
- <sdk:archives>
- <sdk:archive os="windows">
- <!-- arch attribute is optional -->
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-win.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx" arch="ppc">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux" arch="x86">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux" arch="x86_64">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:platform>
-
- <sdk:add-on>
- <sdk:name>My Second add-on</sdk:name>
- <sdk:api-level>2</sdk:api-level>
- <sdk:vendor>John Deer</sdk:vendor>
- <sdk:revision>42</sdk:revision>
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/second-42-win.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:libs>
- <sdk:lib>
- <sdk:name>android.blah.somelib</sdk:name>
- <sdk:description>The description for this library.</sdk:description>
- </sdk:lib>
- <sdk:lib>
- <sdk:name>com.android.mymaps</sdk:name>
- </sdk:lib>
- </sdk:libs>
- <sdk:uses-license ref="license2" />
- </sdk:add-on>
+<?xml version="1.0"?> +<!-- + * Copyright (C) 2009 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. +--> +<sdk:sdk-repository + xmlns:sdk="http://schemas.android.com/sdk/android/repository/1"> + + <!-- Define a couple of licenses. These will be referenced by uses-license later. --> + + <sdk:license type="text" id="license1"> + This is the license + for this platform. + </sdk:license> + + <sdk:license id="license2"> + Licenses are only of type 'text' right now, so this is implied. + </sdk:license> + + <!-- Inner elements must be either platform, add-on, doc or tool. + There can be 0 or more of each, in any order. --> + + <sdk:platform> + <sdk:version>1.0</sdk:version> + <sdk:api-level>1</sdk:api-level> + <sdk:revision>3</sdk:revision> + <sdk:uses-license ref="license1" /> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url> + <sdk:release-note>This is an optional release note + for this package. It's a free multi-line text. + </sdk:release-note> + <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url> + <sdk:min-tools-rev>2</sdk:min-tools-rev> + <!-- The archives node is mandatory and it cannot be empty. --> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/files/plat1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:platform> + + <sdk:doc> + <sdk:api-level>1</sdk:api-level> + <sdk:revision>1</sdk:revision> + <!-- the license element is not mandatory. --> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:doc> + + <sdk:add-on> + <sdk:name>My First add-on</sdk:name> + <sdk:api-level>1</sdk:api-level> + <sdk:vendor>John Doe</sdk:vendor> + <sdk:revision>1</sdk:revision> + <sdk:uses-license ref="license2" /> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <!-- The libs node is mandatory, however it can be empty. --> + <sdk:libs> + <sdk:lib> + <sdk:name>android.blah.somelib</sdk:name> + <sdk:description>The description for this library.</sdk:description> + </sdk:lib> + <sdk:lib> + <!-- sdk:description is optional, name is not --> + <sdk:name>com.android.mymaps</sdk:name> + </sdk:lib> + </sdk:libs> + </sdk:add-on> + + <sdk:platform> + <sdk:version>1.1</sdk:version> + <sdk:api-level>2</sdk:api-level> + <sdk:revision>12</sdk:revision> + <sdk:uses-license ref="license1" /> + <!-- sdk:description and sdk:desc-url are optional --> + <sdk:archives> + <sdk:archive os="windows"> + <!-- arch attribute is optional --> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-win.zip</sdk:url> + </sdk:archive> + <sdk:archive os="macosx" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-mac.zip</sdk:url> + </sdk:archive> + <sdk:archive os="macosx" arch="ppc"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-mac.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux" arch="x86"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="linux" arch="x86_64"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:platform> + + <sdk:add-on> + <sdk:name>My Second add-on</sdk:name> + <sdk:api-level>2</sdk:api-level> + <sdk:vendor>John Deer</sdk:vendor> + <sdk:revision>42</sdk:revision> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/second-42-win.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:libs> + <sdk:lib> + <sdk:name>android.blah.somelib</sdk:name> + <sdk:description>The description for this library.</sdk:description> + </sdk:lib> + <sdk:lib> + <sdk:name>com.android.mymaps</sdk:name> + </sdk:lib> + </sdk:libs> + <sdk:uses-license ref="license2" /> + </sdk:add-on> <sdk:platform> <sdk:version>Pastry</sdk:version> @@ -178,97 +178,97 @@ </sdk:archive> </sdk:archives> </sdk:platform> -
- <sdk:tool>
- <sdk:revision>1</sdk:revision>
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url>
- <sdk:uses-license ref="license1" />
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/files/tools1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:tool>
-
- <sdk:doc>
- <sdk:api-level>2</sdk:api-level>
- <sdk:revision>42</sdk:revision>
- <sdk:uses-license ref="license2" />
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs/2.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:doc>
-
- <sdk:tool>
- <sdk:revision>42</sdk:revision>
- <sdk:uses-license ref="license1" />
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools/2.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:tool>
-
- <sdk:add-on>
- <sdk:uses-license ref="license2" />
- <sdk:name>This add-on has no libraries</sdk:name>
- <sdk:api-level>4</sdk:api-level>
- <sdk:vendor>Joe Bar</sdk:vendor>
- <sdk:revision>3</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <!-- The libs node is mandatory, however it can be empty. -->
- <sdk:libs />
- </sdk:add-on>
-
- <sdk:extra>
- <sdk:path>usb_driver</sdk:path>
- <sdk:uses-license ref="license2" />
- <sdk:revision>43</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/extraduff.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description>
- <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
- <sdk:min-tools-rev>3</sdk:min-tools-rev>
- </sdk:extra>
-
-</sdk:sdk-repository>
+ + <sdk:tool> + <sdk:revision>1</sdk:revision> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url> + <sdk:uses-license ref="license1" /> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/files/tools1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:tool> + + <sdk:doc> + <sdk:api-level>2</sdk:api-level> + <sdk:revision>42</sdk:revision> + <sdk:uses-license ref="license2" /> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs/2.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="macosx"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:doc> + + <sdk:tool> + <sdk:revision>42</sdk:revision> + <sdk:uses-license ref="license1" /> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools/2.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="macosx"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:tool> + + <sdk:add-on> + <sdk:uses-license ref="license2" /> + <sdk:name>This add-on has no libraries</sdk:name> + <sdk:api-level>4</sdk:api-level> + <sdk:vendor>Joe Bar</sdk:vendor> + <sdk:revision>3</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <!-- The libs node is mandatory, however it can be empty. --> + <sdk:libs /> + </sdk:add-on> + + <sdk:extra> + <sdk:path>usb_driver</sdk:path> + <sdk:uses-license ref="license2" /> + <sdk:revision>43</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/extraduff.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description> + <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url> + <sdk:min-tools-rev>3</sdk:min-tools-rev> + </sdk:extra> + +</sdk:sdk-repository> diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_2.xml b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_2.xml index 4b8e329..6b2d679 100755 --- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_2.xml +++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_2.xml @@ -1,165 +1,165 @@ -<?xml version="1.0"?>
-<!--
- * Copyright (C) 2009 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.
--->
-<sdk:sdk-repository
- xmlns:sdk="http://schemas.android.com/sdk/android/repository/2">
-
- <!-- Define a couple of licenses. These will be referenced by uses-license later. -->
-
- <sdk:license type="text" id="license1">
- This is the license
- for this platform.
- </sdk:license>
-
- <sdk:license id="license2">
- Licenses are only of type 'text' right now, so this is implied.
- </sdk:license>
-
- <!-- Inner elements must be either platform, add-on, doc or tool.
- There can be 0 or more of each, in any order. -->
-
- <sdk:platform>
- <sdk:version>1.0</sdk:version>
- <sdk:api-level>1</sdk:api-level>
- <sdk:revision>3</sdk:revision>
- <sdk:uses-license ref="license1" />
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
- <sdk:release-note>This is an optional release note
- for this package. It's a free multi-line text.
- </sdk:release-note>
- <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url>
- <sdk:min-tools-rev>2</sdk:min-tools-rev>
- <!-- The archives node is mandatory and it cannot be empty. -->
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:platform>
-
- <sdk:doc>
- <sdk:api-level>1</sdk:api-level>
- <sdk:revision>1</sdk:revision>
- <!-- the license element is not mandatory. -->
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url>
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:doc>
-
- <sdk:add-on>
- <sdk:name>My First add-on</sdk:name>
- <sdk:api-level>1</sdk:api-level>
- <sdk:vendor>John Doe</sdk:vendor>
- <sdk:revision>1</sdk:revision>
- <sdk:uses-license ref="license2" />
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url>
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <!-- The libs node is mandatory, however it can be empty. -->
- <sdk:libs>
- <sdk:lib>
- <sdk:name>android.blah.somelib</sdk:name>
- <sdk:description>The description for this library.</sdk:description>
- </sdk:lib>
- <sdk:lib>
- <!-- sdk:description is optional, name is not -->
- <sdk:name>com.android.mymaps</sdk:name>
- </sdk:lib>
- </sdk:libs>
- </sdk:add-on>
-
- <sdk:platform>
- <sdk:version>1.1</sdk:version>
- <sdk:api-level>2</sdk:api-level>
- <sdk:revision>12</sdk:revision>
- <sdk:uses-license ref="license1" />
- <!-- sdk:description and sdk:desc-url are optional -->
- <sdk:archives>
- <sdk:archive os="windows">
- <!-- arch attribute is optional -->
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-win.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx" arch="ppc">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux" arch="x86">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux" arch="x86_64">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:platform>
-
- <sdk:add-on>
- <sdk:name>My Second add-on</sdk:name>
- <sdk:api-level>2</sdk:api-level>
- <sdk:vendor>John Deer</sdk:vendor>
- <sdk:revision>42</sdk:revision>
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/second-42-win.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:libs>
- <sdk:lib>
- <sdk:name>android.blah.somelib</sdk:name>
- <sdk:description>The description for this library.</sdk:description>
- </sdk:lib>
- <sdk:lib>
- <sdk:name>com.android.mymaps</sdk:name>
- </sdk:lib>
- </sdk:libs>
- <sdk:uses-license ref="license2" />
- </sdk:add-on>
+<?xml version="1.0"?> +<!-- + * Copyright (C) 2009 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. +--> +<sdk:sdk-repository + xmlns:sdk="http://schemas.android.com/sdk/android/repository/2"> + + <!-- Define a couple of licenses. These will be referenced by uses-license later. --> + + <sdk:license type="text" id="license1"> + This is the license + for this platform. + </sdk:license> + + <sdk:license id="license2"> + Licenses are only of type 'text' right now, so this is implied. + </sdk:license> + + <!-- Inner elements must be either platform, add-on, doc or tool. + There can be 0 or more of each, in any order. --> + + <sdk:platform> + <sdk:version>1.0</sdk:version> + <sdk:api-level>1</sdk:api-level> + <sdk:revision>3</sdk:revision> + <sdk:uses-license ref="license1" /> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url> + <sdk:release-note>This is an optional release note + for this package. It's a free multi-line text. + </sdk:release-note> + <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url> + <sdk:min-tools-rev>2</sdk:min-tools-rev> + <!-- The archives node is mandatory and it cannot be empty. --> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/files/plat1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:platform> + + <sdk:doc> + <sdk:api-level>1</sdk:api-level> + <sdk:revision>1</sdk:revision> + <!-- the license element is not mandatory. --> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:doc> + + <sdk:add-on> + <sdk:name>My First add-on</sdk:name> + <sdk:api-level>1</sdk:api-level> + <sdk:vendor>John Doe</sdk:vendor> + <sdk:revision>1</sdk:revision> + <sdk:uses-license ref="license2" /> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <!-- The libs node is mandatory, however it can be empty. --> + <sdk:libs> + <sdk:lib> + <sdk:name>android.blah.somelib</sdk:name> + <sdk:description>The description for this library.</sdk:description> + </sdk:lib> + <sdk:lib> + <!-- sdk:description is optional, name is not --> + <sdk:name>com.android.mymaps</sdk:name> + </sdk:lib> + </sdk:libs> + </sdk:add-on> + + <sdk:platform> + <sdk:version>1.1</sdk:version> + <sdk:api-level>2</sdk:api-level> + <sdk:revision>12</sdk:revision> + <sdk:uses-license ref="license1" /> + <!-- sdk:description and sdk:desc-url are optional --> + <sdk:archives> + <sdk:archive os="windows"> + <!-- arch attribute is optional --> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-win.zip</sdk:url> + </sdk:archive> + <sdk:archive os="macosx" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-mac.zip</sdk:url> + </sdk:archive> + <sdk:archive os="macosx" arch="ppc"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-mac.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux" arch="x86"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="linux" arch="x86_64"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:platform> + + <sdk:add-on> + <sdk:name>My Second add-on</sdk:name> + <sdk:api-level>2</sdk:api-level> + <sdk:vendor>John Deer</sdk:vendor> + <sdk:revision>42</sdk:revision> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/second-42-win.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:libs> + <sdk:lib> + <sdk:name>android.blah.somelib</sdk:name> + <sdk:description>The description for this library.</sdk:description> + </sdk:lib> + <sdk:lib> + <sdk:name>com.android.mymaps</sdk:name> + </sdk:lib> + </sdk:libs> + <sdk:uses-license ref="license2" /> + </sdk:add-on> <sdk:platform> <sdk:version>Pastry</sdk:version> @@ -178,132 +178,132 @@ </sdk:archive> </sdk:archives> </sdk:platform> -
- <sdk:tool>
- <sdk:revision>1</sdk:revision>
- <sdk:description>Some optional description</sdk:description>
- <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url>
- <sdk:uses-license ref="license1" />
- <sdk:archives>
- <sdk:archive os="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>http://www.example.com/files/tools1.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:tool>
-
- <sdk:doc>
- <sdk:api-level>2</sdk:api-level>
- <sdk:revision>42</sdk:revision>
- <sdk:uses-license ref="license2" />
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs/2.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:doc>
-
- <sdk:tool>
- <sdk:revision>42</sdk:revision>
- <sdk:uses-license ref="license1" />
- <sdk:archives>
- <sdk:archive os="windows">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools/2.zip</sdk:url>
- </sdk:archive>
- <sdk:archive os="linux">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url>
- </sdk:archive>
- <sdk:archive os="macosx">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url>
- </sdk:archive>
- </sdk:archives>
- </sdk:tool>
-
- <sdk:add-on>
- <sdk:uses-license ref="license2" />
- <sdk:name>This add-on has no libraries</sdk:name>
- <sdk:api-level>4</sdk:api-level>
- <sdk:vendor>Joe Bar</sdk:vendor>
- <sdk:revision>3</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <!-- The libs node is mandatory, however it can be empty. -->
- <sdk:libs />
- </sdk:add-on>
-
- <sdk:extra>
- <sdk:path>usb_driver</sdk:path>
- <sdk:uses-license ref="license2" />
- <sdk:revision>43</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/extraduff.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description>
- <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
- <sdk:min-tools-rev>3</sdk:min-tools-rev>
- <sdk:obsolete/>
- </sdk:extra>
-
- <sdk:extra>
- <sdk:path>extra_api_dep</sdk:path>
- <sdk:uses-license ref="license2" />
- <sdk:revision>2</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65536</sdk:size>
- <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/extra_mega_duff.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:description>Some extra package that has a min-api-level of 42</sdk:description>
- <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
- <sdk:min-tools-rev>3</sdk:min-tools-rev>
- <sdk:min-api-level>42</sdk:min-api-level>
- <sdk:obsolete></sdk:obsolete>
- </sdk:extra>
-
- <sdk:sample>
- <sdk:api-level>14</sdk:api-level>
- <sdk:revision>24</sdk:revision>
- <sdk:archives>
- <sdk:archive os="any" arch="any">
- <sdk:size>65537</sdk:size>
- <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
- <sdk:url>distrib/sample_duff.zip</sdk:url>
- </sdk:archive>
- </sdk:archives>
- <sdk:description>Some sample package</sdk:description>
- <sdk:desc-url>http://www.example.com/sample.html</sdk:desc-url>
- <sdk:min-tools-rev>5</sdk:min-tools-rev>
- <sdk:obsolete>This is obsolete</sdk:obsolete>
- </sdk:sample>
-
-</sdk:sdk-repository>
+ + <sdk:tool> + <sdk:revision>1</sdk:revision> + <sdk:description>Some optional description</sdk:description> + <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url> + <sdk:uses-license ref="license1" /> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/files/tools1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:tool> + + <sdk:doc> + <sdk:api-level>2</sdk:api-level> + <sdk:revision>42</sdk:revision> + <sdk:uses-license ref="license2" /> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs/2.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="macosx"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:doc> + + <sdk:tool> + <sdk:revision>42</sdk:revision> + <sdk:uses-license ref="license1" /> + <sdk:archives> + <sdk:archive os="windows"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools/2.zip</sdk:url> + </sdk:archive> + <sdk:archive os="linux"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url> + </sdk:archive> + <sdk:archive os="macosx"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:tool> + + <sdk:add-on> + <sdk:uses-license ref="license2" /> + <sdk:name>This add-on has no libraries</sdk:name> + <sdk:api-level>4</sdk:api-level> + <sdk:vendor>Joe Bar</sdk:vendor> + <sdk:revision>3</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <!-- The libs node is mandatory, however it can be empty. --> + <sdk:libs /> + </sdk:add-on> + + <sdk:extra> + <sdk:path>usb_driver</sdk:path> + <sdk:uses-license ref="license2" /> + <sdk:revision>43</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/extraduff.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description> + <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url> + <sdk:min-tools-rev>3</sdk:min-tools-rev> + <sdk:obsolete/> + </sdk:extra> + + <sdk:extra> + <sdk:path>extra_api_dep</sdk:path> + <sdk:uses-license ref="license2" /> + <sdk:revision>2</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/extra_mega_duff.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:description>Some extra package that has a min-api-level of 42</sdk:description> + <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url> + <sdk:min-tools-rev>3</sdk:min-tools-rev> + <sdk:min-api-level>42</sdk:min-api-level> + <sdk:obsolete></sdk:obsolete> + </sdk:extra> + + <sdk:sample> + <sdk:api-level>14</sdk:api-level> + <sdk:revision>24</sdk:revision> + <sdk:archives> + <sdk:archive os="any" arch="any"> + <sdk:size>65537</sdk:size> + <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>distrib/sample_duff.zip</sdk:url> + </sdk:archive> + </sdk:archives> + <sdk:description>Some sample package</sdk:description> + <sdk:desc-url>http://www.example.com/sample.html</sdk:desc-url> + <sdk:min-tools-rev>5</sdk:min-tools-rev> + <sdk:obsolete>This is obsolete</sdk:obsolete> + </sdk:sample> + +</sdk:sdk-repository> |