Order files
This commit is contained in:
15159
android/tools/android-osx/tools/NOTICE.txt
Executable file
15159
android/tools/android-osx/tools/NOTICE.txt
Executable file
File diff suppressed because it is too large
Load Diff
114
android/tools/android-osx/tools/android
Executable file
114
android/tools/android-osx/tools/android
Executable file
@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2005-2007, 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.
|
||||
|
||||
# Set up prog to be the path of this script, including following symlinks,
|
||||
# and set up progdir to be the fully-qualified pathname of its directory.
|
||||
prog="$0"
|
||||
while [ -h "${prog}" ]; do
|
||||
newProg=`/bin/ls -ld "${prog}"`
|
||||
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
|
||||
if expr "x${newProg}" : 'x/' >/dev/null; then
|
||||
prog="${newProg}"
|
||||
else
|
||||
progdir=`dirname "${prog}"`
|
||||
prog="${progdir}/${newProg}"
|
||||
fi
|
||||
done
|
||||
oldwd=`pwd`
|
||||
progdir=`dirname "${prog}"`
|
||||
cd "${progdir}"
|
||||
progdir=`pwd`
|
||||
prog="${progdir}"/`basename "${prog}"`
|
||||
cd "${oldwd}"
|
||||
|
||||
jarfile=sdkmanager.jar
|
||||
frameworkdir="$progdir"
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/tools/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/framework
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
echo `basename "$prog"`": can't find $jarfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Check args.
|
||||
if [ debug = "$1" ]; then
|
||||
# add this in for debugging
|
||||
java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
|
||||
shift 1
|
||||
else
|
||||
java_debug=
|
||||
fi
|
||||
|
||||
java_cmd="java"
|
||||
|
||||
# Mac OS X needs an additional arg, or you get an "illegal thread" complaint.
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
os_opts="-XstartOnFirstThread"
|
||||
else
|
||||
os_opts=
|
||||
fi
|
||||
|
||||
if [ `uname` = "Linux" ]; then
|
||||
export GDK_NATIVE_WINDOWS=true
|
||||
fi
|
||||
|
||||
if [ "$OSTYPE" = "cygwin" ] ; then
|
||||
jarpath=`cygpath -w "$frameworkdir/$jarfile"`
|
||||
jarpath="$jarpath;"`cygpath -w "$frameworkdir/swtmenubar.jar"`
|
||||
progdir=`cygpath -w "$progdir"`
|
||||
else
|
||||
jarpath="$frameworkdir/$jarfile:$frameworkdir/swtmenubar.jar"
|
||||
fi
|
||||
|
||||
# Get the current content of java.ext.dirs so that we can add to it instead of replacing
|
||||
javaExtDirs=`"${java_cmd}" -jar "${frameworkdir}/archquery.jar" java.ext.dirs`
|
||||
|
||||
# Figure out the path to the swt.jar for the current architecture.
|
||||
# if ANDROID_SWT is defined, then just use this.
|
||||
# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
|
||||
# else, look for the correct swt folder in the SDK under tools/lib/
|
||||
swtpath=""
|
||||
if [ -n "$ANDROID_SWT" ]; then
|
||||
swtpath="$ANDROID_SWT"
|
||||
else
|
||||
vmarch=`"${java_cmd}" -jar "${frameworkdir}/archquery.jar"`
|
||||
if [ -n "$ANDROID_BUILD_TOP" ]; then
|
||||
osname=`uname -s | tr A-Z a-z`
|
||||
swtpath="${ANDROID_BUILD_TOP}/prebuilts/tools/${osname}-${vmarch}/swt"
|
||||
else
|
||||
swtpath="${frameworkdir}/${vmarch}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$swtpath" ]; then
|
||||
echo "SWT folder '${swtpath}' does not exist."
|
||||
echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
|
||||
exec "$java_cmd" \
|
||||
-Xmx256M $os_opts $java_debug \
|
||||
-Dcom.android.sdkmanager.toolsdir="$progdir" \
|
||||
-classpath "$jarpath:$swtpath/swt.jar" \
|
||||
com.android.sdkmanager.Main "$@"
|
190
android/tools/android-osx/tools/ant/NOTICE
Executable file
190
android/tools/android-osx/tools/ant/NOTICE
Executable file
@ -0,0 +1,190 @@
|
||||
|
||||
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
|
||||
|
1534
android/tools/android-osx/tools/ant/build.xml
Executable file
1534
android/tools/android-osx/tools/ant/build.xml
Executable file
File diff suppressed because it is too large
Load Diff
260
android/tools/android-osx/tools/ant/uibuild.xml
Executable file
260
android/tools/android-osx/tools/ant/uibuild.xml
Executable file
@ -0,0 +1,260 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="android_rules" default="debug">
|
||||
|
||||
<!--
|
||||
This build file is imported by the project build file. It contains
|
||||
all the targets and tasks necessary to build Android projects, be they
|
||||
regular projects, library projects, or test projects.
|
||||
|
||||
At the beginning of the file is a list of properties that can be overridden
|
||||
by adding them to your ant.properties (properties are immutable, so their
|
||||
first definition sticks and is never changed).
|
||||
|
||||
Follows:
|
||||
- custom task definitions,
|
||||
- more properties (do not override those unless the whole build system is modified).
|
||||
- macros used throughout the build,
|
||||
- base build targets,
|
||||
- debug-specific build targets,
|
||||
- release-specific build targets,
|
||||
- instrument-specific build targets,
|
||||
- test project-specific build targets,
|
||||
- install targets,
|
||||
- help target
|
||||
-->
|
||||
|
||||
<!-- ******************************************************* -->
|
||||
<!-- **************** Overridable Properties *************** -->
|
||||
<!-- ******************************************************* -->
|
||||
|
||||
<!-- You can override these values in your build.xml or ant.properties.
|
||||
Overriding any other properties may result in broken build. -->
|
||||
|
||||
<!-- Tells adb which device to target. You can change this from the command line
|
||||
by invoking "ant -Dadb.device.arg=-d" for device "ant -Dadb.device.arg=-e" for
|
||||
the emulator. -->
|
||||
<property name="adb.device.arg" value="" />
|
||||
|
||||
<!-- filename only of the output file. Cannot be a path -->
|
||||
<property name="out.filename" value="${ant.project.name}.jar" />
|
||||
|
||||
<!-- compilation options -->
|
||||
<property name="java.encoding" value="UTF-8" />
|
||||
<property name="java.target" value="1.5" />
|
||||
<property name="java.source" value="1.5" />
|
||||
<property name="java.compilerargs" value="" />
|
||||
|
||||
<!-- Verbosity -->
|
||||
<property name="verbose" value="false" />
|
||||
|
||||
<!-- ******************************************************* -->
|
||||
<!-- ********************* Custom Tasks ******************** -->
|
||||
<!-- ******************************************************* -->
|
||||
|
||||
<!-- jar file from where the tasks are loaded -->
|
||||
<path id="android.antlibs">
|
||||
<pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
|
||||
</path>
|
||||
|
||||
<!-- Custom tasks -->
|
||||
<taskdef resource="anttasks.properties" classpathref="android.antlibs" />
|
||||
|
||||
<!-- Emma configuration -->
|
||||
<property name="emma.dir" value="${sdk.dir}/tools/lib" />
|
||||
<path id="emma.lib">
|
||||
<pathelement location="${emma.dir}/emma.jar" />
|
||||
<pathelement location="${emma.dir}/emma_ant.jar" />
|
||||
</path>
|
||||
<taskdef resource="emma_ant.properties" classpathref="emma.lib" />
|
||||
<!-- End of emma configuration -->
|
||||
|
||||
|
||||
<!-- ******************************************************* -->
|
||||
<!-- ******************* Other Properties ****************** -->
|
||||
<!-- ******************************************************* -->
|
||||
<!-- overriding these properties may break the build
|
||||
unless the whole file is updated -->
|
||||
|
||||
<!-- Input directories -->
|
||||
<property name="source.dir" value="src" />
|
||||
<property name="source.absolute.dir" location="${source.dir}" />
|
||||
<property name="jar.libs.dir" value="libs" />
|
||||
<property name="jar.libs.absolute.dir" location="${jar.libs.dir}" />
|
||||
|
||||
<!-- Output directories -->
|
||||
<property name="out.dir" value="bin" />
|
||||
<property name="out.absolute.dir" location="${out.dir}" />
|
||||
<property name="out.classes.absolute.dir" location="${out.dir}/classes" />
|
||||
|
||||
<property name="out.file" value="${out.absolute.dir}/${out.filename}" />
|
||||
|
||||
<!-- tools location -->
|
||||
<property name="android.tools.dir" location="${sdk.dir}/tools" />
|
||||
<property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
|
||||
<condition property="exe" value=".exe" else=""><os family="windows" /></condition>
|
||||
<condition property="bat" value=".bat" else=""><os family="windows" /></condition>
|
||||
<property name="adb" location="${android.platform.tools.dir}/adb${exe}" />
|
||||
|
||||
<!-- Intermediate files -->
|
||||
<property name="dex.file.name" value="classes.dex" />
|
||||
<property name="intermediate.dex.file" location="${out.absolute.dir}/${dex.file.name}" />
|
||||
<property name="resource.package.file.name" value="${ant.project.name}.ap_" />
|
||||
|
||||
<!-- whether we need to fork javac.
|
||||
This is only needed on Windows when running Java < 7 -->
|
||||
<condition else="false" property="need.javac.fork">
|
||||
<and>
|
||||
<matches pattern="1\.[56]" string="${java.specification.version}"/>
|
||||
<not>
|
||||
<os family="unix"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
<macrodef name="run-tests-helper">
|
||||
<attribute name="emma.enabled" default="false" />
|
||||
<element name="extra-instrument-args" optional="yes" />
|
||||
<sequential>
|
||||
<echo level="info">Running tests ...</echo>
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg line="${adb.device.arg}" />
|
||||
<arg value="shell" />
|
||||
<arg value="am" />
|
||||
<arg value="instrument" />
|
||||
<arg value="-w" />
|
||||
<arg value="-e" />
|
||||
<arg value="coverage" />
|
||||
<arg value="@{emma.enabled}" />
|
||||
<extra-instrument-args />
|
||||
<arg value="${project.app.package}/${test.runner}" />
|
||||
</exec>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<!-- ******************************************************* -->
|
||||
<!-- ******************** Build Targets ******************** -->
|
||||
<!-- ******************************************************* -->
|
||||
|
||||
<!-- Basic Ant + SDK check -->
|
||||
<target name="-check-env">
|
||||
<checkenv />
|
||||
</target>
|
||||
|
||||
<!-- empty default pre-clean target. Create a similar target in
|
||||
your build.xml and it'll be called instead of this one. -->
|
||||
<target name="-pre-clean"/>
|
||||
|
||||
<!-- clean target -->
|
||||
<target name="clean" depends="-check-env, -pre-clean"
|
||||
description="Removes output files created by other targets.">
|
||||
<delete dir="${out.absolute.dir}" verbose="${verbose}" />
|
||||
</target>
|
||||
|
||||
<!-- Pre build setup -->
|
||||
<target name="-build-setup" depends="-check-env">
|
||||
<getbuildtools name="android.build.tools.dir" />
|
||||
<property name="dx" location="${android.build.tools.dir}/dx${bat}" />
|
||||
|
||||
<echo level="info">Resolving Build Target for ${ant.project.name}...</echo>
|
||||
<!-- load project properties, resolve Android target, library dependencies
|
||||
and set some properties with the results.
|
||||
All property names are passed as parameters ending in -Out -->
|
||||
<getuitarget compileClassPathOut="project.target.class.path" />
|
||||
|
||||
<echo level="info">----------</echo>
|
||||
<echo level="info">Creating output directories if needed...</echo>
|
||||
<mkdir dir="${out.absolute.dir}" />
|
||||
<mkdir dir="${out.classes.absolute.dir}" />
|
||||
|
||||
</target>
|
||||
|
||||
<!-- empty default pre-compile target. Create a similar target in
|
||||
your build.xml and it'll be called instead of this one. -->
|
||||
<target name="-pre-compile"/>
|
||||
|
||||
<!-- Compiles this project's .java files into .class files. -->
|
||||
<target name="compile" depends="-build-setup, -pre-compile">
|
||||
<javac encoding="${java.encoding}"
|
||||
source="${java.source}" target="${java.target}"
|
||||
debug="true" extdirs="" includeantruntime="false"
|
||||
destdir="${out.classes.absolute.dir}"
|
||||
bootclasspathref="project.target.class.path"
|
||||
verbose="${verbose}"
|
||||
fork="${need.javac.fork}">
|
||||
<src path="${source.absolute.dir}" />
|
||||
<compilerarg line="${java.compilerargs}" />
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- empty default post-compile target. Create a similar target in
|
||||
your build.xml and it'll be called instead of this one. -->
|
||||
<target name="-post-compile"/>
|
||||
|
||||
<!-- Converts this project's .class files into .dex files -->
|
||||
<target name="-dex" depends="compile, -post-compile">
|
||||
<dex executable="${dx}"
|
||||
output="${intermediate.dex.file}"
|
||||
nolocals="@{nolocals}"
|
||||
verbose="${verbose}">
|
||||
<path path="${out.classes.absolute.dir}"/>
|
||||
</dex>
|
||||
</target>
|
||||
|
||||
<!-- empty default post-dex target. Create a similar target in
|
||||
your build.xml and it'll be called instead of this one. -->
|
||||
<target name="-post-dex"/>
|
||||
|
||||
<target name="-jar" depends="-dex, -post-dex" >
|
||||
<jar destfile="${out.file}">
|
||||
<fileset file="${intermediate.dex.file}" />
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<!-- empty default post-jar target. Create a similar target in
|
||||
your build.xml and it'll be called instead of this one. -->
|
||||
<target name="-post-jar"/>
|
||||
|
||||
<target name="build" depends="-jar, -post-jar" />
|
||||
|
||||
<target name="install" description="Install the test package">
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg line="${adb.device.arg}" />
|
||||
<arg value="push" />
|
||||
<arg value="${out.file}" />
|
||||
<arg value="/data/local/tmp" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="test" description="Runs tests">
|
||||
<!-- todo: fix this -->
|
||||
<fail message="Launching tests from Ant not supported yet" />
|
||||
|
||||
<exec executable="${adb}" failonerror="true">
|
||||
<arg line="${adb.device.arg}" />
|
||||
<arg value="shell" />
|
||||
<arg value="uiautomator" />
|
||||
<arg value="runtest" />
|
||||
<arg value="${out.filename}" />
|
||||
<arg value="-e" />
|
||||
<arg value="class" />
|
||||
<arg value="com.android.uiautomator.samples.skeleton.DemoTestCase" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="help">
|
||||
<!-- displays starts at col 13
|
||||
|13 80| -->
|
||||
<echo>Android Ant Build. Available targets:</echo>
|
||||
<echo> help: Displays this help.</echo>
|
||||
<echo> clean: Removes output files created by other targets.</echo>
|
||||
<echo> build: Builds the test library.</echo>
|
||||
<echo> install: Installs the library on a connected device or</echo>
|
||||
<echo> emulator.</echo>
|
||||
<echo> test: Runs the tests.</echo>
|
||||
<echo></echo>
|
||||
<echo>It is possible to mix targets. For instance:</echo>
|
||||
<echo> ant build install test</echo>
|
||||
<echo>This will build, install and run the test in a single command.</echo>
|
||||
</target>
|
||||
|
||||
</project>
|
8
android/tools/android-osx/tools/apps/SdkController/.classpath
Executable file
8
android/tools/android-osx/tools/apps/SdkController/.classpath
Executable file
@ -0,0 +1,8 @@
|
||||
<?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>
|
34
android/tools/android-osx/tools/apps/SdkController/.project
Executable file
34
android/tools/android-osx/tools/apps/SdkController/.project
Executable file
@ -0,0 +1,34 @@
|
||||
<?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>
|
@ -0,0 +1,12 @@
|
||||
#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
|
44
android/tools/android-osx/tools/apps/SdkController/AndroidManifest.xml
Executable file
44
android/tools/android-osx/tools/apps/SdkController/AndroidManifest.xml
Executable file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.tools.sdkcontroller"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="15" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" >
|
||||
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleInstance" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.SensorActivity"
|
||||
android:launchMode="singleInstance"
|
||||
android:windowSoftInputMode="stateUnchanged" android:label="@string/sensors_activity_title"/>
|
||||
|
||||
<activity
|
||||
android:name=".activities.MultiTouchActivity"
|
||||
android:launchMode="singleInstance"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.MultiTouch"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
|
||||
<service
|
||||
android:name=".service.ControllerService"
|
||||
android:description="@string/service_description"
|
||||
android:icon="@drawable/ic_launcher" />
|
||||
</application>
|
||||
</manifest>
|
85
android/tools/android-osx/tools/apps/SdkController/Implementation.txt
Executable file
85
android/tools/android-osx/tools/apps/SdkController/Implementation.txt
Executable file
@ -0,0 +1,85 @@
|
||||
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
|
||||
|
||||
----
|
190
android/tools/android-osx/tools/apps/SdkController/NOTICE
Executable file
190
android/tools/android-osx/tools/apps/SdkController/NOTICE
Executable file
@ -0,0 +1,190 @@
|
||||
|
||||
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
|
||||
|
42
android/tools/android-osx/tools/apps/SdkController/assets/intro_help.html
Executable file
42
android/tools/android-osx/tools/apps/SdkController/assets/intro_help.html
Executable file
@ -0,0 +1,42 @@
|
||||
<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>
|
BIN
android/tools/android-osx/tools/apps/SdkController/bin/SdkControllerApp.apk
Executable file
BIN
android/tools/android-osx/tools/apps/SdkController/bin/SdkControllerApp.apk
Executable file
Binary file not shown.
20
android/tools/android-osx/tools/apps/SdkController/proguard-project.txt
Executable file
20
android/tools/android-osx/tools/apps/SdkController/proguard-project.txt
Executable file
@ -0,0 +1,20 @@
|
||||
# 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 *;
|
||||
#}
|
14
android/tools/android-osx/tools/apps/SdkController/project.properties
Executable file
14
android/tools/android-osx/tools/apps/SdkController/project.properties
Executable file
@ -0,0 +1,14 @@
|
||||
# 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
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
168
android/tools/android-osx/tools/apps/SdkController/res/layout-land/sensors.xml
Executable file
168
android/tools/android-osx/tools/apps/SdkController/res/layout-land/sensors.xml
Executable file
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<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>
|
116
android/tools/android-osx/tools/apps/SdkController/res/layout/main.xml
Executable file
116
android/tools/android-osx/tools/apps/SdkController/res/layout/main.xml
Executable file
@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp" >
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/toggleService"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/labelService"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBaseline="@+id/toggleService"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="@string/main_label_service"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<!-- Placeholder status text. Becomes visibility=gone when empty. -->
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBaseline="@+id/labelService"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_toRightOf="@+id/labelService"
|
||||
android:text="[status]"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<!-- Placeholder error text. Becomes visibility=gone when empty. -->
|
||||
<TextView
|
||||
android:id="@+id/textError"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@+id/toggleService"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="#F00F"
|
||||
android:gravity="center_horizontal"
|
||||
android:padding="8dp"
|
||||
android:text="[service errors]"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textColor="#FFF0"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/labelButtons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/textError"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/main_label_buttons"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOpenMultitouch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/labelButtons"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/main_btn_open_multitouch" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnOpenSensors"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/btnOpenMultitouch"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/main_btn_open_sensors" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webIntro"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/btnOpenSensors"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@null"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
</ScrollView>
|
32
android/tools/android-osx/tools/apps/SdkController/res/layout/multitouch.xml
Executable file
32
android/tools/android-osx/tools/apps/SdkController/res/layout/multitouch.xml
Executable file
@ -0,0 +1,32 @@
|
||||
<?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>
|
42
android/tools/android-osx/tools/apps/SdkController/res/layout/sensor_row.xml
Executable file
42
android/tools/android-osx/tools/apps/SdkController/res/layout/sensor_row.xml
Executable file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!-- One row per sensor added to the TableLayout from layout/sensors.xml -->
|
||||
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/row_checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="10dp"
|
||||
android:saveEnabled="false"
|
||||
android:text="Some CheckBox"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/row_textview"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
</TableRow>
|
130
android/tools/android-osx/tools/apps/SdkController/res/layout/sensors.xml
Executable file
130
android/tools/android-osx/tools/apps/SdkController/res/layout/sensors.xml
Executable file
@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
|
||||
<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>
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Theme.MultiTouch" parent="android:Theme.Holo.NoActionBar.Fullscreen">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
48
android/tools/android-osx/tools/apps/SdkController/res/values/strings.xml
Executable file
48
android/tools/android-osx/tools/apps/SdkController/res/values/strings.xml
Executable file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<!-- Strings for manifest. -->
|
||||
<string name="app_name">SDK Controller</string>
|
||||
<string name="service_description">Background service for SDK Controller</string>
|
||||
|
||||
<!-- Strings for service. -->
|
||||
<string name="service_notif_title">SDK Controller is running</string>
|
||||
|
||||
<!-- Strings for layout/main -->
|
||||
<string name="main_label_service">Service:</string>
|
||||
<string name="main_label_buttons">What you can do:</string>
|
||||
<string name="main_btn_open_multitouch">Control Multi-touch</string>
|
||||
<string name="main_btn_open_sensors">Control Sensors</string>
|
||||
<string name="main_service_status_connected">Emulator Connected</string>
|
||||
<string name="main_service_status_disconnected">Emulator Connected</string>
|
||||
|
||||
<!-- Strings for layout/sensors -->
|
||||
<string name="sensors_activity_title">SDK Controller > Sensors</string>
|
||||
<string name="sensors_top_description">Available Sensors:</string>
|
||||
<string name="sensors_sample_rate">Sample Rate</string>
|
||||
<string name="sensors_hz_per_sensor">Hz per sensor</string>
|
||||
<string name="sensors_actual_rate">Actual</string>
|
||||
<string name="sensors_hz_average">Hz average</string>
|
||||
<!-- Default sample rate for SensorsActivity UI.
|
||||
Should match the default for SensorsHandler.mUpdateTargetMs. -->
|
||||
<string name="sensors_default_sample_rate">20</string>
|
||||
|
||||
</resources>
|
26
android/tools/android-osx/tools/apps/SdkController/res/values/styles.xml
Executable file
26
android/tools/android-osx/tools/apps/SdkController/res/values/styles.xml
Executable file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Theme.MultiTouch" parent="android:Theme.NoTitleBar.Fullscreen">
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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));
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.activities;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.tools.sdkcontroller.R;
|
||||
import com.android.tools.sdkcontroller.handlers.MultiTouchChannel;
|
||||
import com.android.tools.sdkcontroller.lib.Channel;
|
||||
import com.android.tools.sdkcontroller.lib.ProtocolConstants;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener;
|
||||
import com.android.tools.sdkcontroller.utils.ApiHelper;
|
||||
import com.android.tools.sdkcontroller.views.MultiTouchView;
|
||||
|
||||
/**
|
||||
* Activity that controls and displays the {@link MultiTouchChannel}.
|
||||
*/
|
||||
public class MultiTouchActivity extends BaseBindingActivity
|
||||
implements android.os.Handler.Callback {
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private static String TAG = MultiTouchActivity.class.getSimpleName();
|
||||
private static boolean DEBUG = true;
|
||||
|
||||
private volatile MultiTouchChannel mHandler;
|
||||
|
||||
private TextView mTextError;
|
||||
private TextView mTextStatus;
|
||||
private MultiTouchView mImageView;
|
||||
/** Width of the emulator's display. */
|
||||
private int mEmulatorWidth = 0;
|
||||
/** Height of the emulator's display. */
|
||||
private int mEmulatorHeight = 0;
|
||||
/** Bitmap storage. */
|
||||
private int[] mColors;
|
||||
|
||||
private final TouchListener mTouchListener = new TouchListener();
|
||||
private final android.os.Handler mUiHandler = new android.os.Handler(this);
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.multitouch);
|
||||
mImageView = (MultiTouchView) findViewById(R.id.imageView);
|
||||
mTextError = (TextView) findViewById(R.id.textError);
|
||||
mTextStatus = (TextView) findViewById(R.id.textStatus);
|
||||
updateStatus("Waiting for connection");
|
||||
|
||||
ApiHelper ah = ApiHelper.get();
|
||||
ah.View_setSystemUiVisibility(mImageView, View.SYSTEM_UI_FLAG_LOW_PROFILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (DEBUG) Log.d(TAG, "onResume");
|
||||
// BaseBindingActivity.onResume will bind to the service.
|
||||
// Note: any initialization related to the service or the handler should
|
||||
// go in onServiceConnected() since in this call the service may not be
|
||||
// bound yet.
|
||||
super.onResume();
|
||||
updateError();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if (DEBUG) Log.d(TAG, "onPause");
|
||||
// BaseBindingActivity.onResume will unbind from (but not stop) the service.
|
||||
super.onPause();
|
||||
mImageView.setEnabled(false);
|
||||
updateStatus("Paused");
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
@Override
|
||||
protected void onServiceConnected() {
|
||||
if (DEBUG) Log.d(TAG, "onServiceConnected");
|
||||
mHandler = (MultiTouchChannel) getServiceBinder().getChannel(Channel.MULTITOUCH_CHANNEL);
|
||||
if (mHandler != null) {
|
||||
mHandler.setViewSize(mImageView.getWidth(), mImageView.getHeight());
|
||||
mHandler.addUiHandler(mUiHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceDisconnected() {
|
||||
if (DEBUG) Log.d(TAG, "onServiceDisconnected");
|
||||
if (mHandler != null) {
|
||||
mHandler.removeUiHandler(mUiHandler);
|
||||
mHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ControllerListener createControllerListener() {
|
||||
return new MultiTouchControllerListener();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
private class MultiTouchControllerListener implements ControllerListener {
|
||||
@Override
|
||||
public void onErrorChanged() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateError();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ControllerBinder binder = getServiceBinder();
|
||||
if (binder != null) {
|
||||
boolean connected = binder.isEmuConnected();
|
||||
mImageView.setEnabled(connected);
|
||||
updateStatus(connected ? "Emulator connected" : "Emulator disconnected");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
/**
|
||||
* Implements OnTouchListener interface that receives touch screen events,
|
||||
* and reports them to the emulator application.
|
||||
*/
|
||||
class TouchListener implements OnTouchListener {
|
||||
/**
|
||||
* Touch screen event handler.
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
ByteBuffer bb = null;
|
||||
final int action = event.getAction();
|
||||
final int action_code = action & MotionEvent.ACTION_MASK;
|
||||
final int action_pid_index = action >> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
int msg_type = 0;
|
||||
MultiTouchChannel h = mHandler;
|
||||
|
||||
// Build message for the emulator.
|
||||
switch (action_code) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (h != null) {
|
||||
bb = ByteBuffer.allocate(
|
||||
event.getPointerCount() * ProtocolConstants.MT_EVENT_ENTRY_SIZE);
|
||||
bb.order(h.getEndian());
|
||||
for (int n = 0; n < event.getPointerCount(); n++) {
|
||||
mImageView.constructEventMessage(bb, event, n);
|
||||
}
|
||||
msg_type = ProtocolConstants.MT_MOVE;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (h != null) {
|
||||
bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
|
||||
bb.order(h.getEndian());
|
||||
mImageView.constructEventMessage(bb, event, action_pid_index);
|
||||
msg_type = ProtocolConstants.MT_FISRT_DOWN;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (h != null) {
|
||||
bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
|
||||
bb.order(h.getEndian());
|
||||
bb.putInt(event.getPointerId(action_pid_index));
|
||||
msg_type = ProtocolConstants.MT_LAST_UP;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (h != null) {
|
||||
bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
|
||||
bb.order(h.getEndian());
|
||||
mImageView.constructEventMessage(bb, event, action_pid_index);
|
||||
msg_type = ProtocolConstants.MT_POINTER_DOWN;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (h != null) {
|
||||
bb = ByteBuffer.allocate(ProtocolConstants.MT_EVENT_ENTRY_SIZE);
|
||||
bb.order(h.getEndian());
|
||||
bb.putInt(event.getPointerId(action_pid_index));
|
||||
msg_type = ProtocolConstants.MT_POINTER_UP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "Unknown action type: " + action_code);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DEBUG && bb != null) Log.d(TAG, bb.toString());
|
||||
|
||||
if (h != null && bb != null) {
|
||||
h.postMessage(msg_type, bb);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // TouchListener
|
||||
|
||||
/** Implementation of Handler.Callback */
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MultiTouchChannel.EVENT_MT_START:
|
||||
MultiTouchChannel h = mHandler;
|
||||
if (h != null) {
|
||||
mImageView.setEnabled(true);
|
||||
mImageView.setOnTouchListener(mTouchListener);
|
||||
}
|
||||
break;
|
||||
case MultiTouchChannel.EVENT_MT_STOP:
|
||||
mImageView.setOnTouchListener(null);
|
||||
break;
|
||||
case MultiTouchChannel.EVENT_FRAME_BUFFER:
|
||||
onFrameBuffer(((ByteBuffer) msg.obj).array());
|
||||
mHandler.postMessage(ProtocolConstants.MT_FB_HANDLED, (byte[]) null);
|
||||
break;
|
||||
}
|
||||
return true; // we consumed this message
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a BLOB query is received from the emulator.
|
||||
* <p/>
|
||||
* This query is used to deliver framebuffer updates in the emulator. The
|
||||
* blob contains an update header, followed by the bitmap containing updated
|
||||
* rectangle. The header is defined as MTFrameHeader structure in
|
||||
* external/qemu/android/multitouch-port.h
|
||||
* <p/>
|
||||
* NOTE: This method is called from the I/O loop, so all communication with
|
||||
* the emulator will be "on hold" until this method returns.
|
||||
*
|
||||
* TODO ===> CHECK that we can consume that array from a different thread than the producer's.
|
||||
* E.g. does the produce reuse the same array or does it generate a new one each time?
|
||||
*
|
||||
* @param array contains BLOB data for the query.
|
||||
*/
|
||||
private void onFrameBuffer(byte[] array) {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(array);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// Read frame header.
|
||||
final int header_size = bb.getInt();
|
||||
final int disp_width = bb.getInt();
|
||||
final int disp_height = bb.getInt();
|
||||
final int x = bb.getInt();
|
||||
final int y = bb.getInt();
|
||||
final int w = bb.getInt();
|
||||
final int h = bb.getInt();
|
||||
final int bpl = bb.getInt();
|
||||
final int bpp = bb.getInt();
|
||||
final int format = bb.getInt();
|
||||
|
||||
// Update application display.
|
||||
updateDisplay(disp_width, disp_height);
|
||||
|
||||
if (format == ProtocolConstants.MT_FRAME_JPEG) {
|
||||
/*
|
||||
* Framebuffer is in JPEG format.
|
||||
*/
|
||||
|
||||
final ByteArrayInputStream jpg = new ByteArrayInputStream(bb.array());
|
||||
// Advance input stream to JPEG image.
|
||||
jpg.skip(header_size);
|
||||
// Draw the image.
|
||||
mImageView.drawJpeg(x, y, w, h, jpg);
|
||||
} else {
|
||||
/*
|
||||
* Framebuffer is in a raw RGB format.
|
||||
*/
|
||||
|
||||
final int pixel_num = h * w;
|
||||
// Advance stream to the beginning of framebuffer data.
|
||||
bb.position(header_size);
|
||||
|
||||
// Make sure that mColors is large enough to contain the
|
||||
// update bitmap.
|
||||
if (mColors == null || mColors.length < pixel_num) {
|
||||
mColors = new int[pixel_num];
|
||||
}
|
||||
|
||||
// Convert the blob bitmap into bitmap that we will display.
|
||||
if (format == ProtocolConstants.MT_FRAME_RGB565) {
|
||||
for (int n = 0; n < pixel_num; n++) {
|
||||
// Blob bitmap is in RGB565 format.
|
||||
final int color = bb.getShort();
|
||||
final int r = ((color & 0xf800) >> 8) | ((color & 0xf800) >> 14);
|
||||
final int g = ((color & 0x7e0) >> 3) | ((color & 0x7e0) >> 9);
|
||||
final int b = ((color & 0x1f) << 3) | ((color & 0x1f) >> 2);
|
||||
mColors[n] = Color.rgb(r, g, b);
|
||||
}
|
||||
} else if (format == ProtocolConstants.MT_FRAME_RGB888) {
|
||||
for (int n = 0; n < pixel_num; n++) {
|
||||
// Blob bitmap is in RGB565 format.
|
||||
final int r = bb.getChar();
|
||||
final int g = bb.getChar();
|
||||
final int b = bb.getChar();
|
||||
mColors[n] = Color.rgb(r, g, b);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Invalid framebuffer format: " + format);
|
||||
return;
|
||||
}
|
||||
mImageView.drawBitmap(x, y, w, h, mColors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates application's screen accordingly to the emulator screen.
|
||||
*
|
||||
* @param e_width Width of the emulator screen.
|
||||
* @param e_height Height of the emulator screen.
|
||||
*/
|
||||
private void updateDisplay(int e_width, int e_height) {
|
||||
if (e_width != mEmulatorWidth || e_height != mEmulatorHeight) {
|
||||
mEmulatorWidth = e_width;
|
||||
mEmulatorHeight = e_height;
|
||||
|
||||
boolean rotateDisplay = false;
|
||||
int w = mImageView.getWidth();
|
||||
int h = mImageView.getHeight();
|
||||
if (w > h != e_width > e_height) {
|
||||
rotateDisplay = true;
|
||||
int tmp = w;
|
||||
w = h;
|
||||
h = tmp;
|
||||
}
|
||||
|
||||
float dx = (float) w / (float) e_width;
|
||||
float dy = (float) h / (float) e_height;
|
||||
mImageView.setDxDy(dx, dy, rotateDisplay);
|
||||
if (DEBUG) Log.d(TAG, "Dispay updated: " + e_width + " x " + e_height +
|
||||
" -> " + w + " x " + h + " ratio: " +
|
||||
dx + " x " + dy);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
private void updateStatus(String status) {
|
||||
mTextStatus.setVisibility(status == null ? View.GONE : View.VISIBLE);
|
||||
if (status != null) mTextStatus.setText(status);
|
||||
}
|
||||
|
||||
private void updateError() {
|
||||
ControllerBinder binder = getServiceBinder();
|
||||
String error = binder == null ? "" : binder.getServiceError();
|
||||
if (error == null) {
|
||||
error = "";
|
||||
}
|
||||
|
||||
mTextError.setVisibility(error.length() == 0 ? View.GONE : View.VISIBLE);
|
||||
mTextError.setText(error);
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.activities;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TableRow;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.tools.sdkcontroller.R;
|
||||
import com.android.tools.sdkcontroller.handlers.SensorChannel;
|
||||
import com.android.tools.sdkcontroller.handlers.SensorChannel.MonitoredSensor;
|
||||
import com.android.tools.sdkcontroller.lib.Channel;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService.ControllerBinder;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService.ControllerListener;
|
||||
|
||||
/**
|
||||
* Activity that displays and controls the sensors from {@link SensorChannel}.
|
||||
* For each sensor it displays a checkbox that is enabled if the sensor is supported
|
||||
* by the emulator. The user can select whether the sensor is active. It also displays
|
||||
* data from the sensor when available.
|
||||
*/
|
||||
public class SensorActivity extends BaseBindingActivity
|
||||
implements android.os.Handler.Callback {
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
public static String TAG = SensorActivity.class.getSimpleName();
|
||||
private static boolean DEBUG = true;
|
||||
|
||||
private static final int MSG_UPDATE_ACTUAL_HZ = 0x31415;
|
||||
|
||||
private TableLayout mTableLayout;
|
||||
private TextView mTextError;
|
||||
private TextView mTextStatus;
|
||||
private TextView mTextTargetHz;
|
||||
private TextView mTextActualHz;
|
||||
private SensorChannel mSensorHandler;
|
||||
|
||||
private final Map<MonitoredSensor, DisplayInfo> mDisplayedSensors =
|
||||
new HashMap<SensorChannel.MonitoredSensor, SensorActivity.DisplayInfo>();
|
||||
private final android.os.Handler mUiHandler = new android.os.Handler(this);
|
||||
private int mTargetSampleRate;
|
||||
private long mLastActualUpdateMs;
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.sensors);
|
||||
mTableLayout = (TableLayout) findViewById(R.id.tableLayout);
|
||||
mTextError = (TextView) findViewById(R.id.textError);
|
||||
mTextStatus = (TextView) findViewById(R.id.textStatus);
|
||||
mTextTargetHz = (TextView) findViewById(R.id.textSampleRate);
|
||||
mTextActualHz = (TextView) findViewById(R.id.textActualRate);
|
||||
updateStatus("Waiting for connection");
|
||||
|
||||
mTextTargetHz.setOnKeyListener(new OnKeyListener() {
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
updateSampleRate();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
mTextTargetHz.setOnFocusChangeListener(new OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
updateSampleRate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (DEBUG) Log.d(TAG, "onResume");
|
||||
// BaseBindingActivity.onResume will bind to the service.
|
||||
super.onResume();
|
||||
updateError();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
if (DEBUG) Log.d(TAG, "onPause");
|
||||
// BaseBindingActivity.onResume will unbind from (but not stop) the service.
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (DEBUG) Log.d(TAG, "onDestroy");
|
||||
super.onDestroy();
|
||||
removeSensorUi();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
@Override
|
||||
protected void onServiceConnected() {
|
||||
if (DEBUG) Log.d(TAG, "onServiceConnected");
|
||||
createSensorUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServiceDisconnected() {
|
||||
if (DEBUG) Log.d(TAG, "onServiceDisconnected");
|
||||
removeSensorUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ControllerListener createControllerListener() {
|
||||
return new SensorsControllerListener();
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
private class SensorsControllerListener implements ControllerListener {
|
||||
@Override
|
||||
public void onErrorChanged() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateError();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChanged() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ControllerBinder binder = getServiceBinder();
|
||||
if (binder != null) {
|
||||
boolean connected = binder.isEmuConnected();
|
||||
mTableLayout.setEnabled(connected);
|
||||
updateStatus(connected ? "Emulated connected" : "Emulator disconnected");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void createSensorUi() {
|
||||
final LayoutInflater inflater = getLayoutInflater();
|
||||
|
||||
if (!mDisplayedSensors.isEmpty()) {
|
||||
removeSensorUi();
|
||||
}
|
||||
|
||||
mSensorHandler = (SensorChannel) getServiceBinder().getChannel(Channel.SENSOR_CHANNEL);
|
||||
if (mSensorHandler != null) {
|
||||
mSensorHandler.addUiHandler(mUiHandler);
|
||||
mUiHandler.sendEmptyMessage(MSG_UPDATE_ACTUAL_HZ);
|
||||
|
||||
assert mDisplayedSensors.isEmpty();
|
||||
List<MonitoredSensor> sensors = mSensorHandler.getSensors();
|
||||
for (MonitoredSensor sensor : sensors) {
|
||||
final TableRow row = (TableRow) inflater.inflate(R.layout.sensor_row,
|
||||
mTableLayout,
|
||||
false);
|
||||
mTableLayout.addView(row);
|
||||
mDisplayedSensors.put(sensor, new DisplayInfo(sensor, row));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSensorUi() {
|
||||
if (mSensorHandler != null) {
|
||||
mSensorHandler.removeUiHandler(mUiHandler);
|
||||
mSensorHandler = null;
|
||||
}
|
||||
mTableLayout.removeAllViews();
|
||||
for (DisplayInfo info : mDisplayedSensors.values()) {
|
||||
info.release();
|
||||
}
|
||||
mDisplayedSensors.clear();
|
||||
}
|
||||
|
||||
private class DisplayInfo implements CompoundButton.OnCheckedChangeListener {
|
||||
private MonitoredSensor mSensor;
|
||||
private CheckBox mChk;
|
||||
private TextView mVal;
|
||||
|
||||
public DisplayInfo(MonitoredSensor sensor, TableRow row) {
|
||||
mSensor = sensor;
|
||||
|
||||
// Initialize displayed checkbox for this sensor, and register
|
||||
// checked state listener for it.
|
||||
mChk = (CheckBox) row.findViewById(R.id.row_checkbox);
|
||||
mChk.setText(sensor.getUiName());
|
||||
mChk.setEnabled(sensor.isEnabledByEmulator());
|
||||
mChk.setChecked(sensor.isEnabledByUser());
|
||||
mChk.setOnCheckedChangeListener(this);
|
||||
|
||||
// Initialize displayed text box for this sensor.
|
||||
mVal = (TextView) row.findViewById(R.id.row_textview);
|
||||
mVal.setText(sensor.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checked state change for the associated CheckBox. If check
|
||||
* box is checked we will register sensor change listener. If it is
|
||||
* unchecked, we will unregister sensor change listener.
|
||||
*/
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (mSensor != null) {
|
||||
mSensor.onCheckedChanged(isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
mChk = null;
|
||||
mVal = null;
|
||||
mSensor = null;
|
||||
|
||||
}
|
||||
|
||||
public void updateState() {
|
||||
if (mChk != null && mSensor != null) {
|
||||
mChk.setEnabled(mSensor.isEnabledByEmulator());
|
||||
mChk.setChecked(mSensor.isEnabledByUser());
|
||||
}
|
||||
}
|
||||
|
||||
public void updateValue() {
|
||||
if (mVal != null && mSensor != null) {
|
||||
mVal.setText(mSensor.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of Handler.Callback */
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
DisplayInfo info = null;
|
||||
switch (msg.what) {
|
||||
case SensorChannel.SENSOR_STATE_CHANGED:
|
||||
info = mDisplayedSensors.get(msg.obj);
|
||||
if (info != null) {
|
||||
info.updateState();
|
||||
}
|
||||
break;
|
||||
case SensorChannel.SENSOR_DISPLAY_MODIFIED:
|
||||
info = mDisplayedSensors.get(msg.obj);
|
||||
if (info != null) {
|
||||
info.updateValue();
|
||||
}
|
||||
if (mSensorHandler != null) {
|
||||
updateStatus(Integer.toString(mSensorHandler.getMsgSentCount()) + " events sent");
|
||||
|
||||
// Update the "actual rate" field if the value has changed
|
||||
long ms = mSensorHandler.getActualUpdateMs();
|
||||
if (ms != mLastActualUpdateMs) {
|
||||
mLastActualUpdateMs = ms;
|
||||
String hz = mLastActualUpdateMs <= 0 ? "--" :
|
||||
Integer.toString((int) Math.ceil(1000. / ms));
|
||||
mTextActualHz.setText(hz);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSG_UPDATE_ACTUAL_HZ:
|
||||
if (mSensorHandler != null) {
|
||||
// Update the "actual rate" field if the value has changed
|
||||
long ms = mSensorHandler.getActualUpdateMs();
|
||||
if (ms != mLastActualUpdateMs) {
|
||||
mLastActualUpdateMs = ms;
|
||||
String hz = mLastActualUpdateMs <= 0 ? "--" :
|
||||
Integer.toString((int) Math.ceil(1000. / ms));
|
||||
mTextActualHz.setText(hz);
|
||||
}
|
||||
mUiHandler.sendEmptyMessageDelayed(MSG_UPDATE_ACTUAL_HZ, 1000 /*1s*/);
|
||||
}
|
||||
}
|
||||
return true; // we consumed this message
|
||||
}
|
||||
|
||||
private void updateStatus(String status) {
|
||||
mTextStatus.setVisibility(status == null ? View.GONE : View.VISIBLE);
|
||||
if (status != null) mTextStatus.setText(status);
|
||||
}
|
||||
|
||||
private void updateError() {
|
||||
ControllerBinder binder = getServiceBinder();
|
||||
String error = binder == null ? "" : binder.getServiceError();
|
||||
if (error == null) {
|
||||
error = "";
|
||||
}
|
||||
|
||||
mTextError.setVisibility(error.length() == 0 ? View.GONE : View.VISIBLE);
|
||||
mTextError.setText(error);
|
||||
}
|
||||
|
||||
private void updateSampleRate() {
|
||||
String str = mTextTargetHz.getText().toString();
|
||||
try {
|
||||
int hz = Integer.parseInt(str.trim());
|
||||
|
||||
// Cap the value. 50 Hz is a reasonable max value for the emulator.
|
||||
if (hz <= 0 || hz > 50) {
|
||||
hz = 50;
|
||||
}
|
||||
|
||||
if (hz != mTargetSampleRate) {
|
||||
mTargetSampleRate = hz;
|
||||
if (mSensorHandler != null) {
|
||||
mSensorHandler.setUpdateTargetMs(hz <= 0 ? 0 : (int)(1000.0f / hz));
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.handlers;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.tools.sdkcontroller.lib.Channel;
|
||||
import com.android.tools.sdkcontroller.lib.ProtocolConstants;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Implements multi-touch emulation.
|
||||
*/
|
||||
public class MultiTouchChannel extends Channel {
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private static final String TAG = MultiTouchChannel.class.getSimpleName();
|
||||
/**
|
||||
* A new frame buffer has been received from the emulator.
|
||||
* Parameter {@code obj} is a {@code byte[] array} containing the screen data.
|
||||
*/
|
||||
public static final int EVENT_FRAME_BUFFER = 1;
|
||||
/**
|
||||
* A multi-touch "start" command has been received from the emulator.
|
||||
* Parameter {@code obj} is the string parameter from the start command.
|
||||
*/
|
||||
public static final int EVENT_MT_START = 2;
|
||||
/**
|
||||
* A multi-touch "stop" command has been received from the emulator. There
|
||||
* is no {@code obj} parameter associated.
|
||||
*/
|
||||
public static final int EVENT_MT_STOP = 3;
|
||||
|
||||
private static final Point mViewSize = new Point(0, 0);
|
||||
|
||||
/**
|
||||
* Constructs MultiTouchChannel instance.
|
||||
*/
|
||||
public MultiTouchChannel(ControllerService service) {
|
||||
super(service, Channel.MULTITOUCH_CHANNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets size of the display view for emulated screen updates.
|
||||
*
|
||||
* @param width View width in pixels.
|
||||
* @param height View height in pixels.
|
||||
*/
|
||||
public void setViewSize(int width, int height) {
|
||||
mViewSize.set(width, height);
|
||||
}
|
||||
|
||||
/*
|
||||
* Channel abstract implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method is invoked when this channel is fully connected with its
|
||||
* counterpart in the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorConnected() {
|
||||
if (hasUiHandler()) {
|
||||
enable();
|
||||
notifyUiHandlers(EVENT_MT_START);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when this channel loses connection with its
|
||||
* counterpart in the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorDisconnected() {
|
||||
if (hasUiHandler()) {
|
||||
disable();
|
||||
notifyUiHandlers(EVENT_MT_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A message has been received from the emulator.
|
||||
*
|
||||
* @param msg_type Message type.
|
||||
* @param msg_data Packet received from the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) {
|
||||
switch (msg_type) {
|
||||
case ProtocolConstants.MT_FB_UPDATE:
|
||||
Message msg = Message.obtain();
|
||||
msg.what = EVENT_FRAME_BUFFER;
|
||||
msg.obj = msg_data;
|
||||
postMessage(ProtocolConstants.MT_FB_ACK, (byte[]) null);
|
||||
notifyUiHandlers(msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e(TAG, "Unknown message type " + msg_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A query has been received from the emulator.
|
||||
*
|
||||
* @param query_id Identifies the query. This ID must be used when replying
|
||||
* to the query.
|
||||
* @param query_type Query type.
|
||||
* @param query_data Query data.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) {
|
||||
Loge("Unexpected query " + query_type + " in multi-touch");
|
||||
sendQueryResponse(query_id, (byte[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new UI handler.
|
||||
*
|
||||
* @param uiHandler A non-null UI handler to register. Ignored if the UI
|
||||
* handler is null or already registered.
|
||||
*/
|
||||
@Override
|
||||
public void addUiHandler(android.os.Handler uiHandler) {
|
||||
final boolean first_handler = !hasUiHandler();
|
||||
super.addUiHandler(uiHandler);
|
||||
if (first_handler && isConnected()) {
|
||||
enable();
|
||||
notifyUiHandlers(EVENT_MT_START);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an UI handler.
|
||||
*
|
||||
* @param uiHandler A non-null UI listener to unregister. Ignored if the
|
||||
* listener is null or already registered.
|
||||
*/
|
||||
@Override
|
||||
public void removeUiHandler(android.os.Handler uiHandler) {
|
||||
super.removeUiHandler(uiHandler);
|
||||
if (isConnected() && !hasUiHandler()) {
|
||||
disable();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Logging wrappers
|
||||
**************************************************************************/
|
||||
|
||||
private void Loge(String log) {
|
||||
mService.addError(log);
|
||||
Log.e(TAG, log);
|
||||
}
|
||||
}
|
@ -0,0 +1,675 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.handlers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.tools.sdkcontroller.lib.Channel;
|
||||
import com.android.tools.sdkcontroller.lib.ProtocolConstants;
|
||||
import com.android.tools.sdkcontroller.service.ControllerService;
|
||||
|
||||
/**
|
||||
* Implements sensors emulation.
|
||||
*/
|
||||
public class SensorChannel extends Channel {
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private static String TAG = SensorChannel.class.getSimpleName();
|
||||
@SuppressWarnings("hiding")
|
||||
private static boolean DEBUG = false;
|
||||
/**
|
||||
* The target update time per sensor. Ignored if 0 or negative.
|
||||
* Sensor updates that arrive faster than this delay are ignored.
|
||||
* Ideally the emulator can be updated at up to 50 fps, however
|
||||
* for average power devices something like 20 fps is more
|
||||
* reasonable.
|
||||
* Default value should match res/values/strings.xml > sensors_default_sample_rate.
|
||||
*/
|
||||
private long mUpdateTargetMs = 1000/20; // 20 fps in milliseconds
|
||||
/** Accumulates average update frequency. */
|
||||
private long mGlobalAvgUpdateMs = 0;
|
||||
|
||||
/** Array containing monitored sensors. */
|
||||
private final List<MonitoredSensor> mSensors = new ArrayList<MonitoredSensor>();
|
||||
/** Sensor manager. */
|
||||
private SensorManager mSenMan;
|
||||
|
||||
/*
|
||||
* Messages exchanged with the UI.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sensor "enabled by emulator" state has changed. Parameter {@code obj} is
|
||||
* the {@link MonitoredSensor}.
|
||||
*/
|
||||
public static final int SENSOR_STATE_CHANGED = 1;
|
||||
/**
|
||||
* Sensor display value has changed. Parameter {@code obj} is the
|
||||
* {@link MonitoredSensor}.
|
||||
*/
|
||||
public static final int SENSOR_DISPLAY_MODIFIED = 2;
|
||||
|
||||
/**
|
||||
* Constructs SensorChannel instance.
|
||||
*
|
||||
* @param service Service context.
|
||||
*/
|
||||
public SensorChannel(ControllerService service) {
|
||||
super(service, Channel.SENSOR_CHANNEL);
|
||||
mSenMan = (SensorManager) service.getSystemService(Context.SENSOR_SERVICE);
|
||||
// Iterate through the available sensors, adding them to the array.
|
||||
List<Sensor> sensors = mSenMan.getSensorList(Sensor.TYPE_ALL);
|
||||
int cur_index = 0;
|
||||
for (int n = 0; n < sensors.size(); n++) {
|
||||
Sensor avail_sensor = sensors.get(n);
|
||||
|
||||
// There can be multiple sensors of the same type. We need only one.
|
||||
if (!isSensorTypeAlreadyMonitored(avail_sensor.getType())) {
|
||||
// The first sensor we've got for the given type is not
|
||||
// necessarily the right one. So, use the default sensor
|
||||
// for the given type.
|
||||
Sensor def_sens = mSenMan.getDefaultSensor(avail_sensor.getType());
|
||||
MonitoredSensor to_add = new MonitoredSensor(def_sens);
|
||||
cur_index++;
|
||||
mSensors.add(to_add);
|
||||
if (DEBUG)
|
||||
Log.d(TAG, String.format(
|
||||
"Monitoring sensor #%02d: Name = '%s', Type = 0x%x",
|
||||
cur_index, def_sens.getName(), def_sens.getType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of sensors found on the device.
|
||||
* The list is computed once by {@link #SensorChannel(ControllerService)}.
|
||||
*
|
||||
* @return A non-null possibly-empty list of sensors.
|
||||
*/
|
||||
public List<MonitoredSensor> getSensors() {
|
||||
return mSensors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the target update delay throttling per-sensor, in milliseconds.
|
||||
* <p/>
|
||||
* For example setting it to 1000/50 means that updates for a <em>given</em> sensor
|
||||
* faster than 50 fps is discarded.
|
||||
*
|
||||
* @param updateTargetMs 0 to disable throttling, otherwise a > 0 millisecond minimum
|
||||
* between sensor updates.
|
||||
*/
|
||||
public void setUpdateTargetMs(long updateTargetMs) {
|
||||
mUpdateTargetMs = updateTargetMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual average time in milliseconds between same-sensor updates.
|
||||
*
|
||||
* @return The actual average time in milliseconds between same-sensor updates or 0.
|
||||
*/
|
||||
public long getActualUpdateMs() {
|
||||
return mGlobalAvgUpdateMs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Channel abstract implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method is invoked when this channel is fully connected with its
|
||||
* counterpart in the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorConnected() {
|
||||
// Emulation is now possible. Note though that it will start only after
|
||||
// emulator tells us so with SENSORS_START command.
|
||||
enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when this channel loses connection with its
|
||||
* counterpart in the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorDisconnected() {
|
||||
// Stop sensor event callbacks.
|
||||
stopSensors();
|
||||
}
|
||||
|
||||
/**
|
||||
* A query has been received from the emulator.
|
||||
*
|
||||
* @param query_id Identifies the query. This ID should be used when
|
||||
* replying to the query.
|
||||
* @param query_type Query type.
|
||||
* @param query_data Query data.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorQuery(int query_id, int query_type, ByteBuffer query_data) {
|
||||
switch (query_type) {
|
||||
case ProtocolConstants.SENSORS_QUERY_LIST:
|
||||
// Preallocate large response buffer.
|
||||
ByteBuffer resp = ByteBuffer.allocate(1024);
|
||||
resp.order(getEndian());
|
||||
// Iterate through the list of monitored sensors, dumping them
|
||||
// into the response buffer.
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
// Entry for each sensor must contain:
|
||||
// - an integer for its ID
|
||||
// - a zero-terminated emulator-friendly name.
|
||||
final byte[] name = sensor.getEmulatorFriendlyName().getBytes();
|
||||
final int required_size = 4 + name.length + 1;
|
||||
resp = ExpandIf(resp, required_size);
|
||||
resp.putInt(sensor.getType());
|
||||
resp.put(name);
|
||||
resp.put((byte) 0);
|
||||
}
|
||||
// Terminating entry contains single -1 integer.
|
||||
resp = ExpandIf(resp, 4);
|
||||
resp.putInt(-1);
|
||||
sendQueryResponse(query_id, resp);
|
||||
return;
|
||||
|
||||
default:
|
||||
Loge("Unknown query " + query_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A message has been received from the emulator.
|
||||
*
|
||||
* @param msg_type Message type.
|
||||
* @param msg_data Packet received from the emulator.
|
||||
*/
|
||||
@Override
|
||||
public void onEmulatorMessage(int msg_type, ByteBuffer msg_data) {
|
||||
switch (msg_type) {
|
||||
case ProtocolConstants.SENSORS_START:
|
||||
Log.v(TAG, "Starting sensors emulation.");
|
||||
startSensors();
|
||||
break;
|
||||
case ProtocolConstants.SENSORS_STOP:
|
||||
Log.v(TAG, "Stopping sensors emulation.");
|
||||
stopSensors();
|
||||
break;
|
||||
case ProtocolConstants.SENSORS_ENABLE:
|
||||
String enable_name = new String(msg_data.array());
|
||||
Log.v(TAG, "Enabling sensor: " + enable_name);
|
||||
onEnableSensor(enable_name);
|
||||
break;
|
||||
case ProtocolConstants.SENSORS_DISABLE:
|
||||
String disable_name = new String(msg_data.array());
|
||||
Log.v(TAG, "Disabling sensor: " + disable_name);
|
||||
onDisableSensor(disable_name);
|
||||
break;
|
||||
default:
|
||||
Loge("Unknown message type " + msg_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles 'enable' message.
|
||||
*
|
||||
* @param name Emulator-friendly name of a sensor to enable, or "all" to
|
||||
* enable all sensors.
|
||||
*/
|
||||
private void onEnableSensor(String name) {
|
||||
if (name.contentEquals("all")) {
|
||||
// Enable all sensors.
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
sensor.enableSensor();
|
||||
}
|
||||
} else {
|
||||
// Lookup sensor by emulator-friendly name.
|
||||
final MonitoredSensor sensor = getSensorByEFN(name);
|
||||
if (sensor != null) {
|
||||
sensor.enableSensor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles 'disable' message.
|
||||
*
|
||||
* @param name Emulator-friendly name of a sensor to disable, or "all" to
|
||||
* disable all sensors.
|
||||
*/
|
||||
private void onDisableSensor(String name) {
|
||||
if (name.contentEquals("all")) {
|
||||
// Disable all sensors.
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
sensor.disableSensor();
|
||||
}
|
||||
} else {
|
||||
// Lookup sensor by emulator-friendly name.
|
||||
MonitoredSensor sensor = getSensorByEFN(name);
|
||||
if (sensor != null) {
|
||||
sensor.disableSensor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start listening to all monitored sensors.
|
||||
*/
|
||||
private void startSensors() {
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
sensor.startListening();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop listening to all monitored sensors.
|
||||
*/
|
||||
private void stopSensors() {
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
sensor.stopListening();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Internals
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Checks if a sensor for the given type is already monitored.
|
||||
*
|
||||
* @param type Sensor type (one of the Sensor.TYPE_XXX constants)
|
||||
* @return true if a sensor for the given type is already monitored, or
|
||||
* false if the sensor is not monitored.
|
||||
*/
|
||||
private boolean isSensorTypeAlreadyMonitored(int type) {
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
if (sensor.getType() == type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a monitored sensor by its emulator-friendly name.
|
||||
*
|
||||
* @param name Emulator-friendly name to look up the monitored sensor for.
|
||||
* @return Monitored sensor for the fiven name, or null if sensor was not
|
||||
* found.
|
||||
*/
|
||||
private MonitoredSensor getSensorByEFN(String name) {
|
||||
for (MonitoredSensor sensor : mSensors) {
|
||||
if (sensor.mEmulatorFriendlyName.contentEquals(name)) {
|
||||
return sensor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates a sensor that is being monitored. To monitor sensor changes
|
||||
* each monitored sensor registers with sensor manager as a sensor listener.
|
||||
* To control sensor monitoring from the UI, each monitored sensor has two
|
||||
* UI controls associated with it: - A check box (named after sensor) that
|
||||
* can be used to enable, or disable listening to the sensor changes. - A
|
||||
* text view where current sensor value is displayed.
|
||||
*/
|
||||
public class MonitoredSensor {
|
||||
/** Sensor to monitor. */
|
||||
private final Sensor mSensor;
|
||||
/** The sensor name to display in the UI. */
|
||||
private String mUiName = "";
|
||||
/** Text view displaying the value of the sensor. */
|
||||
private String mValue = null;
|
||||
/** Emulator-friendly name for the sensor. */
|
||||
private String mEmulatorFriendlyName;
|
||||
/** Formats string to show in the TextView. */
|
||||
private String mTextFmt;
|
||||
/** Sensor values. */
|
||||
private float[] mValues = new float[3];
|
||||
/**
|
||||
* Enabled state. This state is controlled by the emulator, that
|
||||
* maintains its own list of sensors. So, if a sensor is missing, or is
|
||||
* disabled in the emulator, it should be disabled in this application.
|
||||
*/
|
||||
private boolean mEnabledByEmulator = false;
|
||||
/** User-controlled enabled state. */
|
||||
private boolean mEnabledByUser = true;
|
||||
/** Sensor event listener for this sensor. */
|
||||
private final OurSensorEventListener mListener = new OurSensorEventListener();
|
||||
|
||||
/**
|
||||
* Constructs MonitoredSensor instance, and register the listeners.
|
||||
*
|
||||
* @param sensor Sensor to monitor.
|
||||
*/
|
||||
MonitoredSensor(Sensor sensor) {
|
||||
mSensor = sensor;
|
||||
mEnabledByUser = true;
|
||||
|
||||
// Set appropriate sensor name depending on the type. Unfortunately,
|
||||
// we can't really use sensor.getName() here, since the value it
|
||||
// returns (although resembles the purpose) is a bit vaguer than it
|
||||
// should be. Also choose an appropriate format for the strings that
|
||||
// display sensor's value.
|
||||
switch (sensor.getType()) {
|
||||
case Sensor.TYPE_ACCELEROMETER:
|
||||
mUiName = "Accelerometer";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "acceleration";
|
||||
break;
|
||||
case 9: // Sensor.TYPE_GRAVITY is missing in API 7
|
||||
mUiName = "Gravity";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "gravity";
|
||||
break;
|
||||
case Sensor.TYPE_GYROSCOPE:
|
||||
mUiName = "Gyroscope";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "gyroscope";
|
||||
break;
|
||||
case Sensor.TYPE_LIGHT:
|
||||
mUiName = "Light";
|
||||
mTextFmt = "%.0f";
|
||||
mEmulatorFriendlyName = "light";
|
||||
break;
|
||||
case 10: // Sensor.TYPE_LINEAR_ACCELERATION is missing in API 7
|
||||
mUiName = "Linear acceleration";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "linear-acceleration";
|
||||
break;
|
||||
case Sensor.TYPE_MAGNETIC_FIELD:
|
||||
mUiName = "Magnetic field";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "magnetic-field";
|
||||
break;
|
||||
case Sensor.TYPE_ORIENTATION:
|
||||
mUiName = "Orientation";
|
||||
mTextFmt = "%+03.0f %+03.0f %+03.0f";
|
||||
mEmulatorFriendlyName = "orientation";
|
||||
break;
|
||||
case Sensor.TYPE_PRESSURE:
|
||||
mUiName = "Pressure";
|
||||
mTextFmt = "%.0f";
|
||||
mEmulatorFriendlyName = "pressure";
|
||||
break;
|
||||
case Sensor.TYPE_PROXIMITY:
|
||||
mUiName = "Proximity";
|
||||
mTextFmt = "%.0f";
|
||||
mEmulatorFriendlyName = "proximity";
|
||||
break;
|
||||
case 11: // Sensor.TYPE_ROTATION_VECTOR is missing in API 7
|
||||
mUiName = "Rotation";
|
||||
mTextFmt = "%+.2f %+.2f %+.2f";
|
||||
mEmulatorFriendlyName = "rotation";
|
||||
break;
|
||||
case Sensor.TYPE_TEMPERATURE:
|
||||
mUiName = "Temperature";
|
||||
mTextFmt = "%.0f";
|
||||
mEmulatorFriendlyName = "temperature";
|
||||
break;
|
||||
default:
|
||||
mUiName = "<Unknown>";
|
||||
mTextFmt = "N/A";
|
||||
mEmulatorFriendlyName = "unknown";
|
||||
if (DEBUG) Loge("Unknown sensor type " + mSensor.getType() +
|
||||
" for sensor " + mSensor.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get name for this sensor to display.
|
||||
*
|
||||
* @return Name for this sensor to display.
|
||||
*/
|
||||
public String getUiName() {
|
||||
return mUiName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current sensor value to display.
|
||||
*
|
||||
* @return Current sensor value to display.
|
||||
*/
|
||||
public String getValue() {
|
||||
if (mValue == null) {
|
||||
float[] values = mValues;
|
||||
mValue = String.format(mTextFmt, values[0], values[1], values[2]);
|
||||
}
|
||||
return mValue == null ? "??" : mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if monitoring of this this sensor has been enabled by
|
||||
* emulator.
|
||||
*
|
||||
* @return true if monitoring of this this sensor has been enabled by
|
||||
* emulator, or false if emulator didn't enable this sensor.
|
||||
*/
|
||||
public boolean isEnabledByEmulator() {
|
||||
return mEnabledByEmulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if monitoring of this this sensor has been enabled by user.
|
||||
*
|
||||
* @return true if monitoring of this this sensor has been enabled by
|
||||
* user, or false if user didn't enable this sensor.
|
||||
*/
|
||||
public boolean isEnabledByUser() {
|
||||
return mEnabledByUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checked state change for the associated CheckBox. If check
|
||||
* box is checked we will register sensor change listener. If it is
|
||||
* unchecked, we will unregister sensor change listener.
|
||||
*/
|
||||
public void onCheckedChanged(boolean isChecked) {
|
||||
mEnabledByUser = isChecked;
|
||||
if (isChecked) {
|
||||
startListening();
|
||||
} else {
|
||||
stopListening();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sensor type.
|
||||
*
|
||||
* @return Sensor type as one of the Sensor.TYPE_XXX constants.
|
||||
*/
|
||||
private int getType() {
|
||||
return mSensor.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sensor's emulator-friendly name.
|
||||
*
|
||||
* @return Sensor's emulator-friendly name.
|
||||
*/
|
||||
private String getEmulatorFriendlyName() {
|
||||
return mEmulatorFriendlyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts monitoring the sensor.
|
||||
* NOTE: This method is called from outside of the UI thread.
|
||||
*/
|
||||
private void startListening() {
|
||||
if (mEnabledByEmulator && mEnabledByUser) {
|
||||
if (DEBUG) Log.d(TAG, "+++ Sensor " + getEmulatorFriendlyName() + " is started.");
|
||||
mSenMan.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_FASTEST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops monitoring the sensor.
|
||||
* NOTE: This method is called from outside of the UI thread.
|
||||
*/
|
||||
private void stopListening() {
|
||||
if (DEBUG) Log.d(TAG, "--- Sensor " + getEmulatorFriendlyName() + " is stopped.");
|
||||
mSenMan.unregisterListener(mListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables sensor events.
|
||||
* NOTE: This method is called from outside of the UI thread.
|
||||
*/
|
||||
private void enableSensor() {
|
||||
if (DEBUG) Log.d(TAG, ">>> Sensor " + getEmulatorFriendlyName() + " is enabled.");
|
||||
mEnabledByEmulator = true;
|
||||
mValue = null;
|
||||
|
||||
Message msg = Message.obtain();
|
||||
msg.what = SENSOR_STATE_CHANGED;
|
||||
msg.obj = MonitoredSensor.this;
|
||||
notifyUiHandlers(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables sensor events.
|
||||
* NOTE: This method is called from outside of the UI thread.
|
||||
*/
|
||||
private void disableSensor() {
|
||||
if (DEBUG) Log.w(TAG, "<<< Sensor " + getEmulatorFriendlyName() + " is disabled.");
|
||||
mEnabledByEmulator = false;
|
||||
mValue = "Disabled by emulator";
|
||||
|
||||
Message msg = Message.obtain();
|
||||
msg.what = SENSOR_STATE_CHANGED;
|
||||
msg.obj = MonitoredSensor.this;
|
||||
notifyUiHandlers(msg);
|
||||
}
|
||||
|
||||
private class OurSensorEventListener implements SensorEventListener {
|
||||
/** Last update's time-stamp in local thread millisecond time. */
|
||||
private long mLastUpdateTS = 0;
|
||||
/** Last display update time-stamp. */
|
||||
private long mLastDisplayTS = 0;
|
||||
/** Preallocated buffer for change notification message. */
|
||||
private final ByteBuffer mChangeMsg = ByteBuffer.allocate(64);
|
||||
|
||||
/**
|
||||
* Handles "sensor changed" event.
|
||||
* This is an implementation of the SensorEventListener interface.
|
||||
*/
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
|
||||
long deltaMs = 0;
|
||||
if (mLastUpdateTS != 0) {
|
||||
deltaMs = now - mLastUpdateTS;
|
||||
if (mUpdateTargetMs > 0 && deltaMs < mUpdateTargetMs) {
|
||||
// New sample is arriving too fast. Discard it.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Format and post message for the emulator.
|
||||
float[] values = event.values;
|
||||
final int len = values.length;
|
||||
|
||||
mChangeMsg.order(getEndian());
|
||||
mChangeMsg.position(0);
|
||||
mChangeMsg.putInt(getType());
|
||||
mChangeMsg.putFloat(values[0]);
|
||||
if (len > 1) {
|
||||
mChangeMsg.putFloat(values[1]);
|
||||
if (len > 2) {
|
||||
mChangeMsg.putFloat(values[2]);
|
||||
}
|
||||
}
|
||||
postMessage(ProtocolConstants.SENSORS_SENSOR_EVENT, mChangeMsg);
|
||||
|
||||
// Computes average update time for this sensor and average globally.
|
||||
if (mLastUpdateTS != 0) {
|
||||
if (mGlobalAvgUpdateMs != 0) {
|
||||
mGlobalAvgUpdateMs = (mGlobalAvgUpdateMs + deltaMs) / 2;
|
||||
} else {
|
||||
mGlobalAvgUpdateMs = deltaMs;
|
||||
}
|
||||
}
|
||||
mLastUpdateTS = now;
|
||||
|
||||
// Update the UI for the sensor, with a static throttling of 10 fps max.
|
||||
if (hasUiHandler()) {
|
||||
if (mLastDisplayTS != 0) {
|
||||
long uiDeltaMs = now - mLastDisplayTS;
|
||||
if (uiDeltaMs < 1000 / 4 /* 4fps in ms */) {
|
||||
// Skip this UI update
|
||||
return;
|
||||
}
|
||||
}
|
||||
mLastDisplayTS = now;
|
||||
|
||||
mValues[0] = values[0];
|
||||
if (len > 1) {
|
||||
mValues[1] = values[1];
|
||||
if (len > 2) {
|
||||
mValues[2] = values[2];
|
||||
}
|
||||
}
|
||||
mValue = null;
|
||||
|
||||
Message msg = Message.obtain();
|
||||
msg.what = SENSOR_DISPLAY_MODIFIED;
|
||||
msg.obj = MonitoredSensor.this;
|
||||
notifyUiHandlers(msg);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
long now2 = SystemClock.elapsedRealtime();
|
||||
long processingTimeMs = now2 - now;
|
||||
Log.d(TAG, String.format("glob %d - local %d > target %d - processing %d -- %s",
|
||||
mGlobalAvgUpdateMs, deltaMs, mUpdateTargetMs, processingTimeMs,
|
||||
mSensor.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles "sensor accuracy changed" event.
|
||||
* This is an implementation of the SensorEventListener interface.
|
||||
*/
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
}
|
||||
} // MonitoredSensor
|
||||
|
||||
/***************************************************************************
|
||||
* Logging wrappers
|
||||
**************************************************************************/
|
||||
|
||||
private void Loge(String log) {
|
||||
mService.addError(log);
|
||||
Log.e(TAG, log);
|
||||
}
|
||||
}
|
@ -0,0 +1,795 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,412 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
// 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;
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.tools.sdkcontroller.R;
|
||||
import com.android.tools.sdkcontroller.activities.MainActivity;
|
||||
import com.android.tools.sdkcontroller.handlers.MultiTouchChannel;
|
||||
import com.android.tools.sdkcontroller.handlers.SensorChannel;
|
||||
import com.android.tools.sdkcontroller.lib.Connection;
|
||||
import com.android.tools.sdkcontroller.lib.Channel;
|
||||
|
||||
/**
|
||||
* The background service of the SdkController.
|
||||
* There can be only one instance of this.
|
||||
* <p/>
|
||||
* The service manages a number of SDK controller channels which can be seen as
|
||||
* individual tasks that the user might want to accomplish, for example "sending
|
||||
* sensor data to the emulator" or "sending multi-touch data and displaying an
|
||||
* emulator screen".
|
||||
* <p/>
|
||||
* Each channel connects to the emulator via UNIX-domain socket that is bound to
|
||||
* "android.sdk.controller" port. Connection class provides a socket server that
|
||||
* listens to emulator connections on this port, and binds new connection with a
|
||||
* channel, based on channel name.
|
||||
* <p/>
|
||||
* All the channels are created when the service starts, and whether the emulator
|
||||
* connection is successful or not, and whether there's any UI to control it.
|
||||
* It's up to the channels to deal with these specific details. <br/>
|
||||
* For example the {@link SensorChannel} initializes its sensor list as soon as
|
||||
* created and then tries to send data as soon as there's an emulator
|
||||
* connection. On the other hand the {@link MultiTouchChannel} lays dormant till
|
||||
* there's an UI interacting with it.
|
||||
*/
|
||||
public class ControllerService extends Service {
|
||||
|
||||
/*
|
||||
* Implementation reference:
|
||||
* http://developer.android.com/reference/android/app/Service.html#LocalServiceSample
|
||||
*/
|
||||
|
||||
/** Tag for logging messages. */
|
||||
public static String TAG = ControllerService.class.getSimpleName();
|
||||
/** Controls debug log. */
|
||||
private static boolean DEBUG = true;
|
||||
/** Identifier for the notification. */
|
||||
private static int NOTIF_ID = 'S' << 24 + 'd' << 16 + 'k' << 8 + 'C' << 0;
|
||||
|
||||
/** Connection to the emulator. */
|
||||
public Connection mConnection;
|
||||
|
||||
|
||||
private final IBinder mBinder = new ControllerBinder();
|
||||
|
||||
private List<ControllerListener> mListeners = new ArrayList<ControllerListener>();
|
||||
|
||||
/**
|
||||
* Whether the service is running. Set to true in onCreate, false in onDestroy.
|
||||
*/
|
||||
private static volatile boolean gServiceIsRunning = false;
|
||||
|
||||
/** Internal error reported by the service. */
|
||||
private String mServiceError = "";
|
||||
|
||||
/**
|
||||
* Interface that the service uses to notify binded activities.
|
||||
* <p/>
|
||||
* As a design rule, implementations of this listener should be aware that most calls
|
||||
* will NOT happen on the UI thread. Any access to the UI should be properly protected
|
||||
* by using {@link Activity#runOnUiThread(Runnable)}.
|
||||
*/
|
||||
public interface ControllerListener {
|
||||
/**
|
||||
* The error string reported by the service has changed. <br/>
|
||||
* Note this may be called from a thread different than the UI thread.
|
||||
*/
|
||||
void onErrorChanged();
|
||||
|
||||
/**
|
||||
* The service status has changed (emulator connected/disconnected.)
|
||||
*/
|
||||
void onStatusChanged();
|
||||
}
|
||||
|
||||
/** Interface that callers can use to access the service. */
|
||||
public class ControllerBinder extends Binder {
|
||||
|
||||
/**
|
||||
* Adds a new listener that will be notified when the service state changes.
|
||||
*
|
||||
* @param listener A non-null listener. Ignored if already listed.
|
||||
*/
|
||||
public void addControllerListener(ControllerListener listener) {
|
||||
assert listener != null;
|
||||
if (listener != null) {
|
||||
synchronized (mListeners) {
|
||||
if (!mListeners.contains(listener)) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener.
|
||||
*
|
||||
* @param listener A listener to remove. Can be null.
|
||||
*/
|
||||
public void removeControllerListener(ControllerListener listener) {
|
||||
assert listener != null;
|
||||
synchronized (mListeners) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error string accumulated by the service.
|
||||
* Typically these would relate to failures to establish the communication
|
||||
* channel(s) with the emulator, or unexpected disconnections.
|
||||
*/
|
||||
public String getServiceError() {
|
||||
return mServiceError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates when <em>any</all> of the SDK controller channels is connected
|
||||
* with the emulator.
|
||||
*
|
||||
* @return True if any of the SDK controller channels is connected with the
|
||||
* emulator.
|
||||
*/
|
||||
public boolean isEmuConnected() {
|
||||
return mConnection.isEmulatorConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the channel instance for the given type.
|
||||
*
|
||||
* @param name One of the channel names. Must not be null.
|
||||
* @return Null if the type is not found, otherwise the handler's unique instance.
|
||||
*/
|
||||
public Channel getChannel(String name) {
|
||||
return mConnection.getChannel(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the service is running. Set to true in onCreate, false in onDestroy.
|
||||
*/
|
||||
public static boolean isServiceIsRunning() {
|
||||
return gServiceIsRunning;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (DEBUG) Log.d(TAG, "Service onCreate");
|
||||
gServiceIsRunning = true;
|
||||
showNotification();
|
||||
onServiceStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// We want this service to continue running until it is explicitly
|
||||
// stopped, so return sticky.
|
||||
if (DEBUG) Log.d(TAG, "Service onStartCommand");
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "Service onBind");
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (DEBUG) Log.d(TAG, "Service onDestroy");
|
||||
gServiceIsRunning = false;
|
||||
removeNotification();
|
||||
resetError();
|
||||
onServiceStopped();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void disconnectAll() {
|
||||
if (mConnection != null) {
|
||||
mConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service has been created.
|
||||
*/
|
||||
private void onServiceStarted() {
|
||||
try {
|
||||
disconnectAll();
|
||||
|
||||
// Bind to SDK controller port, and start accepting emulator
|
||||
// connections.
|
||||
mConnection = new Connection(ControllerService.this);
|
||||
mConnection.connect();
|
||||
|
||||
// Create and register sensors channel.
|
||||
mConnection.registerChannel(new SensorChannel(ControllerService.this));
|
||||
// Create and register multi-touch channel.
|
||||
mConnection.registerChannel(new MultiTouchChannel(ControllerService.this));
|
||||
} catch (Exception e) {
|
||||
addError("Connection failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is being destroyed.
|
||||
*/
|
||||
private void onServiceStopped() {
|
||||
disconnectAll();
|
||||
}
|
||||
|
||||
private void notifyErrorChanged() {
|
||||
synchronized (mListeners) {
|
||||
for (ControllerListener listener : mListeners) {
|
||||
listener.onErrorChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyStatusChanged() {
|
||||
synchronized (mListeners) {
|
||||
for (ControllerListener listener : mListeners) {
|
||||
listener.onStatusChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error string and notify listeners.
|
||||
*/
|
||||
private void resetError() {
|
||||
mServiceError = "";
|
||||
|
||||
notifyErrorChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal utility method to add a line to the error string and notify listeners.
|
||||
* @param error A non-null non-empty error line. \n will be added automatically.
|
||||
*/
|
||||
public void addError(String error) {
|
||||
Log.e(TAG, error);
|
||||
if (mServiceError.length() > 0) {
|
||||
mServiceError += "\n";
|
||||
}
|
||||
mServiceError += error;
|
||||
|
||||
notifyErrorChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a notification showing that the service is running.
|
||||
* When the user touches the notification, it opens the main activity
|
||||
* which allows the user to stop this service.
|
||||
*/
|
||||
@SuppressWarnings("deprecated")
|
||||
private void showNotification() {
|
||||
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
|
||||
String text = getString(R.string.service_notif_title);
|
||||
|
||||
// Note: Notification is marked as deprecated -- in API 11+ there's a new Builder class
|
||||
// but we need to have API 7 compatibility so we ignore that warning.
|
||||
|
||||
Notification n = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis());
|
||||
n.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
PendingIntent pi = PendingIntent.getActivity(
|
||||
this, //context
|
||||
0, //requestCode
|
||||
intent, //intent
|
||||
0 //pending intent flags
|
||||
);
|
||||
n.setLatestEventInfo(this, text, text, pi);
|
||||
|
||||
nm.notify(NOTIF_ID, n);
|
||||
}
|
||||
|
||||
private void removeNotification() {
|
||||
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
nm.cancel(NOTIF_ID);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Helper to deal with methods only available at certain API levels.
|
||||
* Users should get use {@link ApiHelper#get()} to retrieve a singleton
|
||||
* and then call the methods they desire. If the method is not available
|
||||
* on the current API level, a stub or a nop will be used instead.
|
||||
*/
|
||||
@TargetApi(7)
|
||||
public class ApiHelper {
|
||||
|
||||
private static ApiHelper sApiHelper = null;
|
||||
|
||||
/** Creates a new ApiHelper adapted to the current runtime API level. */
|
||||
public static ApiHelper get() {
|
||||
if (sApiHelper == null) {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
sApiHelper = new ApiHelper_11();
|
||||
} else {
|
||||
sApiHelper = new ApiHelper();
|
||||
}
|
||||
}
|
||||
|
||||
return sApiHelper;
|
||||
}
|
||||
|
||||
protected ApiHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11.
|
||||
* Does nothing for API < 11.
|
||||
*/
|
||||
public void View_setSystemUiVisibility(View view, int visibility) {
|
||||
// nop
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* API 11: support View_setSystemUiVisibility
|
||||
*/
|
||||
@TargetApi(11)
|
||||
class ApiHelper_11 extends ApiHelper {
|
||||
|
||||
/**
|
||||
* Applies {@link View#setSystemUiVisibility(int)}, available only starting with API 11.
|
||||
* Does nothing for API < 11.
|
||||
*/
|
||||
@Override
|
||||
public void View_setSystemUiVisibility(View view, int visibility) {
|
||||
view.setSystemUiVisibility(visibility);
|
||||
}
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.tools.sdkcontroller.views;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Implements a main view for the application providing multi-touch emulation.
|
||||
*/
|
||||
public class MultiTouchView extends View {
|
||||
/** Tag for logging messages. */
|
||||
private static final String TAG = MultiTouchView.class.getSimpleName();
|
||||
/**
|
||||
* Back-end bitmap. Initialized in onSizeChanged(), updated in
|
||||
* onTouchEvent() and drawn in onDraw().
|
||||
*/
|
||||
private Bitmap mBitmap;
|
||||
/** Default Paint instance for drawing the bitmap. */
|
||||
private final Paint mPaint = new Paint();
|
||||
/** Canvas instance for this view. */
|
||||
private Canvas mCanvas;
|
||||
/** Emulator screen width to this view width ratio. */
|
||||
private float mDx = 1;
|
||||
/** Emulator screen height to this view height ratio. */
|
||||
private float mDy = 1;
|
||||
/**
|
||||
* Flags whether or not image received from the emulator should be rotated.
|
||||
* Rotation is required when display orientation state of the emulator and
|
||||
* the device doesn't match.
|
||||
*/
|
||||
private boolean mRotateDisplay;
|
||||
/** Base matrix that keep emulator->device display scaling */
|
||||
private Matrix mBaseMatrix = new Matrix();
|
||||
/** Matrix that is used to draw emulator's screen on the device. */
|
||||
private Matrix mDrawMatrix = new Matrix();
|
||||
|
||||
/**
|
||||
* Simple constructor to use when creating a view from code.
|
||||
*
|
||||
* @see View#View(Context)
|
||||
*/
|
||||
public MultiTouchView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that is called when inflating a view from XML.
|
||||
*
|
||||
* @see View#View(Context, AttributeSet)
|
||||
*/
|
||||
public MultiTouchView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform inflation from XML and apply a class-specific base style.
|
||||
*
|
||||
* @see View#View(Context, AttributeSet, int)
|
||||
*/
|
||||
public MultiTouchView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
// TODO Add constructor-time code here.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
|
||||
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
mCanvas = new Canvas(mBitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
// Just draw the back-end bitmap without zooming or scaling.
|
||||
if (mBitmap != null) {
|
||||
canvas.drawBitmap(mBitmap, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets emulator screen width and height to this view width and height
|
||||
* ratio.
|
||||
*
|
||||
* @param dx Emulator screen width to this view width ratio.
|
||||
* @param dy Emulator screen height to this view height ratio.
|
||||
* @param rotateDisplay Flags whether image received from the emulator
|
||||
* should be rotated when drawn on the device.
|
||||
*/
|
||||
public void setDxDy(float dx, float dy, boolean rotateDisplay) {
|
||||
mDx = dx;
|
||||
mDy = dy;
|
||||
mRotateDisplay = rotateDisplay;
|
||||
|
||||
mBaseMatrix.setScale(dx, dy);
|
||||
if (mRotateDisplay) {
|
||||
mBaseMatrix.postRotate(90);
|
||||
mBaseMatrix.postTranslate(getWidth(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes draw matrix for the emulator screen update.
|
||||
*
|
||||
* @param x Left screen coordinate of the bitmap on emulator screen.
|
||||
* @param y Top screen coordinate of the bitmap on emulator screen.
|
||||
*/
|
||||
private void computeDrawMatrix(int x, int y) {
|
||||
mDrawMatrix.set(mBaseMatrix);
|
||||
if (mRotateDisplay) {
|
||||
mDrawMatrix.postTranslate(-y * mDy, x * mDx);
|
||||
} else {
|
||||
mDrawMatrix.postTranslate(x * mDx, y * mDy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a bitmap on the screen.
|
||||
*
|
||||
* @param x Left screen coordinate of the bitmap on emulator screen.
|
||||
* @param y Top screen coordinate of the bitmap on emulator screen.
|
||||
* @param w Width of the bitmap on the emulator screen.
|
||||
* @param h Height of the bitmap on the emulator screen.
|
||||
* @param colors Bitmap to draw.
|
||||
*/
|
||||
public void drawBitmap(int x, int y, int w, int h, int[] colors) {
|
||||
if (mCanvas != null) {
|
||||
final Bitmap bmp = Bitmap.createBitmap(colors, 0, w, w, h, Bitmap.Config.ARGB_8888);
|
||||
|
||||
computeDrawMatrix(x, y);
|
||||
|
||||
/* Draw the bitmap and invalidate the updated region. */
|
||||
mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a JPEG bitmap on the screen.
|
||||
*
|
||||
* @param x Left screen coordinate of the bitmap on emulator screen.
|
||||
* @param y Top screen coordinate of the bitmap on emulator screen.
|
||||
* @param w Width of the bitmap on the emulator screen.
|
||||
* @param h Height of the bitmap on the emulator screen.
|
||||
* @param jpeg JPEG bitmap to draw.
|
||||
*/
|
||||
public void drawJpeg(int x, int y, int w, int h, InputStream jpeg) {
|
||||
if (mCanvas != null) {
|
||||
final Bitmap bmp = BitmapFactory.decodeStream(jpeg);
|
||||
|
||||
computeDrawMatrix(x, y);
|
||||
|
||||
/* Draw the bitmap and invalidate the updated region. */
|
||||
mCanvas.drawBitmap(bmp, mDrawMatrix, mPaint);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs touch event message to be send to emulator.
|
||||
*
|
||||
* @param bb ByteBuffer where to construct the message.
|
||||
* @param event Event for which to construct the message.
|
||||
* @param ptr_index Index of the motion pointer for which to construct the
|
||||
* message.
|
||||
*/
|
||||
public void constructEventMessage(ByteBuffer bb, MotionEvent event, int ptr_index) {
|
||||
bb.putInt(event.getPointerId(ptr_index));
|
||||
if (mRotateDisplay == false) {
|
||||
bb.putInt((int) (event.getX(ptr_index) / mDx));
|
||||
bb.putInt((int) (event.getY(ptr_index) / mDy));
|
||||
} else {
|
||||
bb.putInt((int) (event.getY(ptr_index) / mDy));
|
||||
bb.putInt((int) (getWidth() - event.getX(ptr_index) / mDx));
|
||||
}
|
||||
// At the system level the input reader takes integers in the range
|
||||
// 0 - 100 for the pressure.
|
||||
int pressure = (int) (event.getPressure(ptr_index) * 100);
|
||||
// Make sure it doesn't exceed 100...
|
||||
if (pressure > 100) {
|
||||
pressure = 100;
|
||||
}
|
||||
bb.putInt(pressure);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Logging wrappers
|
||||
**************************************************************************/
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void Loge(String log) {
|
||||
Log.e(TAG, log);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void Logw(String log) {
|
||||
Log.w(TAG, log);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void Logv(String log) {
|
||||
Log.v(TAG, log);
|
||||
}
|
||||
}
|
111
android/tools/android-osx/tools/ddms
Executable file
111
android/tools/android-osx/tools/ddms
Executable file
@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
# Copyright 2005-2007, 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.
|
||||
|
||||
# Set up prog to be the path of this script, including following symlinks,
|
||||
# and set up progdir to be the fully-qualified pathname of its directory.
|
||||
prog="$0"
|
||||
while [ -h "${prog}" ]; do
|
||||
newProg=`/bin/ls -ld "${prog}"`
|
||||
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
|
||||
if expr "x${newProg}" : 'x/' >/dev/null; then
|
||||
prog="${newProg}"
|
||||
else
|
||||
progdir=`dirname "${prog}"`
|
||||
prog="${progdir}/${newProg}"
|
||||
fi
|
||||
done
|
||||
oldwd=`pwd`
|
||||
progdir=`dirname "${prog}"`
|
||||
cd "${progdir}"
|
||||
progdir=`pwd`
|
||||
prog="${progdir}"/`basename "${prog}"`
|
||||
cd "${oldwd}"
|
||||
|
||||
jarfile=ddms.jar
|
||||
frameworkdir="$progdir"
|
||||
libdir="$progdir"
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/tools/lib
|
||||
libdir=`dirname "$progdir"`/tools/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/framework
|
||||
libdir=`dirname "$progdir"`/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
echo `basename "$prog"`": can't find $jarfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Check args.
|
||||
if [ debug = "$1" ]; then
|
||||
# add this in for debugging
|
||||
java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
|
||||
shift 1
|
||||
else
|
||||
java_debug=
|
||||
fi
|
||||
|
||||
javaCmd="java"
|
||||
|
||||
# Mac OS X needs an additional arg, or you get an "illegal thread" complaint.
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
os_opts="-XstartOnFirstThread"
|
||||
else
|
||||
os_opts=
|
||||
fi
|
||||
|
||||
if [ `uname` = "Linux" ]; then
|
||||
export GDK_NATIVE_WINDOWS=true
|
||||
fi
|
||||
|
||||
jarpath="$frameworkdir/$jarfile:$frameworkdir/swtmenubar.jar"
|
||||
|
||||
# Figure out the path to the swt.jar for the current architecture.
|
||||
# if ANDROID_SWT is defined, then just use this.
|
||||
# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
|
||||
# else, look for the correct swt folder in the SDK under tools/lib/
|
||||
swtpath=""
|
||||
if [ -n "$ANDROID_SWT" ]; then
|
||||
swtpath="$ANDROID_SWT"
|
||||
else
|
||||
vmarch=`${javaCmd} -jar "${frameworkdir}"/archquery.jar`
|
||||
if [ -n "$ANDROID_BUILD_TOP" ]; then
|
||||
osname=`uname -s | tr A-Z a-z`
|
||||
swtpath="${ANDROID_BUILD_TOP}/prebuilts/tools/${osname}-${vmarch}/swt"
|
||||
else
|
||||
swtpath="${frameworkdir}/${vmarch}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$swtpath" ]; then
|
||||
echo "SWT folder '${swtpath}' does not exist."
|
||||
echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -x $progdir/monitor ]; then
|
||||
echo "The standalone version of DDMS is deprecated."
|
||||
echo "Please use Android Device Monitor (tools/monitor) instead."
|
||||
fi
|
||||
exec "$javaCmd" \
|
||||
-Xmx256M $os_opts $java_debug \
|
||||
-Dcom.android.ddms.bindir="$progdir" \
|
||||
-classpath "$jarpath:$swtpath/swt.jar" \
|
||||
com.android.ddms.Main "$@"
|
63
android/tools/android-osx/tools/draw9patch
Executable file
63
android/tools/android-osx/tools/draw9patch
Executable file
@ -0,0 +1,63 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2008, 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.
|
||||
|
||||
# Set up prog to be the path of this script, including following symlinks,
|
||||
# and set up progdir to be the fully-qualified pathname of its directory.
|
||||
prog="$0"
|
||||
while [ -h "${prog}" ]; do
|
||||
newProg=`/bin/ls -ld "${prog}"`
|
||||
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
|
||||
if expr "x${newProg}" : 'x/' >/dev/null; then
|
||||
prog="${newProg}"
|
||||
else
|
||||
progdir=`dirname "${prog}"`
|
||||
prog="${progdir}/${newProg}"
|
||||
fi
|
||||
done
|
||||
oldwd=`pwd`
|
||||
progdir=`dirname "${prog}"`
|
||||
cd "${progdir}"
|
||||
progdir=`pwd`
|
||||
prog="${progdir}"/`basename "${prog}"`
|
||||
cd "${oldwd}"
|
||||
|
||||
jarfile=draw9patch.jar
|
||||
frameworkdir="$progdir"
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/tools/lib
|
||||
libdir=`dirname "$progdir"`/tools/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/framework
|
||||
libdir=`dirname "$progdir"`/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
echo `basename "$prog"`": can't find $jarfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$OSTYPE" = "cygwin" ] ; then
|
||||
jarpath=`cygpath -w "$frameworkdir/$jarfile"`
|
||||
progdir=`cygpath -w "$progdir"`
|
||||
else
|
||||
jarpath="$frameworkdir/$jarfile"
|
||||
fi
|
||||
|
||||
# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
|
||||
# might need more memory, e.g. -Xmx128M
|
||||
exec java -Djava.ext.dirs="$frameworkdir" -jar "$jarpath" "$@"
|
114
android/tools/android-osx/tools/hierarchyviewer
Executable file
114
android/tools/android-osx/tools/hierarchyviewer
Executable file
@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2008, 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.
|
||||
|
||||
# Set up prog to be the path of this script, including following symlinks,
|
||||
# and set up progdir to be the fully-qualified pathname of its directory.
|
||||
|
||||
prog="$0"
|
||||
while [ -h "${prog}" ]; do
|
||||
newProg=`/bin/ls -ld "${prog}"`
|
||||
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
|
||||
if expr "x${newProg}" : 'x/' >/dev/null; then
|
||||
prog="${newProg}"
|
||||
else
|
||||
progdir=`dirname "${prog}"`
|
||||
prog="${progdir}/${newProg}"
|
||||
fi
|
||||
done
|
||||
oldwd=`pwd`
|
||||
progdir=`dirname "${prog}"`
|
||||
cd "${progdir}"
|
||||
progdir=`pwd`
|
||||
prog="${progdir}"/`basename "${prog}"`
|
||||
cd "${oldwd}"
|
||||
|
||||
jarfile=hierarchyviewer2.jar
|
||||
frameworkdir="$progdir"
|
||||
libdir="$progdir"
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/tools/lib
|
||||
libdir=`dirname "$progdir"`/tools/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/framework
|
||||
libdir=`dirname "$progdir"`/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
echo `basename "$prog"`": can't find $jarfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# Check args.
|
||||
if [ debug = "$1" ]; then
|
||||
# add this in for debugging
|
||||
java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
|
||||
shift 1
|
||||
else
|
||||
java_debug=
|
||||
fi
|
||||
|
||||
javaCmd="java"
|
||||
|
||||
# Mac OS X needs an additional arg, or you get an "illegal thread" complaint.
|
||||
if [ `uname` = "Darwin" ]; then
|
||||
os_opts="-XstartOnFirstThread"
|
||||
else
|
||||
os_opts=
|
||||
fi
|
||||
|
||||
if [ `uname` = "Linux" ]; then
|
||||
export GDK_NATIVE_WINDOWS=true
|
||||
fi
|
||||
|
||||
jarpath="$frameworkdir/$jarfile:$frameworkdir/swtmenubar.jar"
|
||||
|
||||
# Figure out the path to the swt.jar for the current architecture.
|
||||
# if ANDROID_SWT is defined, then just use this.
|
||||
# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
|
||||
# else, look for the correct swt folder in the SDK under tools/lib/
|
||||
swtpath=""
|
||||
if [ -n "$ANDROID_SWT" ]; then
|
||||
swtpath="$ANDROID_SWT"
|
||||
else
|
||||
vmarch=`${javaCmd} -jar "${frameworkdir}"/archquery.jar`
|
||||
if [ -n "$ANDROID_BUILD_TOP" ]; then
|
||||
osname=`uname -s | tr A-Z a-z`
|
||||
swtpath="${ANDROID_BUILD_TOP}/prebuilts/tools/${osname}-${vmarch}/swt"
|
||||
else
|
||||
swtpath="${frameworkdir}/${vmarch}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d "$swtpath" ]; then
|
||||
echo "SWT folder '${swtpath}' does not exist."
|
||||
echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -x $progdir/monitor ]; then
|
||||
echo "The standalone version of hieararchyviewer is deprecated."
|
||||
echo "Please use Android Device Monitor (tools/monitor) instead."
|
||||
fi
|
||||
# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
|
||||
# might need more memory, e.g. -Xmx128M
|
||||
exec "$javaCmd" \
|
||||
-Xmx512M $os_opts $java_debug \
|
||||
-Dcom.android.hierarchyviewer.bindir="$progdir" \
|
||||
-classpath "$jarpath:$swtpath/swt.jar" \
|
||||
com.android.hierarchyviewer.HierarchyViewerApplication "$@"
|
68
android/tools/android-osx/tools/jobb
Executable file
68
android/tools/android-osx/tools/jobb
Executable file
@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2008, 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.
|
||||
|
||||
# Set up prog to be the path of this script, including following symlinks,
|
||||
# and set up progdir to be the fully-qualified pathname of its directory.
|
||||
|
||||
prog="$0"
|
||||
while [ -h "${prog}" ]; do
|
||||
newProg=`/bin/ls -ld "${prog}"`
|
||||
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
|
||||
if expr "x${newProg}" : 'x/' >/dev/null; then
|
||||
prog="${newProg}"
|
||||
else
|
||||
progdir=`dirname "${prog}"`
|
||||
prog="${progdir}/${newProg}"
|
||||
fi
|
||||
done
|
||||
oldwd=`pwd`
|
||||
progdir=`dirname "${prog}"`
|
||||
cd "${progdir}"
|
||||
progdir=`pwd`
|
||||
prog="${progdir}"/`basename "${prog}"`
|
||||
cd "${oldwd}"
|
||||
|
||||
jarfile=jobb.jar
|
||||
frameworkdir="$progdir"
|
||||
libdir="$progdir"
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/tools/lib
|
||||
libdir=`dirname "$progdir"`/tools/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
frameworkdir=`dirname "$progdir"`/framework
|
||||
libdir=`dirname "$progdir"`/lib
|
||||
fi
|
||||
if [ ! -r "$frameworkdir/$jarfile" ]
|
||||
then
|
||||
echo `basename "$prog"`": can't find $jarfile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
javaCmd="java"
|
||||
|
||||
if [ `uname` = "Linux" ]; then
|
||||
export GDK_NATIVE_WINDOWS=true
|
||||
fi
|
||||
|
||||
jarpath="$frameworkdir/$jarfile:$frameworkdir/fat32lib.jar"
|
||||
|
||||
exec "$javaCmd" \
|
||||
$os_opts \
|
||||
-classpath "$jarpath" \
|
||||
com.android.jobb.Main "$@"
|
||||
|
131
android/tools/android-osx/tools/lib/android.el
Executable file
131
android/tools/android-osx/tools/lib/android.el
Executable file
@ -0,0 +1,131 @@
|
||||
;;;; Copyright 2007 The Android Open Source Project
|
||||
|
||||
;;; Set up GUD+JDB to attach to a Java process running on the phone or
|
||||
;;; under the emulator.
|
||||
|
||||
(defvar android-jdb-port-history '("8700")
|
||||
"history of ports supplied to `android-jdb'")
|
||||
|
||||
(defvar android-jdb-project-root-history '()
|
||||
"history of project roots supplied to `android-jdb'")
|
||||
(defvar android-jdb-history nil
|
||||
"history of commands supplied to `android-jdb'")
|
||||
|
||||
(defvar android-jdb-activity-class-history ()
|
||||
"history of activity classes supplied to `start-android-activity'")
|
||||
|
||||
(defcustom android-jdb-command-name "jdb"
|
||||
"Name of Java debugger."
|
||||
:type 'string
|
||||
:group 'android)
|
||||
|
||||
(defgroup android nil
|
||||
"Android Applications."
|
||||
:group 'applications)
|
||||
|
||||
(defcustom android-project-root nil
|
||||
"This is where your Android project root is stored."
|
||||
:type 'directory
|
||||
:group 'android )
|
||||
|
||||
(defcustom android-apk nil
|
||||
"This is where your Android Application Package is stored."
|
||||
:type 'string
|
||||
:group 'android)
|
||||
|
||||
(defcustom android-activity-class nil
|
||||
"This is where your Android Activity class is stored."
|
||||
:type 'string
|
||||
:group 'android)
|
||||
|
||||
(defun android-read-project-root ()
|
||||
(if (or (string-match "XEmacs" emacs-version)
|
||||
(>= emacs-major-version 22))
|
||||
(read-file-name "Android project root: "
|
||||
android-project-root
|
||||
nil
|
||||
t
|
||||
nil
|
||||
'file-directory-p)
|
||||
(labels ((read-directory ()
|
||||
(read-file-name "Android project root: "
|
||||
android-project-root
|
||||
nil
|
||||
t
|
||||
nil)))
|
||||
(do ((entered-root (read-directory) (read-directory)))
|
||||
((and entered-root
|
||||
(file-directory-p entered-root))
|
||||
(expand-file-name entered-root))))))
|
||||
|
||||
(defun android-jdb (port root)
|
||||
"Set GUD+JDB up to run against Android on PORT in directory ROOT."
|
||||
(interactive
|
||||
(list
|
||||
(read-from-minibuffer "Activity's JDWP DDMS port: "
|
||||
(car android-jdb-port-history)
|
||||
nil
|
||||
t
|
||||
'android-jdb-port-history)
|
||||
(android-read-project-root)))
|
||||
(setq android-project-root root)
|
||||
(let ((jdb-command
|
||||
(format "%s -attach localhost:%s -sourcepath%s"
|
||||
android-jdb-command-name
|
||||
port
|
||||
(format "%s/src" root))))
|
||||
(if (not (string= jdb-command (car android-jdb-history)))
|
||||
(push jdb-command android-jdb-history))
|
||||
(jdb jdb-command)))
|
||||
|
||||
(defun android-emulate ()
|
||||
"Run the Android emulator. This expects the SDK tools directory to be in the current path."
|
||||
(interactive)
|
||||
(compile "emulator"))
|
||||
|
||||
(defun android-install-app (apk)
|
||||
"Install an Android application package APK in the Android emulator. This expects the SDK tools directory to be in the current path."
|
||||
(interactive (list (expand-file-name
|
||||
(read-file-name "Android Application Package (.apk): "
|
||||
nil
|
||||
android-apk
|
||||
t
|
||||
nil
|
||||
nil))))
|
||||
(setq android-apk apk)
|
||||
(compile (format "adb install -r %s" apk)))
|
||||
|
||||
(defun android-uninstall-app (package-name)
|
||||
"Uninstall an Android application package APK in the Android emulator. This expects the SDK tools directory to be in the current path.
|
||||
Specify the package name --- and not the name of the application e.g., com.android.foo."
|
||||
(interactive
|
||||
(list
|
||||
(read-from-minibuffer "Package: ")))
|
||||
(compile (format "adb uninstall %s" package-name)))
|
||||
|
||||
(defun android-start-activity (package class)
|
||||
"Start the activity PACKAGE/CLASS in the Android emulator. This expects the SDK tools directory to be in the current path."
|
||||
(interactive
|
||||
(list
|
||||
(read-from-minibuffer "Package: ")
|
||||
(read-from-minibuffer "Activity Java class: "
|
||||
(car android-jdb-activity-class-history)
|
||||
nil
|
||||
t
|
||||
'android-jdb-activity-class-history)))
|
||||
(compile (format "adb shell am start -n %s/%s" package class)))
|
||||
|
||||
(defun android-debug-activity (package class)
|
||||
"Start the activity PACKAGE/CLASS within the debugger in the Android emulator. This expects the SDK tools directory to be in the current path."
|
||||
(interactive
|
||||
(list
|
||||
(read-from-minibuffer "Package: ")
|
||||
(read-from-minibuffer "Activity Java class: "
|
||||
(car android-jdb-activity-class-history)
|
||||
nil
|
||||
t
|
||||
'android-jdb-activity-class-history)))
|
||||
(compile (format "adb shell am start -D -n %s/%s" package class)))
|
||||
|
||||
(provide 'android)
|
||||
|
BIN
android/tools/android-osx/tools/lib/annotations-12.0.jar
Executable file
BIN
android/tools/android-osx/tools/lib/annotations-12.0.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/annotations.jar
Executable file
BIN
android/tools/android-osx/tools/lib/annotations.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/ant-tasks.jar
Executable file
BIN
android/tools/android-osx/tools/lib/ant-tasks.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/archquery.jar
Executable file
BIN
android/tools/android-osx/tools/lib/archquery.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/asm-5.0.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/asm-5.0.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/asm-analysis-5.0.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/asm-analysis-5.0.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/asm-tree-5.0.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/asm-tree-5.0.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/asset-studio.jar
Executable file
BIN
android/tools/android-osx/tools/lib/asset-studio.jar
Executable file
Binary file not shown.
92
android/tools/android-osx/tools/lib/build.template
Executable file
92
android/tools/android-osx/tools/lib/build.template
Executable file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="PROJECT_NAME" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: VERSION_TAG -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
21
android/tools/android-osx/tools/lib/build_gradle.template
Executable file
21
android/tools/android-osx/tools/lib/build_gradle.template
Executable file
@ -0,0 +1,21 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:ARTIFACT_VERSION'
|
||||
}
|
||||
}
|
||||
apply plugin: 'PLUGIN'
|
||||
|
||||
android {
|
||||
compileSdkVersion 'TARGET'
|
||||
buildToolsVersion 'BUILD_TOOL_REV'
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
runProguard false
|
||||
proguardFile getDefaultProguardFile('proguard-android.txt')
|
||||
}
|
||||
}
|
||||
}
|
BIN
android/tools/android-osx/tools/lib/builder-model.jar
Executable file
BIN
android/tools/android-osx/tools/lib/builder-model.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/cglib-nodep-3.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/cglib-nodep-3.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/chimpchat.jar
Executable file
BIN
android/tools/android-osx/tools/lib/chimpchat.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/common.jar
Executable file
BIN
android/tools/android-osx/tools/lib/common.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/commons-codec-1.4.jar
Executable file
BIN
android/tools/android-osx/tools/lib/commons-codec-1.4.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/commons-compress-1.8.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/commons-compress-1.8.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/commons-logging-1.1.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/commons-logging-1.1.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/ddmlib.jar
Executable file
BIN
android/tools/android-osx/tools/lib/ddmlib.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/ddms.jar
Executable file
BIN
android/tools/android-osx/tools/lib/ddms.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/ddmuilib.jar
Executable file
BIN
android/tools/android-osx/tools/lib/ddmuilib.jar
Executable file
Binary file not shown.
595
android/tools/android-osx/tools/lib/devices.xml
Executable file
595
android/tools/android-osx/tools/lib/devices.xml
Executable file
@ -0,0 +1,595 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<d:devices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:d="http://schemas.android.com/sdk/devices/1">
|
||||
|
||||
<d:device>
|
||||
<d:name>Nexus One</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>normal</d:screen-size>
|
||||
<d:diagonal-length>3.7</d:diagonal-length>
|
||||
<d:pixel-density>hdpi</d:pixel-density>
|
||||
<d:screen-ratio>long</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>480</d:x-dimension>
|
||||
<d:y-dimension>800</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>254</d:xdpi>
|
||||
<d:ydpi>254</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>basic</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Wifi
|
||||
Bluetooth
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Compass
|
||||
GPS
|
||||
LightSensor
|
||||
ProximitySensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>back</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>true</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>trackball</d:nav>
|
||||
<d:ram unit="MiB">512</d:ram>
|
||||
<d:buttons>hard</d:buttons>
|
||||
<d:internal-storage unit="MiB">503</d:internal-storage>
|
||||
<d:removable-storage unit="MiB">0</d:removable-storage>
|
||||
<d:cpu>Qualcomm Scorpion</d:cpu>
|
||||
<d:gpu>Qualcomm Adreno 200</d:gpu>
|
||||
<d:abi>
|
||||
armeabi-v7a
|
||||
armeabi
|
||||
</d:abi>
|
||||
<d:dock> </d:dock>
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
<d:software>
|
||||
<d:api-level>7-10</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles> </d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<d:gl-extensions>
|
||||
</d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
<d:state name="Portrait" default="true">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
</d:device>
|
||||
<d:device>
|
||||
<d:name>Nexus S</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>normal</d:screen-size>
|
||||
<d:diagonal-length>4</d:diagonal-length>
|
||||
<d:pixel-density>hdpi</d:pixel-density>
|
||||
<d:screen-ratio>long</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>480</d:x-dimension>
|
||||
<d:y-dimension>800</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>235</d:xdpi>
|
||||
<d:ydpi>235</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>jazz-hands</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Wifi
|
||||
Bluetooth
|
||||
NFC
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Compass
|
||||
GPS
|
||||
Gyroscope
|
||||
LightSensor
|
||||
ProximitySensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>back</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>true</d:flash>
|
||||
</d:camera>
|
||||
<d:camera>
|
||||
<d:location>front</d:location>
|
||||
<d:autofocus>false</d:autofocus>
|
||||
<d:flash>false</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>nonav</d:nav>
|
||||
<d:ram unit="KiB">351428</d:ram>
|
||||
<d:buttons>hard</d:buttons>
|
||||
<d:internal-storage unit="MiB">503</d:internal-storage>
|
||||
<d:removable-storage unit="MiB">0</d:removable-storage>
|
||||
<d:cpu>Samsung Exynos 3110</d:cpu>
|
||||
<d:gpu>PowerVR SGX 540</d:gpu>
|
||||
<d:abi>
|
||||
armeabi-v7a
|
||||
armeabi
|
||||
</d:abi>
|
||||
<d:dock> </d:dock>
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
<d:software>
|
||||
<d:api-level>9-16</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles> </d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<d:gl-extensions>
|
||||
GL_EXT_debug_marker
|
||||
GL_OES_rgb8_rgba8
|
||||
GL_OES_depth24
|
||||
GL_OES_vertex_half_float
|
||||
GL_OES_texture_float
|
||||
GL_OES_texture_half_float
|
||||
GL_OES_element_index_uint
|
||||
GL_OES_mapbuffer
|
||||
GL_OES_fragment_precision_high
|
||||
GL_OES_compressed_ETC1_RGB8_texture
|
||||
GL_OES_EGL_image
|
||||
GL_OES_EGL_image_external
|
||||
GL_OES_required_internalformat
|
||||
GL_OES_depth_texture
|
||||
GL_OES_get_program_binary
|
||||
GL_OES_packed_depth_stencil
|
||||
GL_OES_standard_derivatives
|
||||
GL_OES_vertex_array_object
|
||||
GL_OES_egl_sync
|
||||
GL_EXT_multi_draw_arrays
|
||||
GL_EXT_texture_format_BGRA8888
|
||||
GL_EXT_discard_framebuffer
|
||||
GL_EXT_shader_texture_lod
|
||||
GL_IMG_shader_binary
|
||||
GL_IMG_texture_compression_pvrtc
|
||||
GL_IMG_texture_npot
|
||||
GL_IMG_texture_format_BGRA8888
|
||||
GL_IMG_read_format
|
||||
GL_IMG_program_binary
|
||||
GL_IMG_multisampled_render_to_texture
|
||||
</d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
<d:state name="Portrait" default="true">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
</d:device>
|
||||
|
||||
<d:device>
|
||||
<d:name>Galaxy Nexus</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>normal</d:screen-size>
|
||||
<d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
|
||||
<d:pixel-density>xhdpi</d:pixel-density>
|
||||
<d:screen-ratio>long</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>720</d:x-dimension>
|
||||
<d:y-dimension>1280</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>316</d:xdpi>
|
||||
<d:ydpi>316</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>jazz-hands</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Bluetooth
|
||||
Wifi
|
||||
NFC
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Barometer
|
||||
Gyroscope
|
||||
Compass
|
||||
GPS
|
||||
ProximitySensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>front</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>false</d:flash>
|
||||
</d:camera>
|
||||
<d:camera>
|
||||
<d:location>back</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>true</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>nonav</d:nav>
|
||||
<d:ram unit="GiB">1</d:ram>
|
||||
<d:buttons>soft</d:buttons>
|
||||
<d:internal-storage unit="GiB">16</d:internal-storage>
|
||||
<d:removable-storage unit="KiB"></d:removable-storage>
|
||||
<d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
|
||||
<d:gpu>PowerVR SGX540</d:gpu>
|
||||
<d:abi>
|
||||
armeabi
|
||||
armeabi-v7a
|
||||
</d:abi>
|
||||
<!--dock (car, desk, tv, none)-->
|
||||
<d:dock>
|
||||
</d:dock>
|
||||
<!-- power-type (battery, plugged-in) -->
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
<d:software>
|
||||
<d:api-level>14-</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles>
|
||||
HSP
|
||||
HFP
|
||||
SPP
|
||||
A2DP
|
||||
AVRCP
|
||||
OPP
|
||||
PBAP
|
||||
GAVDP
|
||||
AVDTP
|
||||
HID
|
||||
HDP
|
||||
PAN
|
||||
</d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<!--
|
||||
These can be gotten via
|
||||
javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
|
||||
-->
|
||||
<d:gl-extensions>
|
||||
GL_EXT_discard_framebuffer
|
||||
GL_EXT_multi_draw_arrays
|
||||
GL_EXT_shader_texture_lod
|
||||
GL_EXT_texture_format_BGRA8888
|
||||
GL_IMG_multisampled_render_to_texture
|
||||
GL_IMG_program_binary
|
||||
GL_IMG_read_format
|
||||
GL_IMG_shader_binary
|
||||
GL_IMG_texture_compression_pvrtc
|
||||
GL_IMG_texture_format_BGRA8888
|
||||
GL_IMG_texture_npot
|
||||
GL_OES_compressed_ETC1_RGB8_texture
|
||||
GL_OES_depth_texture
|
||||
GL_OES_depth24
|
||||
GL_OES_EGL_image
|
||||
GL_OES_EGL_image_external
|
||||
GL_OES_egl_sync
|
||||
GL_OES_element_index_uint
|
||||
GL_OES_fragment_precision_high
|
||||
GL_OES_get_program_binary
|
||||
GL_OES_mapbuffer
|
||||
GL_OES_packed_depth_stencil
|
||||
GL_OES_required_internalformat
|
||||
GL_OES_rgb8_rgba8
|
||||
GL_OES_standard_derivatives
|
||||
GL_OES_texture_float
|
||||
GL_OES_texture_half_float
|
||||
GL_OES_vertex_array_object
|
||||
GL_OES_vertex_half_float
|
||||
</d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
<d:state name="Portrait" default="true">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
</d:device>
|
||||
<d:device>
|
||||
<d:name>Nexus 7</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>large</d:screen-size>
|
||||
<d:diagonal-length>7.27</d:diagonal-length>
|
||||
<d:pixel-density>tvdpi</d:pixel-density>
|
||||
<d:screen-ratio>notlong</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>800</d:x-dimension>
|
||||
<d:y-dimension>1280</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>195</d:xdpi>
|
||||
<d:ydpi>200</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>jazz-hands</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Wifi
|
||||
Bluetooth
|
||||
NFC
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Compass
|
||||
GPS
|
||||
Gyroscope
|
||||
LightSensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>front</d:location>
|
||||
<d:autofocus>false</d:autofocus>
|
||||
<d:flash>false</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>nonav</d:nav>
|
||||
<d:ram unit="GiB">1</d:ram>
|
||||
<d:buttons>soft</d:buttons>
|
||||
<d:internal-storage unit="GiB">8</d:internal-storage>
|
||||
<d:removable-storage unit="MiB"> </d:removable-storage>
|
||||
<d:cpu> Tegra3 </d:cpu>
|
||||
<d:gpu> Tegra3 </d:gpu>
|
||||
<d:abi>
|
||||
armeabi-v7a
|
||||
armeabi
|
||||
</d:abi>
|
||||
<d:dock> </d:dock>
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
|
||||
<d:software>
|
||||
<d:api-level>16</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles> </d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<d:gl-extensions> </d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
|
||||
<d:state name="Portrait" default="true">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
|
||||
</d:device>
|
||||
|
||||
<d:device>
|
||||
<d:name>Nexus 4</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>normal</d:screen-size>
|
||||
<d:diagonal-length>4.7</d:diagonal-length>
|
||||
<d:pixel-density>xhdpi</d:pixel-density>
|
||||
<d:screen-ratio>notlong</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>768</d:x-dimension>
|
||||
<d:y-dimension>1280</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>320</d:xdpi>
|
||||
<d:ydpi>320</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>jazz-hands</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Wifi
|
||||
Bluetooth
|
||||
NFC
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Barometer
|
||||
Compass
|
||||
GPS
|
||||
Gyroscope
|
||||
LightSensor
|
||||
ProximitySensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>back</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>true</d:flash>
|
||||
</d:camera>
|
||||
<d:camera>
|
||||
<d:location>front</d:location>
|
||||
<d:autofocus>false</d:autofocus>
|
||||
<d:flash>false</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>nonav</d:nav>
|
||||
<d:ram unit="KiB">1953125</d:ram>
|
||||
<d:buttons>soft</d:buttons>
|
||||
<d:internal-storage unit="KiB">7811891</d:internal-storage>
|
||||
<d:removable-storage unit="MiB"></d:removable-storage>
|
||||
<d:cpu>Qualcomm Snapdragon S4 Pro</d:cpu>
|
||||
<d:gpu>Adreno 320</d:gpu>
|
||||
<d:abi>
|
||||
armeabi-v7a
|
||||
armeabi
|
||||
</d:abi>
|
||||
<d:dock></d:dock>
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
<d:software>
|
||||
<d:api-level>16</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles></d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<d:gl-extensions>GL_EXT_debug_marker GL_AMD_compressed_ATC_texture
|
||||
GL_AMD_performance_monitor GL_AMD_program_binary_Z400 GL_EXT_robustness
|
||||
GL_EXT_texture_format_BGRA8888 GL_EXT_texture_type_2_10_10_10_REV GL_NV_fence
|
||||
GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture GL_OES_depth24
|
||||
GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_element_index_uint
|
||||
GL_OES_fbo_render_mipmap GL_OES_fragment_precision_high GL_OES_get_program_binary
|
||||
GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_OES_standard_derivatives
|
||||
GL_OES_texture_3D GL_OES_texture_float GL_OES_texture_half_float
|
||||
GL_OES_texture_half_float_linear GL_OES_texture_npot GL_OES_vertex_half_float
|
||||
GL_OES_vertex_type_10_10_10_2 GL_OES_vertex_array_object GL_QCOM_alpha_test
|
||||
GL_QCOM_binning_control GL_QCOM_driver_control GL_QCOM_perfmon_global_mode
|
||||
GL_QCOM_extended_get GL_QCOM_extended_get2 GL_QCOM_tiled_rendering
|
||||
GL_QCOM_writeonly_rendering GL_EXT_sRGB
|
||||
</d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
<d:state name="Portrait" default="true">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
</d:device>
|
||||
|
||||
<d:device>
|
||||
<d:name>Nexus 10</d:name>
|
||||
<d:manufacturer>Google</d:manufacturer>
|
||||
<d:hardware>
|
||||
<d:screen>
|
||||
<d:screen-size>xlarge</d:screen-size>
|
||||
<d:diagonal-length>10.055</d:diagonal-length>
|
||||
<d:pixel-density>xhdpi</d:pixel-density>
|
||||
<d:screen-ratio>notlong</d:screen-ratio>
|
||||
<d:dimensions>
|
||||
<d:x-dimension>2560</d:x-dimension>
|
||||
<d:y-dimension>1600</d:y-dimension>
|
||||
</d:dimensions>
|
||||
<d:xdpi>300</d:xdpi>
|
||||
<d:ydpi>300</d:ydpi>
|
||||
<d:touch>
|
||||
<d:multitouch>jazz-hands</d:multitouch>
|
||||
<d:mechanism>finger</d:mechanism>
|
||||
<d:screen-type>capacitive</d:screen-type>
|
||||
</d:touch>
|
||||
</d:screen>
|
||||
<d:networking>
|
||||
Wifi
|
||||
Bluetooth
|
||||
NFC
|
||||
</d:networking>
|
||||
<d:sensors>
|
||||
Accelerometer
|
||||
Barometer
|
||||
Compass
|
||||
GPS
|
||||
Gyroscope
|
||||
LightSensor
|
||||
</d:sensors>
|
||||
<d:mic>true</d:mic>
|
||||
<d:camera>
|
||||
<d:location>back</d:location>
|
||||
<d:autofocus>true</d:autofocus>
|
||||
<d:flash>true</d:flash>
|
||||
</d:camera>
|
||||
<d:camera>
|
||||
<d:location>front</d:location>
|
||||
<d:autofocus>false</d:autofocus>
|
||||
<d:flash>false</d:flash>
|
||||
</d:camera>
|
||||
<d:keyboard>nokeys</d:keyboard>
|
||||
<d:nav>nonav</d:nav>
|
||||
<d:ram unit="KiB">1953125</d:ram>
|
||||
<d:buttons>soft</d:buttons>
|
||||
<d:internal-storage unit="KiB">15623782</d:internal-storage>
|
||||
<d:removable-storage unit="MiB"></d:removable-storage>
|
||||
<d:cpu>Dual-core A15</d:cpu>
|
||||
<d:gpu>Quad-core Mali T604</d:gpu>
|
||||
<d:abi>
|
||||
armeabi-v7a
|
||||
armeabi
|
||||
</d:abi>
|
||||
<d:dock></d:dock>
|
||||
<d:power-type>battery</d:power-type>
|
||||
</d:hardware>
|
||||
<d:software>
|
||||
<d:api-level>16</d:api-level>
|
||||
<d:live-wallpaper-support>true</d:live-wallpaper-support>
|
||||
<d:bluetooth-profiles></d:bluetooth-profiles>
|
||||
<d:gl-version>2.0</d:gl-version>
|
||||
<d:gl-extensions>GL_EXT_debug_marker GL_ARM_rgba8 GL_ARM_mali_shader_binary
|
||||
GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map
|
||||
GL_OES_packed_depth_stencil GL_OES_rgb8_rgba8 GL_EXT_read_format_bgra
|
||||
GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture
|
||||
GL_OES_standard_derivatives GL_OES_EGL_image GL_OES_EGL_image_external
|
||||
GL_OES_EGL_sync GL_OES_texture_npot GL_OES_vertex_half_float
|
||||
GL_OES_required_internalformat GL_OES_vertex_array_object GL_OES_mapbuffer
|
||||
GL_EXT_texture_format_BGRA8888 GL_EXT_texture_rg GL_EXT_texture_type_2_10_10_10_REV
|
||||
GL_OES_fbo_render_mipmap GL_OES_element_index_uint GL_EXT_shadow_samplers
|
||||
GL_EXT_occlusion_query_boolean GL_EXT_blend_minmax GL_EXT_discard_framebuffer
|
||||
GL_OES_get_program_binary GL_OES_texture_3D GL_EXT_texture_storage
|
||||
GL_EXT_multisampled_render_to_texture GL_OES_surfaceless_context
|
||||
GL_ARM_mali_program_binary
|
||||
</d:gl-extensions>
|
||||
<d:status-bar>true</d:status-bar>
|
||||
</d:software>
|
||||
<d:state name="Portrait">
|
||||
<d:description>The phone in portrait view</d:description>
|
||||
<d:screen-orientation>port</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
<d:state name="Landscape" default="true">
|
||||
<d:description>The phone in landscape view</d:description>
|
||||
<d:screen-orientation>land</d:screen-orientation>
|
||||
<d:keyboard-state>keyssoft</d:keyboard-state>
|
||||
<d:nav-state>nonav</d:nav-state>
|
||||
</d:state>
|
||||
</d:device>
|
||||
|
||||
</d:devices>
|
BIN
android/tools/android-osx/tools/lib/draw9patch.jar
Executable file
BIN
android/tools/android-osx/tools/lib/draw9patch.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/dvlib.jar
Executable file
BIN
android/tools/android-osx/tools/lib/dvlib.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/easymock-3.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/easymock-3.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/ecj-4.4.2.jar
Executable file
BIN
android/tools/android-osx/tools/lib/ecj-4.4.2.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/emma.jar
Executable file
BIN
android/tools/android-osx/tools/lib/emma.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/emma_ant.jar
Executable file
BIN
android/tools/android-osx/tools/lib/emma_ant.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/emma_device.jar
Executable file
BIN
android/tools/android-osx/tools/lib/emma_device.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/fat32lib.jar
Executable file
BIN
android/tools/android-osx/tools/lib/fat32lib.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/gson-2.2.4.jar
Executable file
BIN
android/tools/android-osx/tools/lib/gson-2.2.4.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/guava-17.0.jar
Executable file
BIN
android/tools/android-osx/tools/lib/guava-17.0.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/hamcrest-core-1.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/hamcrest-core-1.3.jar
Executable file
Binary file not shown.
402
android/tools/android-osx/tools/lib/hardware-properties.ini
Executable file
402
android/tools/android-osx/tools/lib/hardware-properties.ini
Executable file
@ -0,0 +1,402 @@
|
||||
# This file describes the properties of a given virtual device configuration file.
|
||||
#
|
||||
# Note: Most top-level properties are boolean that control whether a feature is
|
||||
# present or not. Sub-features that depend on it are ignored if their
|
||||
# parent is set to 'false' or 'no'
|
||||
#
|
||||
# This file is parsed by 'android/tools/gen-hw-config.py' to generate
|
||||
# 'android/avd/hw-config-defs.h'. The latter is a special header containing
|
||||
# macro statements that is used several times:
|
||||
#
|
||||
# - once to define the fields of the AndroidHwConfig structure
|
||||
# (see android/avd/hw-config.h)
|
||||
#
|
||||
# - once to implement the hardware configuration loader
|
||||
# (see android/avd/hw-config.h)
|
||||
#
|
||||
# It is also packaged by the SDK and parsed by tools to let the developers
|
||||
# create AVDs.
|
||||
#
|
||||
# NOTE: if you remove items from this file, be sure that you do not break
|
||||
# the emulator build.
|
||||
#
|
||||
|
||||
# CPU Architecture
|
||||
name = hw.cpu.arch
|
||||
type = string
|
||||
default = arm
|
||||
abstract = CPU Architecture
|
||||
description = The CPU Architecture to emulator
|
||||
|
||||
# CPU Model
|
||||
# Leave it empty, and the default value will be computed from
|
||||
# hw.cpu.arch. This is only useful for experimentation for now.
|
||||
name = hw.cpu.model
|
||||
type = string
|
||||
default =
|
||||
abstract = CPU model
|
||||
description = The CPU model (QEMU-specific string)
|
||||
|
||||
# Ram size
|
||||
# Default value will be computed based on screen pixels
|
||||
# or skin version
|
||||
name = hw.ramSize
|
||||
type = integer
|
||||
default = 0
|
||||
abstract = Device ram size
|
||||
description = The amount of physical RAM on the device, in megabytes.
|
||||
|
||||
# Touch screen type
|
||||
name = hw.screen
|
||||
type = string
|
||||
enum = touch, multi-touch, no-touch
|
||||
default = touch
|
||||
abstract = Touch screen type
|
||||
description = Defines type of the screen.
|
||||
|
||||
# Hardware main keys (back/home)
|
||||
name = hw.mainKeys
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Hardware Back/Home keys
|
||||
description = Whether there are hardware back/home keys on the device.
|
||||
|
||||
# Trackball support
|
||||
name = hw.trackBall
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Track-ball support
|
||||
description = Whether there is a trackball on the device.
|
||||
|
||||
# Keyboard support (qwerty/azerty)
|
||||
name = hw.keyboard
|
||||
type = boolean
|
||||
default = no
|
||||
abstract = Keyboard support
|
||||
description = Whether the device has a QWERTY keyboard.
|
||||
|
||||
# Keyboard lid support
|
||||
# (I.e. can the qwerty keyboard be closed/hidden or opened/visible)
|
||||
# this will be ignored if hw.keyboard is false
|
||||
#
|
||||
# NOTE: As a special case, the default value will be 'false' if the
|
||||
# AVD targets API level 12 or higher. See hwConfig_init()
|
||||
# in external/qemu/android/avd/hw-config.c for more details.
|
||||
#
|
||||
name = hw.keyboard.lid
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Keyboard lid support
|
||||
description = Whether the QWERTY keyboard can be opened/closed.
|
||||
|
||||
# The name of the hardware charmap for this device.
|
||||
#
|
||||
# NOTE: This should always be the default 'qwerty2' unless you have
|
||||
# modified the system image accordingly. This name is sent to
|
||||
# the kernel at boot time. Using an incorrect name will result
|
||||
# in an unusable machine.
|
||||
name = hw.keyboard.charmap
|
||||
type = string
|
||||
default = qwerty2
|
||||
abstract = Keyboard charmap name
|
||||
description = Name of the system keyboard charmap file.
|
||||
|
||||
# DPad keys
|
||||
name = hw.dPad
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = DPad support
|
||||
description = Whether the device has DPad keys
|
||||
|
||||
# GSM Modem support
|
||||
name = hw.gsmModem
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = GSM modem support
|
||||
description = Whether there is a GSM modem in the device.
|
||||
|
||||
# GPS support
|
||||
name = hw.gps
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = GPS support
|
||||
description = Whether there is a GPS in the device.
|
||||
|
||||
# Battery
|
||||
name = hw.battery
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Battery support
|
||||
description = Whether the device can run on a battery.
|
||||
|
||||
# Accelerometer (used for auto-rotation)
|
||||
name = hw.accelerometer
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Accelerometer
|
||||
description = Whether there is an accelerometer in the device.
|
||||
|
||||
# Audio input
|
||||
name = hw.audioInput
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Audio recording support
|
||||
description = Whether the device can record audio
|
||||
|
||||
# Audio output
|
||||
name = hw.audioOutput
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Audio playback support
|
||||
description = Whether the device can play audio
|
||||
|
||||
# SDCard support
|
||||
name = hw.sdCard
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = SD Card support
|
||||
description = Whether the device supports insertion/removal of virtual SD Cards.
|
||||
|
||||
name = hw.sdCard.path
|
||||
type = string
|
||||
default =
|
||||
abstract = SD Card image path
|
||||
|
||||
# Cache partition
|
||||
name = disk.cachePartition
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Cache partition support
|
||||
description = Whether we use a /cache partition on the device.
|
||||
|
||||
name = disk.cachePartition.path
|
||||
type = string
|
||||
default =
|
||||
abstract = Cache partition
|
||||
description = Cache partition to use on the device. Ignored if disk.cachePartition is not 'yes'.
|
||||
|
||||
name = disk.cachePartition.size
|
||||
type = diskSize
|
||||
abstract = Cache partition size
|
||||
default = 66MB
|
||||
|
||||
# LCD width
|
||||
name = hw.lcd.width
|
||||
type = integer
|
||||
default = 320
|
||||
abstract = LCD pixel width
|
||||
|
||||
name = hw.lcd.height
|
||||
type = integer
|
||||
default = 640
|
||||
abstract = LCD pixel height
|
||||
|
||||
name = hw.lcd.depth
|
||||
type = integer
|
||||
enum = 16, 32
|
||||
default = 16
|
||||
abstract = LCD color depth
|
||||
description = Color bit depth of emulated framebuffer.
|
||||
|
||||
# LCD density
|
||||
name = hw.lcd.density
|
||||
type = integer
|
||||
enum = 120, 160, 240, 213, 320
|
||||
default = 160
|
||||
abstract = Abstracted LCD density
|
||||
description = A value used to roughly describe the density of the LCD screen for automatic resource/asset selection.
|
||||
|
||||
# LCD backlight - Enable/Disable LCD backlight simulation
|
||||
# default = no : Disabled
|
||||
# default = yes : Enabled
|
||||
name = hw.lcd.backlight
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = LCD backlight
|
||||
description = Enable/Disable LCD backlight simulation,yes-enabled,no-disabled.
|
||||
|
||||
# Hardware OpenGLES emulation support
|
||||
#
|
||||
name = hw.gpu.enabled
|
||||
type = boolean
|
||||
default = no
|
||||
abstract = GPU emulation
|
||||
description = Enable/Disable emulated OpenGLES GPU
|
||||
|
||||
name = hw.gpu.mode
|
||||
type = string
|
||||
default = auto
|
||||
enum = auto, host, mesa
|
||||
abstract = GPU emulation mode
|
||||
description = This value determines how GPU emulation is implemented.
|
||||
|
||||
# Configures the initial orientation: portrait or landscape
|
||||
#
|
||||
name = hw.initialOrientation
|
||||
type = string
|
||||
enum = portrait, landscape
|
||||
default = portrait
|
||||
abstract = Initial screen orientation
|
||||
description = Setup initial screen orientation, can be rotated later on.
|
||||
|
||||
# Configures camera facing back
|
||||
#
|
||||
name = hw.camera.back
|
||||
type = string
|
||||
enum = emulated, none, webcam0, ...
|
||||
default = emulated
|
||||
abstract = Configures camera facing back
|
||||
description = Must be 'emulated' for a fake camera, 'webcam<N>' for a web camera, or 'none' if back camera is disabled.
|
||||
|
||||
# Configures camera facing front
|
||||
#
|
||||
name = hw.camera.front
|
||||
type = string
|
||||
enum = emulated, none, webcam0, ...
|
||||
default = none
|
||||
abstract = Configures camera facing front
|
||||
description = Must be 'emulated' for a fake camera, 'webcam<N>' for a web camera, or 'none' if front camera is disabled.
|
||||
|
||||
# Maximum VM heap size
|
||||
# Higher values are required for high-dpi devices
|
||||
# Default will depend on RAM size.
|
||||
name = vm.heapSize
|
||||
type = integer
|
||||
default = 0
|
||||
abstract = Max VM application heap size
|
||||
description = The maximum heap size a Dalvik application might allocate before being killed by the system. Value is in megabytes.
|
||||
|
||||
# Proximity sensor
|
||||
name = hw.sensors.proximity
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Proximity support
|
||||
description = Whether there is an proximity in the device.
|
||||
|
||||
# Magnetic field sensor
|
||||
name = hw.sensors.magnetic_field
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Magnetic field support
|
||||
description = Provides magnetic field sensor values.
|
||||
|
||||
# Orientation sensor
|
||||
name = hw.sensors.orientation
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Orientation support
|
||||
description = Provides orientation sensor values.
|
||||
|
||||
# Temperature sensor
|
||||
name = hw.sensors.temperature
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Temperature support
|
||||
description = Provides temperature sensor values.
|
||||
|
||||
# File system
|
||||
name = hw.useext4
|
||||
type = boolean
|
||||
default = yes
|
||||
abstract = Deprecated option. Ignored.
|
||||
description = Used to specify the Ext4 partition image type. This is now autodetected.
|
||||
|
||||
# Kernel image.
|
||||
#
|
||||
# kernel.path specified the path to the kernel image
|
||||
# kernel.parameters specifies the string of kernel boot parameters.
|
||||
#
|
||||
name = kernel.path
|
||||
type = string
|
||||
default =
|
||||
abstract = Path to the kernel image
|
||||
description = Path to the kernel image.
|
||||
|
||||
name = kernel.parameters
|
||||
type = string
|
||||
default =
|
||||
abstract = kernel boot parameters string.
|
||||
|
||||
name = kernel.newDeviceNaming
|
||||
type = string
|
||||
enum = autodetect, yes, no
|
||||
default = autodetect
|
||||
abstract = Does the kernel require a new device naming scheme?
|
||||
description = Used to specify whether the kernel requires a new device naming scheme. Typically for Linux 3.10 and above.
|
||||
|
||||
name = kernel.supportsYaffs2
|
||||
type = string
|
||||
enum = autodetect, yes, no
|
||||
default = autodetect
|
||||
abstract = Does the kernel supports YAFFS2 partitions?
|
||||
description = Used to specify whether the kernel supports YAFFS2 partition images. Typically before 3.10 only.
|
||||
|
||||
# Path to the ramdisk image.
|
||||
name = disk.ramdisk.path
|
||||
type = string
|
||||
default =
|
||||
abstract = Path to the ramdisk image
|
||||
description = Path to the ramdisk image.
|
||||
|
||||
# System partition image(s).
|
||||
#
|
||||
# disk.systemPartition.path points to the read/write system partition image.
|
||||
# if empty, a temporary file will be created, initialized with the content
|
||||
# of .initPath
|
||||
#
|
||||
# disk.systemPartition.initPath is only used when .path is empty. It must
|
||||
# then point to a read-only initialization system image file.
|
||||
#
|
||||
# disk.systemPartition.size is the ideal size of the system partition. The
|
||||
# size is ignored if the actual system partition image is larger. Otherwise,
|
||||
# it indicates the maximum size the disk image file can grow to.
|
||||
#
|
||||
name = disk.systemPartition.path
|
||||
type = string
|
||||
default =
|
||||
abstract = Path to runtime system partition image
|
||||
|
||||
name = disk.systemPartition.initPath
|
||||
type = string
|
||||
default =
|
||||
abstract = Initial system partition image
|
||||
|
||||
name = disk.systemPartition.size
|
||||
type = diskSize
|
||||
default = 0
|
||||
abstract = Ideal size of system partition
|
||||
|
||||
# Path to the data partition.
|
||||
name = disk.dataPartition.path
|
||||
type = string
|
||||
default = <temp>
|
||||
abstract = Path to data partition file
|
||||
description = Path to data partition file. Cannot be empty. Special value <temp> means using a temporary file. If disk.dataPartition.initPath is not empty, its content will be copied to the disk.dataPartition.path file at boot-time.
|
||||
|
||||
# Initial path to the data partition.
|
||||
name = disk.dataPartition.initPath
|
||||
type = string
|
||||
default =
|
||||
abstract = Initial data partition
|
||||
description = If not empty, its content will be copied to the disk.dataPartition.path file at boot-time.
|
||||
|
||||
# Data partition size.
|
||||
name = disk.dataPartition.size
|
||||
type = diskSize
|
||||
default = 0
|
||||
abstract = Ideal size of data partition
|
||||
|
||||
# Path to the snapshots storage file.
|
||||
name = disk.snapStorage.path
|
||||
type = string
|
||||
default =
|
||||
abstract = Path to snapshot storage
|
||||
description = Path to a 'snapshot storage' file, where all snapshots are stored.
|
||||
|
||||
# Android AVD name
|
||||
# This is set automatically before launching a core.
|
||||
#
|
||||
name = avd.name
|
||||
type = string
|
||||
default = <build>
|
||||
abstract = Name of the AVD being run
|
BIN
android/tools/android-osx/tools/lib/hierarchyviewer2.jar
Executable file
BIN
android/tools/android-osx/tools/lib/hierarchyviewer2.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/hierarchyviewer2lib.jar
Executable file
BIN
android/tools/android-osx/tools/lib/hierarchyviewer2lib.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/httpclient-4.1.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/httpclient-4.1.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/httpcore-4.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/httpcore-4.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/httpmime-4.1.jar
Executable file
BIN
android/tools/android-osx/tools/lib/httpmime-4.1.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jcommon-1.0.12.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jcommon-1.0.12.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jfreechart-1.0.9.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jfreechart-1.0.9.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jfreechart-swt-1.0.9.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jfreechart-swt-1.0.9.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jobb.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jobb.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jsilver-1.0.0.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jsilver-1.0.0.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/junit-4.12.jar
Executable file
BIN
android/tools/android-osx/tools/lib/junit-4.12.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/jython-standalone-2.5.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/jython-standalone-2.5.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/kxml2-2.3.0.jar
Executable file
BIN
android/tools/android-osx/tools/lib/kxml2-2.3.0.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/layoutlib-api.jar
Executable file
BIN
android/tools/android-osx/tools/lib/layoutlib-api.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/lint-api.jar
Executable file
BIN
android/tools/android-osx/tools/lib/lint-api.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/lint-checks.jar
Executable file
BIN
android/tools/android-osx/tools/lib/lint-checks.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/lint-tests.jar
Executable file
BIN
android/tools/android-osx/tools/lib/lint-tests.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/lint.jar
Executable file
BIN
android/tools/android-osx/tools/lib/lint.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/lombok-ast-0.2.3.jar
Executable file
BIN
android/tools/android-osx/tools/lib/lombok-ast-0.2.3.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/manifest-merger.jar
Executable file
BIN
android/tools/android-osx/tools/lib/manifest-merger.jar
Executable file
Binary file not shown.
BIN
android/tools/android-osx/tools/lib/monkeyrunner.jar
Executable file
BIN
android/tools/android-osx/tools/lib/monkeyrunner.jar
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user