diff options
Diffstat (limited to 'apps/SdkController')
36 files changed, 0 insertions, 5188 deletions
diff --git a/apps/SdkController/.classpath b/apps/SdkController/.classpath deleted file mode 100755 index a4f1e4054..000000000 --- a/apps/SdkController/.classpath +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="gen"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
- <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
- <classpathentry kind="output" path="bin/classes"/>
-</classpath>
diff --git a/apps/SdkController/.project b/apps/SdkController/.project deleted file mode 100755 index a3417c5b0..000000000 --- a/apps/SdkController/.project +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>SdkControllerApp</name>
- <comment></comment>
- <projects>
- <project>SdkControllerLib</project>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>com.android.ide.eclipse.adt.ApkBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
diff --git a/apps/SdkController/.settings/org.eclipse.jdt.core.prefs b/apps/SdkController/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 5b174be29..000000000 --- a/apps/SdkController/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,12 +0,0 @@ -#Fri Apr 06 22:06:54 PDT 2012
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.6
diff --git a/apps/SdkController/AndroidManifest.xml b/apps/SdkController/AndroidManifest.xml deleted file mode 100755 index df7aa47d6..000000000 --- a/apps/SdkController/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?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/Implementation.txt b/apps/SdkController/Implementation.txt deleted file mode 100755 index f1ead49d9..000000000 --- a/apps/SdkController/Implementation.txt +++ /dev/null @@ -1,85 +0,0 @@ -Implementation Details for SdkControllerApp -------------------------------------------- - ----- 2012-03-22 -App is in the namespace com.android.tools.sdkcontroller. - -This is an app that has a minSdkVersion of 7 (Eclair) -and a targetSdkVersion of 15 (ICS). The target version -means the app is forbidden under ICS from doing any network -communication on its main thread. - -The overall design: -- A background service is started by the app. It handles the connection - to the emulator and provides a number of "handlers". Handlers can be - though as being separate tasks that the user wants to achieve, for example - sending sensor data, sending multi-touch events, receiving screen updates, - sending a camera feed, etc. -- All the handlers are started when the service starts and shutdown with it. - They basically stay there as long as the app is running, and its up to the - handler to deal with emulator connections starts/stopping. Some handlers - will run in the background (e.g. sending sensor data) whereas other might - need an activity to connect to them first. -- The app has a number of activities which connect to existing handlers. - -Another way to see it is that the app handles a number of tasks which are -composed of a background handler (that consumes data form the emulator and -can send data to the emulator) and an optional activity for UI (that displays -or controls the handler's state.) - - -Here's a quick overview of the classes in the application: - - -The main UI is in activities.MainActivity. -There are 2 tasks activities: SensorActivity and MultiTouchActivity. - -These all derive from BaseBindingActivity which provides a few convenient common features -- in onResume this will bind to the service, creating and starting it if necessary. -- in onPause, this will unbind from the service, but does not stop it. - -Note however that due to the asynchronous nature of the bind operation, the activity -must not attempt to use the service from onResume. Instead there are 2 callbacks to use: -- onServiceConnected when the bind succeeded. -- onServiceDisconnected as the reverse operation. - -When the activity is connected to the service, it can then use getServiceBinder() -to get an interface to talk to the service. - -In the other direction, the activity provides a listener for the service to notify -the application: ControllerListener createControllerListener(). - -The activity can then access the handler: - handler = getServiceBinder().getHandler(HandlerType....) - -and then the activity wants to provide a listener to get notified by the handler: - handler.addUiHandler(new android.os.Handler(this)); - -The emulator connection is separated in the "lib" subpackage: -- EmulatorConnection abstracts a connection to the emulator. - - Object is first created by giving a non-null EmulatorListener. - - then connect(port) is called to initiate the connection. - - The EmulatorConnection is always created in SYNC mode. -- EmulatorListener is a callback: the emulator connection uses it to indicate - when the connection is actually connected or disconnected. - -In the end we have the following workflow describing who controls what (-->): - - - Emulator - ^ ^ - | | EmuCnxHandler - sendEventToEmulator| | (EmulatorListener) - | +-------------+ - | | - handlers.BaseHandler | v - Activity ------------------------> Handler <---- ControllerService - UI <------------------------ | ^ - android.os.Handler | | - | ^ | | - | | ControllerListener | | - | +--------------------------------------------------+ | - +-----------------------------------------------------------+ - ControllerBinder - ----- diff --git a/apps/SdkController/NOTICE b/apps/SdkController/NOTICE deleted file mode 100644 index 06a9081ca..000000000 --- a/apps/SdkController/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2014, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/apps/SdkController/assets/intro_help.html b/apps/SdkController/assets/intro_help.html deleted file mode 100755 index 7657aa320..000000000 --- a/apps/SdkController/assets/intro_help.html +++ /dev/null @@ -1,42 +0,0 @@ -<html>
-<!--
-/*
- * 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.
- */
--->
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
- <style type="text/css">
- body { color: white; background-color: black }
- a:link { color: #33B5E5; /*blue*/ }
- a:visited { color: #99CC00; /*green*/ }
- a:hover { color: #FFBB33; /*yellow*/; }
- </style>
-</head>
-<body>
-<hr/>
-<b>SdkController</b> is used to send sensor data from an actual device to an emulator. <p/>
-To use it, do the following: <br/>
-<ol>
-<li>Connect your device to your computer via USB. Make sure to enable <i>USB Debugging</i> in <i>Settings > Developer Options</i>. </li>
-<li>Start this application on your device. </li>
-<li>On the computer in a shell, run: <br/><i>adb forward tcp:1970 localabstract:android.sdk.controller</i> </li>
-<li>Finally <b>run an emulator</b> with an AVD targetting <b>API 15</b>.
-Multi-touch emulation must be explicitly enabled in emulator either by setting "Touch screen type" property to "multi-touch" in AVD Manager,
-or by starting the emulator with "-screen multi-touch" option.</li>
-</ol>
-<a href="https://sites.google.com/a/android.com/tools/recent/sensoremulation">Read more.</a>
-</body>
-</html>
diff --git a/apps/SdkController/bin/SdkControllerApp.apk b/apps/SdkController/bin/SdkControllerApp.apk Binary files differdeleted file mode 100755 index f8c12940f..000000000 --- a/apps/SdkController/bin/SdkControllerApp.apk +++ /dev/null diff --git a/apps/SdkController/proguard-project.txt b/apps/SdkController/proguard-project.txt deleted file mode 100755 index f2fe1559a..000000000 --- a/apps/SdkController/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/apps/SdkController/project.properties b/apps/SdkController/project.properties deleted file mode 100755 index 9c52cb128..000000000 --- a/apps/SdkController/project.properties +++ /dev/null @@ -1,14 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt - -# Project target. -target=android-15 diff --git a/apps/SdkController/res/drawable-hdpi/ic_launcher.png b/apps/SdkController/res/drawable-hdpi/ic_launcher.png Binary files differdeleted file mode 100755 index 96a442e5b..000000000 --- a/apps/SdkController/res/drawable-hdpi/ic_launcher.png +++ /dev/null diff --git a/apps/SdkController/res/drawable-ldpi/ic_launcher.png b/apps/SdkController/res/drawable-ldpi/ic_launcher.png Binary files differdeleted file mode 100755 index 99238729d..000000000 --- a/apps/SdkController/res/drawable-ldpi/ic_launcher.png +++ /dev/null diff --git a/apps/SdkController/res/drawable-mdpi/ic_launcher.png b/apps/SdkController/res/drawable-mdpi/ic_launcher.png Binary files differdeleted file mode 100755 index 359047dfa..000000000 --- a/apps/SdkController/res/drawable-mdpi/ic_launcher.png +++ /dev/null diff --git a/apps/SdkController/res/drawable-xhdpi/ic_launcher.png b/apps/SdkController/res/drawable-xhdpi/ic_launcher.png Binary files differdeleted file mode 100755 index 71c6d760f..000000000 --- a/apps/SdkController/res/drawable-xhdpi/ic_launcher.png +++ /dev/null diff --git a/apps/SdkController/res/layout-land/sensors.xml b/apps/SdkController/res/layout-land/sensors.xml deleted file mode 100755 index 1f3e2f1cd..000000000 --- a/apps/SdkController/res/layout-land/sensors.xml +++ /dev/null @@ -1,168 +0,0 @@ -<?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" - > - - <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" /> - -</LinearLayout>
\ No newline at end of file diff --git a/apps/SdkController/res/layout/main.xml b/apps/SdkController/res/layout/main.xml deleted file mode 100755 index 2e7a4bb37..000000000 --- a/apps/SdkController/res/layout/main.xml +++ /dev/null @@ -1,116 +0,0 @@ -<?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/multitouch.xml b/apps/SdkController/res/layout/multitouch.xml deleted file mode 100755 index 0aec0fbd0..000000000 --- a/apps/SdkController/res/layout/multitouch.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" > - - <com.android.tools.sdkcontroller.views.MultiTouchView - android:id="@+id/imageView" - android:layout_width="fill_parent" - android:layout_height="fill_parent" /> - - <!-- 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_alignParentTop="true" - 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:layout_below="@+id/textStatus" - android:gravity="center_horizontal" - android:background="#F00F" - android:padding="8dp" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textColor="#FFF0" /> - -</RelativeLayout> diff --git a/apps/SdkController/res/layout/sensor_row.xml b/apps/SdkController/res/layout/sensor_row.xml deleted file mode 100755 index 16ffd4272..000000000 --- a/apps/SdkController/res/layout/sensor_row.xml +++ /dev/null @@ -1,42 +0,0 @@ -<?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 deleted file mode 100755 index afdab02a3..000000000 --- a/apps/SdkController/res/layout/sensors.xml +++ /dev/null @@ -1,130 +0,0 @@ -<?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" - > - - <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" /> - -</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 deleted file mode 100755 index 3d3860e87..000000000 --- a/apps/SdkController/res/values-v11/styles_v11.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?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 deleted file mode 100755 index e4e1dbb17..000000000 --- a/apps/SdkController/res/values/strings.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?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 deleted file mode 100755 index 67c7278fa..000000000 --- a/apps/SdkController/res/values/styles.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?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/BaseBindingActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/BaseBindingActivity.java deleted file mode 100755 index ab5306ddc..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/BaseBindingActivity.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.IBinder; -import android.util.Log; - -import com.android.tools.sdkcontroller.service.ControllerService; -import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder; -import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener; - -/** - * Base activity class that knows how to bind and unbind from the - * {@link ControllerService}. - */ -public abstract class BaseBindingActivity extends Activity { - - public static String TAG = BaseBindingActivity.class.getSimpleName(); - private static boolean DEBUG = true; - private ServiceConnection mServiceConnection; - private ControllerBinder mServiceBinder; - - /** - * Returns the binder. Activities can use that to query the controller service. - * @return An existing {@link ControllerBinder}. - * The binder is only valid between calls {@link #onServiceConnected()} and - * {@link #onServiceDisconnected()}. Returns null when not valid. - */ - public ControllerBinder getServiceBinder() { - return mServiceBinder; - } - - /** - * Called when the activity resumes. - * This automatically binds to the service, starting it as needed. - * <p/> - * Since on resume we automatically bind to the service, the {@link ServiceConnection} - * will is restored and {@link #onServiceConnected()} is called as necessary. - * Derived classes that need to initialize anything that is related to the service - * (e.g. getting their handler) should thus do so in {@link #onServiceConnected()} and - * <em>not</em> in {@link #onResume()} -- since binding to the service is asynchronous - * there is <em>no</em> guarantee that {@link #getServiceBinder()} returns non-null - * when this call finishes. - */ - @Override - protected void onResume() { - super.onResume(); - bindToService(); - } - - /** - * Called when the activity is paused. - * This automatically unbinds from the service but does not stop it. - */ - @Override - protected void onPause() { - super.onPause(); - unbindFromService(); - } - - // ---------- - - /** - * Called when binding to the service to get the activity's {@link ControllerListener}. - * @return A new non-null {@link ControllerListener}. - */ - protected abstract ControllerListener createControllerListener(); - - /** - * Called by the service once the activity is connected (bound) to it. - * <p/> - * When this is called, {@link #getServiceBinder()} returns a non-null binder that - * can be used by the activity to control the service. - */ - protected abstract void onServiceConnected(); - - /** - * Called by the service when it is forcibly disconnected OR when we know - * we're unbinding the service. - * <p/> - * When this is called, {@link #getServiceBinder()} returns a null binder and - * the activity should stop using that binder and remove any reference to it. - */ - protected abstract void onServiceDisconnected(); - - /** - * Starts the service and binds to it. - */ - protected void bindToService() { - if (mServiceConnection == null) { - final ControllerListener listener = createControllerListener(); - - mServiceConnection = new ServiceConnection() { - /** - * Called when the service is connected. - * Allows us to retrieve the binder to talk to the service. - */ - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - if (DEBUG) Log.d(TAG, "Activity connected to service"); - mServiceBinder = (ControllerBinder) service; - mServiceBinder.addControllerListener(listener); - BaseBindingActivity.this.onServiceConnected(); - } - - /** - * Called when the service got disconnected, e.g. because it crashed. - * This is <em>not</em> called when we unbind from the service. - */ - @Override - public void onServiceDisconnected(ComponentName name) { - if (DEBUG) Log.d(TAG, "Activity disconnected from service"); - mServiceBinder = null; - BaseBindingActivity.this.onServiceDisconnected(); - } - }; - } - - // Start service so that it doesn't stop when we unbind - if (DEBUG) Log.d(TAG, "start requested & bind service"); - Intent service = new Intent(this, ControllerService.class); - startService(service); - bindService(service, - mServiceConnection, - Context.BIND_AUTO_CREATE); - } - - /** - * Unbinds from the service but does not actually stop the service. - * This lets us have it run in the background even if this isn't the active activity. - */ - protected void unbindFromService() { - if (mServiceConnection != null) { - if (DEBUG) Log.d(TAG, "unbind service"); - mServiceConnection.onServiceDisconnected(null /*name*/); - unbindService(mServiceConnection); - mServiceConnection = null; - } - } -}
\ No newline at end of file diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MainActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MainActivity.java deleted file mode 100755 index 47692454c..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MainActivity.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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 android.content.Intent; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.webkit.WebView; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.TextView; -import android.widget.ToggleButton; - -import com.android.tools.sdkcontroller.R; -import com.android.tools.sdkcontroller.service.ControllerService; -import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder; -import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener; - -/** - * Main activity. It's the entry point for the application. - * It allows the user to start/stop the service and see it's current state and errors. - * It also has buttons to start either the sensor control activity or the multitouch activity. - */ -public class MainActivity extends BaseBindingActivity { - - @SuppressWarnings("hiding") - public static String TAG = MainActivity.class.getSimpleName(); - private static boolean DEBUG = true; - private Button mBtnOpenMultitouch; - private Button mBtnOpenSensors; - private ToggleButton mBtnToggleService; - private TextView mTextError; - private TextView mTextStatus; - - /** Called when the activity is first created. */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - mTextError = (TextView) findViewById(R.id.textError); - mTextStatus = (TextView) findViewById(R.id.textStatus); - - WebView wv = (WebView) findViewById(R.id.webIntro); - wv.loadUrl("file:///android_asset/intro_help.html"); - - setupButtons(); - } - - @Override - protected void onResume() { - // BaseBindingActivity.onResume will bind to the service. - super.onResume(); - updateError(); - } - - @Override - protected void onPause() { - // BaseBindingActivity.onResume will unbind from (but not stop) the service. - super.onPause(); - } - - @Override - public void onBackPressed() { - if (DEBUG) Log.d(TAG, "onBackPressed"); - // If back is pressed, we stop the service automatically. - // It seems more intuitive that way. - stopService(); - super.onBackPressed(); - } - - // ---------- - - @Override - protected void onServiceConnected() { - updateButtons(); - } - - @Override - protected void onServiceDisconnected() { - updateButtons(); - } - - @Override - protected ControllerListener createControllerListener() { - return new MainControllerListener(); - } - - // ---------- - - private void setupButtons() { - mBtnOpenMultitouch = (Button) findViewById(R.id.btnOpenMultitouch); - mBtnOpenSensors = (Button) findViewById(R.id.btnOpenSensors); - - mBtnOpenMultitouch.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // Open the multi-touch activity. - Intent i = new Intent(MainActivity.this, MultiTouchActivity.class); - startActivity(i); - } - }); - - mBtnOpenSensors.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // Open the sensor activity. - Intent i = new Intent(MainActivity.this, SensorActivity.class); - startActivity(i); - } - }); - - mBtnToggleService = (ToggleButton) findViewById(R.id.toggleService); - - // set initial state - updateButtons(); - - mBtnToggleService.setOnCheckedChangeListener(new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (isChecked) { - bindToService(); - updateButtons(); - } else { - stopService(); - updateButtons(); - } - } - }); - - } - - private void updateButtons() { - boolean running = ControllerService.isServiceIsRunning(); - mBtnOpenMultitouch.setEnabled(running); - mBtnOpenSensors.setEnabled(running); - mBtnToggleService.setChecked(running); - } - - /** - * Unbind and then actually stops the service. - */ - private void stopService() { - Intent service = new Intent(this, ControllerService.class); - unbindFromService(); - if (DEBUG) Log.d(TAG, "stop service requested"); - stopService(service); - } - - private class MainControllerListener 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() { - updateStatus(); - } - }); - } - } - - 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 updateStatus() { - ControllerBinder binder = getServiceBinder(); - boolean connected = binder == null ? false : binder.isEmuConnected(); - mTextStatus.setText( - getText(connected ? R.string.main_service_status_connected - : R.string.main_service_status_disconnected)); - - } -}
\ No newline at end of file diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java b/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java deleted file mode 100755 index faba8828f..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/MultiTouchActivity.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * 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 deleted file mode 100755 index 61c308152..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/activities/SensorActivity.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * 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 deleted file mode 100755 index ad00e921e..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/MultiTouchChannel.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 deleted file mode 100755 index ffc2fd03a..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/handlers/SensorChannel.java +++ /dev/null @@ -1,675 +0,0 @@ -/* - * 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/lib/Channel.java b/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Channel.java deleted file mode 100644 index 639f4cfd4..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Channel.java +++ /dev/null @@ -1,795 +0,0 @@ -/* - * 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.lib; - -import android.os.Message; -import android.util.Log; - -import com.android.tools.sdkcontroller.service.ControllerService; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Encapsulates basics of a connection with the emulator. - * This class must be used as a base class for all the channelss that provide - * particular type of emulation (such as sensors, multi-touch, etc.) - * <p/> - * Essentially, Channel is an implementation of a particular emulated functionality, - * that defines logical format of the data transferred between the emulator and - * SDK controller. For instance, "sensors" is a channel that emulates sensors, - * and transfers sensor value changes from the device to the emulator. "Multi-touch" - * is a channel that supports multi-touch emulation, and transfers multi-touch - * events to the emulator, while receiving frame buffer updates from the emulator. - * <p/> - * Besides connection with the emulator, each channel may contain one or more UI - * components associated with it. This class provides some basics for UI support, - * including: - * <p/> - * - Providing a way to register / unregister a UI component with the channel. - * <p/> - * - Implementing posting of messages to emulator in opposite to direct message - * sent. This is due to requirement that UI threads are prohibited from doing - * network I/O. - */ -public abstract class Channel { - - /** - * Encapsulates a message posted to be sent to the emulator from a worker - * thread. This class is used to describe a message that is posted in UI - * thread, and then picked up in the worker thread. - */ - private class SdkControllerMessage { - /** Message type. */ - private int mMessageType; - /** Message data (can be null). */ - private byte[] mMessage; - /** Message data size */ - private int mMessageSize; - - /** - * Construct message from an array. - * - * @param type Message type. - * @param message Message data. Message data size is defined by size of - * the array. - */ - public SdkControllerMessage(int type, byte[] message) { - mMessageType = type; - mMessage = message; - mMessageSize = (message != null) ? message.length : 0; - } - - /** - * Construct message from a ByteBuffer. - * - * @param type Message type. - * @param message Message data. Message data size is defined by - * position() property of the ByteBuffer. - */ - public SdkControllerMessage(int type, ByteBuffer message) { - mMessageType = type; - if (message != null) { - mMessage = message.array(); - mMessageSize = message.position(); - } else { - mMessage = null; - mMessageSize = 0; - } - } - - /** - * Gets message type. - - * - * @return Message type. - */ - public int getMessageType() { - return mMessageType; - } - - /** - * Gets message buffer. - * - * @return Message buffer. - */ - public byte[] getMessage() { - return mMessage; - } - - /** - * Gets message buffer size. - * - * @return Message buffer size. - */ - public int getMessageSize() { - return mMessageSize; - } - } // SdkControllerMessage - - /* - * Names for currently implemented SDK controller channels. - */ - - /** Name for a channel that handles sensors emulation */ - public static final String SENSOR_CHANNEL = "sensors"; - /** Name for a channel that handles multi-touch emulation */ - public static final String MULTITOUCH_CHANNEL = "multi-touch"; - - /* - * Types of messages internally used by Channel class. - */ - - /** Service-side emulator is connected. */ - private static final int MSG_CONNECTED = -1; - /** Service-side emulator is disconnected. */ - private static final int MSG_DISCONNECTED = -2; - /** Service-side emulator is enabled. */ - private static final int MSG_ENABLED = -3; - /** Service-side emulator is disabled. */ - private static final int MSG_DISABLED = -4; - - /** Tag for logging messages. */ - private static final String TAG = "SdkControllerChannel"; - /** Controls debug log. */ - private static final boolean DEBUG = false; - - /** Service that has created this object. */ - protected ControllerService mService; - - /* - * Socket stuff. - */ - - /** Socket to use to to communicate with the emulator. */ - private Socket mSocket = null; - /** Channel name ("sensors", "multi-touch", etc.) */ - private String mChannelName; - /** Endianness of data transferred in this channel. */ - private ByteOrder mEndian; - - /* - * Message posting support. - */ - - /** Total number of messages posted in this channel */ - private final AtomicInteger mMsgCount = new AtomicInteger(0); - /** Flags whether or not message thread is running. */ - private volatile boolean mRunMsgQueue = true; - /** Queue of messages pending transmission. */ - private final BlockingQueue<SdkControllerMessage> - mMsgQueue = new LinkedBlockingQueue<SdkControllerMessage>(); - /** Message thread */ - private final Thread mMsgThread; - - /* - * UI support. - */ - - /** Lists UI handlers attached to this channel. */ - private final List<android.os.Handler> mUiHandlers = new ArrayList<android.os.Handler>(); - - /* - * Abstract methods. - */ - - /** - * This method is invoked when this channel is fully connected with its - * counterpart in the emulator. - */ - public abstract void onEmulatorConnected(); - - /** - * This method is invoked when this channel loses connection with its - * counterpart in the emulator. - */ - public abstract void onEmulatorDisconnected(); - - /** - * A message has been received from the emulator. - * - * @param msg_type Message type. - * @param msg_data Message data. Message data size is defined by the length - * of the array wrapped by the ByteBuffer. - */ - public abstract void onEmulatorMessage(int msg_type, ByteBuffer msg_data); - - /** - * 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. Query data size is defined by the length of - * the array wrapped by the ByteBuffer. - */ - public abstract void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data); - - /* - * Channel implementation. - */ - - /** - * Constructs Channel instance. - * - * @param name Channel name. - */ - public Channel(ControllerService service, String name) { - mService = service; - mChannelName = name; - // Start the worker thread for posted messages. - mMsgThread = new Thread(new Runnable() { - @Override - public void run() { - if (DEBUG) Log.d(TAG, "MsgThread.started-" + mChannelName); - while (mRunMsgQueue) { - try { - SdkControllerMessage msg = mMsgQueue.take(); - if (msg != null) { - sendMessage( - msg.getMessageType(), msg.getMessage(), msg.getMessageSize()); - mMsgCount.incrementAndGet(); - } - } catch (InterruptedException e) { - Log.e(TAG, "MsgThread-" + mChannelName, e); - } - } - if (DEBUG) Log.d(TAG, "MsgThread.terminate-" + mChannelName); - } - }, "MsgThread-" + name); - mMsgThread.start(); - if (DEBUG) Log.d(TAG, "Channel is constructed for " + mChannelName); - } - - /** - * Gets name for this channel. - * - * @return Emulator name. - */ - public String getChannelName() { - return mChannelName; - } - - /** - * Gets endianness for this channel. - * - * @return Channel endianness. - */ - public ByteOrder getEndian() { - return mEndian; - } - - /** - * Gets number of messages sent via postMessage method. - * - * @return Number of messages sent via postMessage method. - */ - public int getMsgSentCount() { - return mMsgCount.get(); - } - - /** - * Checks if this channel is connected with the emulator. - * - * @return true if this channel is connected with the emulator, or false if it is - * not connected. - */ - public boolean isConnected() { - // Use local copy of the socket, ensuring it's not going to NULL while - // we're working with it. If it gets closed, while we're in the middle - // of data transfer - it's OK, since it will produce an exception, and - // the caller will gracefully handle it. - // - // Same technique is used everywhere in this class where mSocket member - // is touched. - Socket socket = mSocket; - return socket != null && socket.isConnected(); - } - - /** - * Establishes connection with the emulator. This method is called by Connection - * object when emulator successfully connects to this channel, or this channel - * gets registered, and there is a pending socket connection for it. - * - * @param socket Channel connection socket. - */ - public void connect(Socket socket) { - mSocket = socket; - mEndian = socket.getEndian(); - Logv("Channel " + mChannelName + " is now connected with the emulator."); - // Notify the emulator that connection is established. - sendMessage(MSG_CONNECTED, (byte[]) null); - - // Let the derived class know that emulator is connected, and start the - // I/O loop in which we will receive data from the emulator. Note that - // we start the loop after onEmulatorConnected call, since we don't want - // to start dispatching messages before the derived class could set - // itself up for receiving them. - onEmulatorConnected(); - new Thread(new Runnable() { - @Override - public void run() { - runIOLooper(); - } - }, "ChannelIoLoop").start(); - mService.notifyStatusChanged(); - } - - /** - * Disconnects this channel from the emulator. - * - * @return true if this channel has been disconnected in this call, or false if - * channel has been already disconnected when this method has been called. - */ - public boolean disconnect() { - // This is the only place in this class where we will null the - // socket object. Since this method can be called concurrently from - // different threads, lets do this under the lock. - Socket socket; - synchronized (this) { - socket = mSocket; - mSocket = null; - } - if (socket != null) { - // Notify the emulator about channel disconnection before we close - // the communication socket. - try { - sendMessage(socket, MSG_DISCONNECTED, null, 0); - } catch (IOException e) { - // Ignore I/O exception at this point. We don't care about - // it, since the socket is being closed anyways. - } - // This will eventually stop I/O looper thread. - socket.close(); - mService.notifyStatusChanged(); - } - return socket != null; - } - - /** - * Enables the emulation. Typically, this method is called for channels that are - * dependent on UI to handle the emulation. For instance, multi-touch emulation is - * disabled until at least one UI component is attached to the channel. So, for - * multi-touch emulation this method is called when UI gets attached to the channel. - */ - public void enable() { - postMessage(MSG_ENABLED, (byte[]) null); - mService.notifyStatusChanged(); - } - - /** - * Disables the emulation. Just the opposite to enable(). For multi-touch this - * method is called when UI detaches from the channel. - */ - public void disable() { - postMessage(MSG_DISABLED, (byte[]) null); - mService.notifyStatusChanged(); - } - - /** - * Sends message to the emulator. - * - * @param socket Socket to send the message to. - * @param msg_type Message type. - * @param msg Message data to send. - * @param len Byte size of message data. - * @throws IOException - */ - private void sendMessage(Socket socket, int msg_type, byte[] msg, int len) - throws IOException { - // In async environment we must have message header and message data in - // one block to prevent messages from other threads getting between the - // header and the data. So, we can't sent header, and then the data. We - // must combine them in one data block instead. - ByteBuffer bb = ByteBuffer.allocate(ProtocolConstants.MESSAGE_HEADER_SIZE + len); - bb.order(mEndian); - - // Initialize message header. - bb.putInt(ProtocolConstants.PACKET_SIGNATURE); - bb.putInt(ProtocolConstants.MESSAGE_HEADER_SIZE + len); - bb.putInt(ProtocolConstants.PACKET_TYPE_MESSAGE); - bb.putInt(msg_type); - - // Save message data (if there is any). - if (len != 0) { - bb.put(msg, 0, len); - } - - socket.send(bb.array()); - } - - /** - * Sends message to the emulator. - * - * @param msg_type Message type. - * @param msg Message data to send. Message size is defined by the size of - * the array. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendMessage(int msg_type, byte[] msg, int msg_len) { - try { - Socket socket = mSocket; - if (socket != null) { - sendMessage(socket, msg_type, msg, msg_len); - return true; - } else { - Logw("sendMessage is called on disconnected Channel " + mChannelName); - } - } catch (IOException e) { - Loge("Exception " + e + " in sendMessage for Channel " + mChannelName); - onIoFailure(); - } - return false; - } - - /** - * Sends message to the emulator. - * - * @param msg_type Message type. - * @param msg Message data to send. Message size is defined by the size of - * the array. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendMessage(int msg_type, byte[] msg) { - try { - Socket socket = mSocket; - if (socket != null) { - if (msg != null) { - sendMessage(socket, msg_type, msg, msg.length); - } else { - sendMessage(socket, msg_type, null, 0); - } - return true; - } else { - Logw("sendMessage is called on disconnected Channel " + mChannelName); - } - } catch (IOException e) { - Loge("Exception " + e + " in sendMessage for Channel " + mChannelName); - onIoFailure(); - } - return false; - } - - /** - * Sends message to the emulator. - * - * @param msg_type Message type. - * @param msg Message data to send. Message size is defined by the - * position() property of the ByteBuffer. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendMessage(int msg_type, ByteBuffer msg) { - try { - Socket socket = mSocket; - if (socket != null) { - if (msg != null) { - sendMessage(socket, msg_type, msg.array(), msg.position()); - } else { - sendMessage(socket, msg_type, null, 0); - } - return true; - } else { - Logw("sendMessage is called on disconnected Channel " + mChannelName); - } - } catch (IOException e) { - Loge("Exception " + e + " in sendMessage for Channel " + mChannelName); - onIoFailure(); - } - return false; - } - - /** - * Posts message to the emulator. - * - * @param msg_type Message type. - * @param msg Message data to post. Message size is defined by the size of - * the array. - */ - public void postMessage(int msg_type, byte[] msg) { - try { - mMsgQueue.put(new SdkControllerMessage(msg_type, msg)); - } catch (InterruptedException e) { - Log.e(TAG, "mMessageQueue.put", e); - } - } - - /** - * Posts message to the emulator. - * - * @param msg_type Message type. - * @param msg Message data to post. Message size is defined by the - * position() property of the ByteBuffer. - */ - public void postMessage(int msg_type, ByteBuffer msg) { - try { - mMsgQueue.put(new SdkControllerMessage(msg_type, msg)); - } catch (InterruptedException e) { - Log.e(TAG, "mMessageQueue.put", e); - } - } - - /** - * Sends query response to the emulator. - * - * @param query_id Query identifier. - * @param qresp Response to the query. - * @param len Byte size of query response data. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendQueryResponse(int query_id, byte[] qresp, int len) { - // Just like with messages, we must combine header and data in a single - // transmitting block. - ByteBuffer bb = ByteBuffer.allocate(ProtocolConstants.QUERY_RESP_HEADER_SIZE + len); - bb.order(mEndian); - - // Initialize response header. - bb.putInt(ProtocolConstants.PACKET_SIGNATURE); - bb.putInt(ProtocolConstants.QUERY_RESP_HEADER_SIZE + len); - bb.putInt(ProtocolConstants.PACKET_TYPE_QUERY_RESPONSE); - bb.putInt(query_id); - - // Save response data (if there is any). - if (qresp != null && len != 0) { - bb.put(qresp, 0, len); - } - - // Send the response. - try { - Socket socket = mSocket; - if (socket != null) { - socket.send(bb.array()); - return true; - } else { - Logw("sendQueryResponse is called on disconnected Channel " - + mChannelName); - } - } catch (IOException e) { - Loge("Exception " + e + " in sendQueryResponse for Channel " + mChannelName); - onIoFailure(); - } - return false; - } - - /** - * Sends query response to the emulator. - * - * @param query_id Query identifier. - * @param qresp Response to the query. Query response size is defined by the - * size of the array. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendQueryResponse(int query_id, byte[] qresp) { - return (qresp != null) ? sendQueryResponse(query_id, qresp, qresp.length) : - sendQueryResponse(query_id, null, 0); - } - - /** - * Sends query response to the emulator. - * - * @param query_id Query identifier. - * @param qresp Response to the query. Query response size is defined by the - * position() property of the ByteBuffer. - * @return true on success, or false if data transmission has failed. - */ - public boolean sendQueryResponse(int query_id, ByteBuffer qresp) { - return (qresp != null) ? sendQueryResponse(query_id, qresp.array(), qresp.position()) : - sendQueryResponse(query_id, null, 0); - } - - /** - * Handles an I/O failure occurred in the channel. - */ - private void onIoFailure() { - // All I/O failures cause disconnection. - if (disconnect()) { - // Success of disconnect() indicates that I/O failure is not the - // result of a disconnection request, but is in deed an I/O - // failure. Report lost connection to the derived class. - Loge("Connection with the emulator has been lost in Channel " + mChannelName); - onEmulatorDisconnected(); - } - } - - /** - * Loops on the local socket, handling connection attempts. - */ - private void runIOLooper() { - if (DEBUG) Log.d(TAG, "In I/O looper for Channel " + mChannelName); - // Initialize byte buffer large enough to receive packet header. - ByteBuffer header = ByteBuffer.allocate(ProtocolConstants.PACKET_HEADER_SIZE); - header.order(mEndian); - try { - // Since disconnection (which will null the mSocket) can be - // requested from outside of this thread, it's simpler just to make - // a copy of mSocket here, and work with that copy. Otherwise we - // will have to go through a complex synchronization algorithm that - // would decrease performance on normal runs. If socket gets closed - // while we're in the middle of transfer, an exception will occur, - // which we will catch and handle properly. - Socket socket = mSocket; - while (socket != null) { - // Reset header position. - header.position(0); - // This will receive total packet size + packet type. - socket.receive(header.array()); - // First - signature. - final int signature = header.getInt(); - assert signature == ProtocolConstants.PACKET_SIGNATURE; - // Next - packet size (including header). - int remains = header.getInt() - ProtocolConstants.PACKET_HEADER_SIZE; - // After the size comes packet type. - final int packet_type = header.getInt(); - - // Get the remainder of the data, and dispatch the packet to - // an appropriate handler. - switch (packet_type) { - case ProtocolConstants.PACKET_TYPE_MESSAGE: - // Read message header (one int: message type). - final int ext = ProtocolConstants.MESSAGE_HEADER_SIZE - ProtocolConstants.PACKET_HEADER_SIZE; - header.position(0); - socket.receive(header.array(), ext); - final int msg_type = header.getInt(); - - // Read message data. - remains -= ext; - final ByteBuffer msg_data = ByteBuffer.allocate(remains); - msg_data.order(mEndian); - socket.receive(msg_data.array()); - - // Dispatch message for handling. - onEmulatorMessage(msg_type, msg_data); - break; - - case ProtocolConstants.PACKET_TYPE_QUERY: - // Read query ID and query type. - final int extq = ProtocolConstants.QUERY_HEADER_SIZE - ProtocolConstants.PACKET_HEADER_SIZE; - header.position(0); - socket.receive(header.array(), extq); - final int query_id = header.getInt(); - final int query_type = header.getInt(); - - // Read query data. - remains -= extq; - final ByteBuffer query_data = ByteBuffer.allocate(remains); - query_data.order(mEndian); - socket.receive(query_data.array()); - - // Dispatch query for handling. - onEmulatorQuery(query_id, query_type, query_data); - break; - - default: - // Unknown packet type. Just discard the remainder - // of the packet - Loge("Unknown packet type " + packet_type + " in Channel " - + mChannelName); - final byte[] discard_data = new byte[remains]; - socket.receive(discard_data); - break; - } - socket = mSocket; - } - } catch (IOException e) { - Loge("Exception " + e + " in I/O looper for Channel " + mChannelName); - onIoFailure(); - } - if (DEBUG) Log.d(TAG, "Exiting I/O looper for Channel " + mChannelName); - } - - /** - * Indicates any UI handler is currently registered with the channel. If no UI - * is displaying the channel's state, maybe the channel can skip UI related tasks. - * - * @return True if there's at least one UI handler registered. - */ - public boolean hasUiHandler() { - return !mUiHandlers.isEmpty(); - } - - /** - * Registers a new UI handler. - * - * @param uiHandler A non-null UI handler to register. Ignored if the UI - * handler is null or already registered. - */ - public void addUiHandler(android.os.Handler uiHandler) { - assert uiHandler != null; - if (uiHandler != null) { - if (!mUiHandlers.contains(uiHandler)) { - mUiHandlers.add(uiHandler); - } - } - } - - /** - * Unregisters an UI handler. - * - * @param uiHandler A non-null UI listener to unregister. Ignored if the - * listener is null or already registered. - */ - public void removeUiHandler(android.os.Handler uiHandler) { - assert uiHandler != null; - mUiHandlers.remove(uiHandler); - } - - /** - * Protected method to be used by handlers to send an event to all UI - * handlers. - * - * @param event An integer event code with no specific parameters. To be - * defined by the handler itself. - */ - protected void notifyUiHandlers(int event) { - for (android.os.Handler uiHandler : mUiHandlers) { - uiHandler.sendEmptyMessage(event); - } - } - - /** - * Protected method to be used by handlers to send an event to all UI - * handlers. - * - * @param msg An event with parameters. To be defined by the handler itself. - */ - protected void notifyUiHandlers(Message msg) { - for (android.os.Handler uiHandler : mUiHandlers) { - uiHandler.sendMessage(msg); - } - } - - /** - * A helper routine that expands ByteBuffer to contain given number of extra - * bytes. - * - * @param buff Buffer to expand. - * @param extra Number of bytes that are required to be available in the - * buffer after current position() - * @return ByteBuffer, containing required number of available bytes. - */ - public ByteBuffer ExpandIf(ByteBuffer buff, int extra) { - if (extra <= buff.remaining()) { - return buff; - } - ByteBuffer ret = ByteBuffer.allocate(buff.position() + extra); - ret.order(buff.order()); - ret.put(buff.array(), 0, buff.position()); - return ret; - } - - /*************************************************************************** - * Logging wrappers - **************************************************************************/ - - private void Loge(String log) { - mService.addError(log); - Log.e(TAG, log); - } - - private void Logw(String log) { - Log.w(TAG, log); - } - - private void Logv(String log) { - Log.v(TAG, log); - } -} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Connection.java b/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Connection.java deleted file mode 100644 index cb5086905..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Connection.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * 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.lib; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; - -import android.util.Log; -import android.net.LocalServerSocket; -import android.net.LocalSocket; - -import com.android.tools.sdkcontroller.lib.Channel; -import com.android.tools.sdkcontroller.service.ControllerService; - -/** - * Encapsulates a connection between SdkController service and the emulator. On - * the device side, the connection is bound to the UNIX-domain socket named - * 'android.sdk.controller'. On the emulator side the connection is established - * via TCP port that is used to forward I/O traffic on the host machine to - * 'android.sdk.controller' socket on the device. Typically, the port forwarding - * can be enabled using adb command: - * <p/> - * 'adb forward tcp:<TCP port number> localabstract:android.sdk.controller' - * <p/> - * The way communication between the emulator and SDK controller service works - * is as follows: - * <p/> - * 1. Both sides, emulator and the service have components that implement a particular - * type of emulation. For instance, AndroidSensorsPort in the emulator, and - * SensorChannel in the application implement sensors emulation. - * Emulation channels are identified by unique names. For instance, sensor emulation - * is done via "sensors" channel, multi-touch emulation is done via "multi-touch" - * channel, etc. - * <p/> - * 2. Channels are connected to emulator via separate socket instance (though all - * of the connections share the same socket address). - * <p/> - * 3. Connection is initiated by the emulator side, while the service provides - * its side (a channel) that implement functionality and exchange protocol required - * by the requested type of emulation. - * <p/> - * Given that, the main responsibilities of this class are: - * <p/> - * 1. Bind to "android.sdk.controller" socket, listening to emulator connections. - * <p/> - * 2. Maintain a list of service-side channels registered by the application. - * <p/> - * 3. Bind emulator connection with service-side channel via port name, provided by - * the emulator. - * <p/> - * 4. Monitor connection state with the emulator, and automatically restore the - * connection once it is lost. - */ -public class Connection { - /** UNIX-domain name reserved for SDK controller. */ - public static final String SDK_CONTROLLER_PORT = "android.sdk.controller"; - /** Tag for logging messages. */ - private static final String TAG = "SdkControllerConnection"; - /** Controls debug logging */ - private static final boolean DEBUG = false; - - /** Server socket used to listen to emulator connections. */ - private LocalServerSocket mServerSocket = null; - /** Service that has created this object. */ - private ControllerService mService; - /** - * List of connected emulator sockets, pending for a channel to be registered. - * <p/> - * Emulator may connect to SDK controller before the app registers a channel - * for that connection. In this case (when app-side channel is not registered - * with this class) we will keep emulator connection in this list, pending - * for the app-side channel to register. - */ - private List<Socket> mPendingSockets = new ArrayList<Socket>(); - /** - * List of registered app-side channels. - * <p/> - * Channels that are kept in this list may be disconnected from (or pending - * connection with) the emulator, or they may be connected with the - * emulator. - */ - private List<Channel> mChannels = new ArrayList<Channel>(); - - /** - * Constructs Connection instance. - */ - public Connection(ControllerService service) { - mService = service; - if (DEBUG) Log.d(TAG, "SdkControllerConnection is constructed."); - } - - /** - * Binds to the socket, and starts the listening thread. - */ - public void connect() { - if (DEBUG) Log.d(TAG, "SdkControllerConnection is connecting..."); - // Start connection listener. - new Thread(new Runnable() { - @Override - public void run() { - runIOLooper(); - } - }, "SdkControllerConnectionIoLoop").start(); - } - - /** - * Stops the listener, and closes the socket. - * - * @return true if connection has been stopped in this call, or false if it - * has been already stopped when this method has been called. - */ - public boolean disconnect() { - // This is the only place in this class where we will null the - // socket object. Since this method can be called concurrently from - // different threads, lets do this under the lock. - LocalServerSocket socket; - synchronized (this) { - socket = mServerSocket; - mServerSocket = null; - } - if (socket != null) { - if (DEBUG) Log.d(TAG, "SdkControllerConnection is stopping I/O looper..."); - // Stop accepting new connections. - wakeIOLooper(socket); - try { - socket.close(); - } catch (Exception e) { - } - - // Close all the pending sockets, and clear pending socket list. - if (DEBUG) Log.d(TAG, "SdkControllerConnection is closing pending sockets..."); - for (Socket pending_socket : mPendingSockets) { - pending_socket.close(); - } - mPendingSockets.clear(); - - // Disconnect all the emualtors. - if (DEBUG) Log.d(TAG, "SdkControllerConnection is disconnecting channels..."); - for (Channel channel : mChannels) { - if (channel.disconnect()) { - channel.onEmulatorDisconnected(); - } - } - if (DEBUG) Log.d(TAG, "SdkControllerConnection is disconnected."); - } - return socket != null; - } - - /** - * Registers SDK controller channel. - * - * @param channel SDK controller emulator to register. - * @return true if channel has been registered successfully, or false if channel - * with the same name is already registered. - */ - public boolean registerChannel(Channel channel) { - for (Channel check_channel : mChannels) { - if (check_channel.getChannelName().equals(channel.getChannelName())) { - Loge("Registering a duplicate Channel " + channel.getChannelName()); - return false; - } - } - if (DEBUG) Log.d(TAG, "Registering Channel " + channel.getChannelName()); - mChannels.add(channel); - - // Lets see if there is a pending socket for this channel. - for (Socket pending_socket : mPendingSockets) { - if (pending_socket.getChannelName().equals(channel.getChannelName())) { - // Remove the socket from the pending list, and connect the registered channel with it. - if (DEBUG) Log.d(TAG, "Found pending Socket for registering Channel " - + channel.getChannelName()); - mPendingSockets.remove(pending_socket); - channel.connect(pending_socket); - } - } - return true; - } - - /** - * Checks if at least one socket connection exists with channel. - * - * @return true if at least one socket connection exists with channel. - */ - public boolean isEmulatorConnected() { - for (Channel channel : mChannels) { - if (channel.isConnected()) { - return true; - } - } - return !mPendingSockets.isEmpty(); - } - - /** - * Gets Channel instance for the given channel name. - * - * @param name Channel name to get Channel instance for. - * @return Channel instance for the given channel name, or NULL if no - * channel has been registered for that name. - */ - public Channel getChannel(String name) { - for (Channel channel : mChannels) { - if (channel.getChannelName().equals(name)) { - return channel; - } - } - return null; - } - - /** - * Gets connected emulator socket that is pending for service-side channel - * registration. - * - * @param name Channel name to lookup Socket for. - * @return Connected emulator socket that is pending for service-side channel - * registration, or null if no socket is pending for service-size - * channel registration. - */ - private Socket getPendingSocket(String name) { - for (Socket socket : mPendingSockets) { - if (socket.getChannelName().equals(name)) { - return socket; - } - } - return null; - } - - /** - * Wakes I/O looper waiting on connection with the emulator. - * - * @param socket Server socket waiting on connection. - */ - private void wakeIOLooper(LocalServerSocket socket) { - // We wake the looper by connecting to the socket. - LocalSocket waker = new LocalSocket(); - try { - waker.connect(socket.getLocalSocketAddress()); - } catch (IOException e) { - Loge("Exception " + e + " in SdkControllerConnection while waking up the I/O looper."); - } - } - - /** - * Loops on the local socket, handling emulator connection attempts. - */ - private void runIOLooper() { - if (DEBUG) Log.d(TAG, "In SdkControllerConnection I/O looper."); - do { - try { - // Create non-blocking server socket that would listen for connections, - // and bind it to the given port on the local host. - mServerSocket = new LocalServerSocket(SDK_CONTROLLER_PORT); - LocalServerSocket socket = mServerSocket; - while (socket != null) { - final LocalSocket sk = socket.accept(); - if (mServerSocket != null) { - onAccept(sk); - } else { - break; - } - socket = mServerSocket; - } - } catch (IOException e) { - Loge("Exception " + e + "SdkControllerConnection I/O looper."); - } - if (DEBUG) Log.d(TAG, "Exiting SdkControllerConnection I/O looper."); - - // If we're exiting the internal loop for reasons other than an explicit - // disconnect request, we should reconnect again. - } while (disconnect()); - } - - /** - * Accepts new connection from the emulator. - * - * @param sock Connecting socket. - * @throws IOException - */ - private void onAccept(LocalSocket sock) throws IOException { - final ByteBuffer handshake = ByteBuffer.allocate(ProtocolConstants.QUERY_HEADER_SIZE); - - // By protocol, first byte received from newly connected emulator socket - // indicates host endianness. - Socket.receive(sock, handshake.array(), 1); - final ByteOrder endian = (handshake.getChar() == 0) ? ByteOrder.LITTLE_ENDIAN : - ByteOrder.BIG_ENDIAN; - handshake.order(endian); - - // Right after that follows the handshake query header. - handshake.position(0); - Socket.receive(sock, handshake.array(), handshake.array().length); - - // First int - signature - final int signature = handshake.getInt(); - assert signature == ProtocolConstants.PACKET_SIGNATURE; - // Second int - total query size (including fixed query header) - final int remains = handshake.getInt() - ProtocolConstants.QUERY_HEADER_SIZE; - // After that - header type (which must be SDKCTL_PACKET_TYPE_QUERY) - final int msg_type = handshake.getInt(); - assert msg_type == ProtocolConstants.PACKET_TYPE_QUERY; - // After that - query ID. - final int query_id = handshake.getInt(); - // And finally, query type (which must be ProtocolConstants.QUERY_HANDSHAKE for - // handshake query) - final int query_type = handshake.getInt(); - assert query_type == ProtocolConstants.QUERY_HANDSHAKE; - // Verify that received is a query. - if (msg_type != ProtocolConstants.PACKET_TYPE_QUERY) { - // Message type is not a query. Lets read and discard the remainder - // of the message. - if (remains > 0) { - Loge("Unexpected handshake message type: " + msg_type); - byte[] discard = new byte[remains]; - Socket.receive(sock, discard, discard.length); - } - return; - } - - // Receive query data. - final byte[] name_array = new byte[remains]; - Socket.receive(sock, name_array, name_array.length); - - // Prepare response header. - handshake.position(0); - handshake.putInt(ProtocolConstants.PACKET_SIGNATURE); - // Handshake reply is just one int. - handshake.putInt(ProtocolConstants.QUERY_RESP_HEADER_SIZE + 4); - handshake.putInt(ProtocolConstants.PACKET_TYPE_QUERY_RESPONSE); - handshake.putInt(query_id); - - // Verify that received query is in deed a handshake query. - if (query_type != ProtocolConstants.QUERY_HANDSHAKE) { - // Query is not a handshake. Reply with failure. - Loge("Unexpected handshake query type: " + query_type); - handshake.putInt(ProtocolConstants.HANDSHAKE_RESP_QUERY_UNKNOWN); - sock.getOutputStream().write(handshake.array()); - return; - } - - // Handshake query data consist of SDK controller channel name. - final String channel_name = new String(name_array); - if (DEBUG) Log.d(TAG, "Handshake received for channel " + channel_name); - - // Respond to query depending on service-side channel availability - final Channel channel = getChannel(channel_name); - Socket sk = null; - - if (channel != null) { - if (channel.isConnected()) { - // This is a duplicate connection. - Loge("Duplicate connection to a connected Channel " + channel_name); - handshake.putInt(ProtocolConstants.HANDSHAKE_RESP_DUP); - } else { - // Connecting to a registered channel. - if (DEBUG) Log.d(TAG, "Emulator is connected to a registered Channel " + channel_name); - handshake.putInt(ProtocolConstants.HANDSHAKE_RESP_CONNECTED); - } - } else { - // Make sure that there are no other channel connections for this - // channel name. - if (getPendingSocket(channel_name) != null) { - // This is a duplicate. - Loge("Duplicate connection to a pending Socket " + channel_name); - handshake.putInt(ProtocolConstants.HANDSHAKE_RESP_DUP); - } else { - // Connecting to a channel that has not been registered yet. - if (DEBUG) Log.d(TAG, "Emulator is connected to a pending Socket " + channel_name); - handshake.putInt(ProtocolConstants.HANDSHAKE_RESP_NOPORT); - sk = new Socket(sock, channel_name, endian); - mPendingSockets.add(sk); - } - } - - // Send handshake reply. - sock.getOutputStream().write(handshake.array()); - - // If a disconnected channel for emulator connection has been found, - // connect it. - if (channel != null && !channel.isConnected()) { - if (DEBUG) Log.d(TAG, "Connecting Channel " + channel_name + " with emulator."); - sk = new Socket(sock, channel_name, endian); - channel.connect(sk); - } - - mService.notifyStatusChanged(); - } - - /*************************************************************************** - * Logging wrappers - **************************************************************************/ - - private void Loge(String log) { - mService.addError(log); - Log.e(TAG, log); - } -} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/ProtocolConstants.java b/apps/SdkController/src/com/android/tools/sdkcontroller/lib/ProtocolConstants.java deleted file mode 100644 index 32abf2bc0..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/ProtocolConstants.java +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2012 Google Inc. All Rights Reserved. - -package com.android.tools.sdkcontroller.lib; - -/** - * Contains declarations of constants that are tied to emulator implementation. - * These constants can be changed only simultaneously in both places. - */ -public final class ProtocolConstants { - /* - * Constants related to data transfer. - */ - - /** Signature of a packet sent via SDK controller socket ('SDKC') */ - public static final int PACKET_SIGNATURE = 0x53444B43; - - /* - * Header sizes for packets sent / received by SDK controller emulator. - */ - - /** - * 12 bytes (3 ints) for the packet header: - * <p/> - * - Signature. - * <p/> - * - Total packet size. - * <p/> - * - Packet type. - */ - public static final int PACKET_HEADER_SIZE = 12; - /** - * 16 bytes (4 ints) for the message header: - * <p/> - * - Common packet header. - * <p/> - * - Message type. - */ - public static final int MESSAGE_HEADER_SIZE = 16; - /** - * 20 bytes (5 ints) for the query header: - * <p/> - * - Common packet header. - * <p/> - * - Query ID. - * <p/> - * - Query type. - */ - public static final int QUERY_HEADER_SIZE = 20; - /** - * 16 bytes (4 ints) for the query response: - * <p/> - * - Common packet header. - * <p/> - * - Query ID. - */ - public static final int QUERY_RESP_HEADER_SIZE = 16; - - /* - * Types of packets transferred via SDK Controller channel. - */ - - /** Packet is a message. */ - public static final int PACKET_TYPE_MESSAGE = 1; - /** Packet is a query. */ - public static final int PACKET_TYPE_QUERY = 2; - /** Packet is a response to a query. */ - public static final int PACKET_TYPE_QUERY_RESPONSE = 3; - - /* - * Constants related to handshake protocol between the emulator and a channel. - */ - - /** - * Query type for a special "handshake" query. - * <p/> - * When emulator connects to SDK controller, the first thing that goes - * through the socket is a special "handshake" query that delivers channel name - * to the service. - */ - public static final int QUERY_HANDSHAKE = -1; - /** - * Handshake query response on condition that service-side channel is available - * (registered). - */ - public static final int HANDSHAKE_RESP_CONNECTED = 0; - /** - * Handshake query response on condition that service-side channel is not - * available (not registered). - */ - public static final int HANDSHAKE_RESP_NOPORT = 1; - /** - * Handshake query response on condition that there is already an existing - * emulator connection for this channel. Emulator should stop connection - * attempts in this case. - */ - public static final int HANDSHAKE_RESP_DUP = -1; - /** Response to an unknown handshake query type. */ - public static final int HANDSHAKE_RESP_QUERY_UNKNOWN = -2; - - /* - * Constants related to multi-touch emulation. - */ - - /** Received frame is JPEG image. */ - public static final int MT_FRAME_JPEG = 1; - /** Received frame is RGB565 bitmap. */ - public static final int MT_FRAME_RGB565 = 2; - /** Received frame is RGB888 bitmap. */ - public static final int MT_FRAME_RGB888 = 3; - - /** Pointer(s) moved. */ - public static final int MT_MOVE = 1; - /** First pointer down message. */ - public static final int MT_FISRT_DOWN = 2; - /** Last pointer up message. */ - public static final int MT_LAST_UP = 3; - /** Pointer down message. */ - public static final int MT_POINTER_DOWN = 4; - /** Pointer up message. */ - public static final int MT_POINTER_UP = 5; - /** Sends framebuffer update. */ - public static final int MT_FB_UPDATE = 6; - /** Frame buffer update has been received. */ - public static final int MT_FB_ACK = 7; - /** Frame buffer update has been handled. */ - public static final int MT_FB_HANDLED = 8; - /** Size of an event entry in the touch event message to the emulator. */ - public static final int MT_EVENT_ENTRY_SIZE = 16; - - /* - * Constants related to sensor emulation. - */ - - /** Query type for a query that should return the list of available sensors. */ - public static final int SENSORS_QUERY_LIST = 1; - /** Message that starts sensor emulation. */ - public static final int SENSORS_START = 1; - /** Message that stops sensor emulation. */ - public static final int SENSORS_STOP = 2; - /** Message that enables emulation of a particular sensor. */ - public static final int SENSORS_ENABLE = 3; - /** Message that disables emulation of a particular sensor. */ - public static final int SENSORS_DISABLE = 4; - /** Message that delivers sensor events to emulator. */ - public static final int SENSORS_SENSOR_EVENT = 5; -} diff --git a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Socket.java b/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Socket.java deleted file mode 100644 index 08e6b2813..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/lib/Socket.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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.lib; - -import android.net.LocalSocket; -import android.util.Log; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteOrder; -import java.nio.channels.ClosedChannelException; - -/** - * Encapsulates a connection with the emulator over a UNIX-domain socket. - */ -public class Socket { - /** UNIX-domain socket connected with the emulator. */ - private LocalSocket mSocket = null; - /** Channel name for the connection established via this socket. */ - private String mChannelName; - /** Endianness of data transferred in this connection. */ - private ByteOrder mEndian; - - /** Tag for message logging. */ - private static final String TAG = "SdkControllerSocket"; - /** Controls debug log. */ - private static boolean DEBUG = false; - - /** - * Constructs Socket instance. - * - * @param socket Socket connection with the emulator. - * @param name Channel port name for this connection. - * @param endian Endianness of data transferred in this connection. - */ - public Socket(LocalSocket socket, String name, ByteOrder endian) { - mSocket = socket; - mChannelName = name; - mEndian = endian; - if (DEBUG) Log.d(TAG, "Socket is constructed for " + mChannelName); - } - - /** - * Gets connection status of this socket. - * - * @return true if socket is connected, or false if socket is not connected. - */ - public boolean isConnected() { - return mSocket != null; - } - - /** - * Gets channel name for this socket. - * - * @return Channel name for this socket. - */ - public String getChannelName() { - return mChannelName; - } - - /** - * Gets endianness of data transferred via this socket. - * - * @return Endianness of data transferred via this socket. - */ - public ByteOrder getEndian() { - return mEndian; - } - - /** - * Sends data to the socket. - * - * @param data Data to send. Data size is defined by the length of the - * array. - * @throws IOException - */ - public void send(byte[] data) throws IOException { - // Use local copy of the socket, ensuring it's not going to NULL while - // we're working with it. If it gets closed, while we're in the middle - // of data transfer - it's OK, since it will produce an exception, and - // the caller will gracefully handle it. - // - // Same technique is used everywhere in this class where mSocket member - // is touched. - LocalSocket socket = mSocket; - if (socket == null) { - Logw("'send' request on closed Socket " + mChannelName); - throw new ClosedChannelException(); - } - socket.getOutputStream().write(data); - } - - /** - * Sends data to the socket. - * - * @param data Data to send. - * @param offset The start position in data from where to get bytes. - * @param len The number of bytes from data to write to this socket. - * @throws IOException - */ - public void send(byte[] data, int offset, int len) throws IOException { - LocalSocket socket = mSocket; - if (socket == null) { - Logw("'send' request on closed Socket " + mChannelName); - throw new ClosedChannelException(); - } - socket.getOutputStream().write(data, offset, len); - } - - /** - * Receives data from the socket. - * - * @param socket Socket from where to receive data. - * @param data Array where to save received data. - * @param len Number of bytes to receive. - * @throws IOException - */ - public static void receive(LocalSocket socket, byte[] data, int len) throws IOException { - final InputStream is = socket.getInputStream(); - int received = 0; - while (received != len) { - final int chunk = is.read(data, received, len - received); - if (chunk < 0) { - throw new IOException( - "I/O failure while receiving SDK controller data from socket."); - } - received += chunk; - } - } - - /** - * Receives data from the socket. - * - * @param data Array where to save received data. - * @param len Number of bytes to receive. - * @throws IOException - */ - public void receive(byte[] data, int len) throws IOException { - LocalSocket socket = mSocket; - if (socket == null) { - Logw("'receive' request on closed Socket " + mChannelName); - throw new ClosedChannelException(); - } - receive(socket, data, len); - } - - /** - * Receives data from the socket. - * - * @param data Array where to save received data. Data size is defined by - * the size of the array. - * @throws IOException - */ - public void receive(byte[] data) throws IOException { - receive(data, data.length); - } - - /** - * Closes the socket. - * - * @return true if socket has been closed in this call, or false if it had - * been already closed when this method has been called. - */ - public boolean close() { - // This is the only place in this class where we will null the socket - // object. Since this method can be called concurrently from different - // threads, lets do this under the lock. - LocalSocket socket; - synchronized (this) { - socket = mSocket; - mSocket = null; - } - if (socket != null) { - try { - // Force all I/O to stop before closing the socket. - socket.shutdownInput(); - socket.shutdownOutput(); - socket.close(); - if (DEBUG) Log.d(TAG, "Socket is closed for " + mChannelName); - return true; - } catch (IOException e) { - Loge("Exception " + e + " while closing Socket for " + mChannelName); - } - } - return false; - } - - /*************************************************************************** - * Logging wrappers - **************************************************************************/ - - private void Loge(String log) { - Log.e(TAG, log); - } - - private void Logw(String log) { - Log.w(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 deleted file mode 100755 index 9a3408b3e..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/service/ControllerService.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * 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 deleted file mode 100755 index 66bce49f3..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 deleted file mode 100755 index 2d4e8cd3f..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/utils/ApiHelper_11.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 deleted file mode 100755 index 0f185b173..000000000 --- a/apps/SdkController/src/com/android/tools/sdkcontroller/views/MultiTouchView.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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); - } -} |