diff options
Diffstat (limited to 'tests')
135 files changed, 5816 insertions, 107 deletions
diff --git a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/DisplaySinkService.java b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/DisplaySinkService.java index daec845..8189fa9 100644 --- a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/DisplaySinkService.java +++ b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/DisplaySinkService.java @@ -30,6 +30,7 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; +import java.io.IOException; import java.nio.ByteBuffer; public class DisplaySinkService extends Service implements SurfaceHolder.Callback { @@ -150,7 +151,12 @@ public class DisplaySinkService extends Service implements SurfaceHolder.Callbac if (mSurface != null) { MediaFormat format = MediaFormat.createVideoFormat( "video/avc", mSurfaceWidth, mSurfaceHeight); - mCodec = MediaCodec.createDecoderByType("video/avc"); + try { + mCodec = MediaCodec.createDecoderByType("video/avc"); + } catch (IOException e) { + throw new RuntimeException( + "failed to create video/avc decoder", e); + } mCodec.configure(format, mSurface, null, 0); mCodec.start(); mCodecBufferInfo = new BufferInfo(); diff --git a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java index 256f900..a4faca5 100644 --- a/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java +++ b/tests/AccessoryDisplay/source/src/com/android/accessorydisplay/source/DisplaySourceService.java @@ -32,6 +32,7 @@ import android.os.Message; import android.view.Display; import android.view.Surface; +import java.io.IOException; import java.nio.ByteBuffer; public class DisplaySourceService extends Service { @@ -191,8 +192,13 @@ public class DisplaySourceService extends Service { format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE); format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL); - - MediaCodec codec = MediaCodec.createEncoderByType("video/avc"); + MediaCodec codec; + try { + codec = MediaCodec.createEncoderByType("video/avc"); + } catch (IOException e) { + throw new RuntimeException( + "failed to create video/avc encoder", e); + } codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); Surface surface = codec.createInputSurface(); codec.start(); diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java index 2b5e674..ea08a6a 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java @@ -22,11 +22,25 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.GridLayout; -import android.widget.*; +import android.widget.Space; +import android.widget.TextView; -import static android.text.InputType.*; -import static android.widget.GridLayout.*; +import static android.text.InputType.TYPE_CLASS_TEXT; +import static android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; +import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD; +import static android.widget.GridLayout.ALIGN_BOUNDS; +import static android.widget.GridLayout.BASELINE; +import static android.widget.GridLayout.CENTER; +import static android.widget.GridLayout.FILL; +import static android.widget.GridLayout.LEFT; +import static android.widget.GridLayout.RIGHT; +import static android.widget.GridLayout.START; +import static android.widget.GridLayout.Spec; +import static android.widget.GridLayout.spec; public class BiDiTestGridLayoutCodeLtr extends Fragment { diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java index 3a03c6c..fc3a92c 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java @@ -22,11 +22,25 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.GridLayout; -import android.widget.*; +import android.widget.Space; +import android.widget.TextView; -import static android.text.InputType.*; -import static android.widget.GridLayout.*; +import static android.text.InputType.TYPE_CLASS_TEXT; +import static android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; +import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD; +import static android.widget.GridLayout.ALIGN_BOUNDS; +import static android.widget.GridLayout.BASELINE; +import static android.widget.GridLayout.CENTER; +import static android.widget.GridLayout.FILL; +import static android.widget.GridLayout.LEFT; +import static android.widget.GridLayout.RIGHT; +import static android.widget.GridLayout.START; +import static android.widget.GridLayout.Spec; +import static android.widget.GridLayout.spec; public class BiDiTestGridLayoutCodeRtl extends Fragment { diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java index ef885e3..ec02d34 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java @@ -117,7 +117,7 @@ public class GraphReader { } @Override - public void execute(CommandStack stack) { + public void execute(CommandStack stack) { Filter filter = null; try { filter = stack.getFactory().createFilterByClassName(mClassName, diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/AudioTrackDecoder.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/AudioTrackDecoder.java index 0219fd7..3b3de9f 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/AudioTrackDecoder.java +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/AudioTrackDecoder.java @@ -59,8 +59,15 @@ public class AudioTrackDecoder extends TrackDecoder { @Override protected MediaCodec initMediaCodec(MediaFormat format) { - MediaCodec mediaCodec = MediaCodec.createDecoderByType( - format.getString(MediaFormat.KEY_MIME)); + MediaCodec mediaCodec; + try { + mediaCodec = MediaCodec.createDecoderByType( + format.getString(MediaFormat.KEY_MIME)); + } catch (IOException e) { + throw new RuntimeException( + "failed to create decoder for " + + format.getString(MediaFormat.KEY_MIME), e); + } mediaCodec.configure(format, null, null, 0); return mediaCodec; } diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/CpuVideoTrackDecoder.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/CpuVideoTrackDecoder.java index 96f3059..a624010 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/CpuVideoTrackDecoder.java +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/CpuVideoTrackDecoder.java @@ -29,6 +29,7 @@ import androidx.media.filterfw.Frame; import androidx.media.filterfw.FrameImage2D; import androidx.media.filterfw.PixelUtils; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashSet; @@ -214,7 +215,13 @@ public class CpuVideoTrackDecoder extends VideoTrackDecoder { return null; } else { String bestCodec = candidateCodecs.firstEntry().getValue(); - return MediaCodec.createByCodecName(bestCodec); + try { + return MediaCodec.createByCodecName(bestCodec); + } catch (IOException e) { + throw new RuntimeException( + "failed to create codec for " + + bestCodec, e); + } } } diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/GpuVideoTrackDecoder.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/GpuVideoTrackDecoder.java index bbba9d8..f5eb513 100644 --- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/GpuVideoTrackDecoder.java +++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/decoder/GpuVideoTrackDecoder.java @@ -28,6 +28,7 @@ import androidx.media.filterfw.FrameImage2D; import androidx.media.filterfw.ImageShader; import androidx.media.filterfw.TextureSource; +import java.io.IOException; import java.nio.ByteBuffer; /** @@ -86,9 +87,16 @@ public class GpuVideoTrackDecoder extends VideoTrackDecoder { @Override protected MediaCodec initMediaCodec(MediaFormat format) { + MediaCodec mediaCodec; + try { + mediaCodec = MediaCodec.createDecoderByType( + format.getString(MediaFormat.KEY_MIME)); + } catch (IOException e) { + throw new RuntimeException( + "failed to create decoder for " + + format.getString(MediaFormat.KEY_MIME), e); + } Surface surface = new Surface(mSurfaceTexture); - MediaCodec mediaCodec = MediaCodec.createDecoderByType( - format.getString(MediaFormat.KEY_MIME)); mediaCodec.configure(format, surface, null, 0); surface.release(); return mediaCodec; diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java index 0b85189..8d8d9de 100644 --- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java +++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java @@ -97,7 +97,7 @@ abstract public class CompareActivity extends Activity { Log.d(LOG_TAG, "failure to access hardware layer"); return; } - Method copyInto = hardwareLayer.getClass().getSuperclass() + Method copyInto = hardwareLayer.getClass() .getDeclaredMethod("copyInto", Bitmap.class); if (!copyInto.isAccessible()) copyInto.setAccessible(true); diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java index a08b558..c90b626 100644 --- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java +++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java @@ -35,23 +35,24 @@ public class ErrorCalculator { private static final boolean LOG_TIMING = false; private static final boolean LOG_CALC = false; - private final RenderScript mRS; + private RenderScript mRS; private Allocation mIdealPixelsAllocation; private Allocation mGivenPixelsAllocation; private Allocation mOutputPixelsAllocation; - private final Allocation mInputRowsAllocation; - private final Allocation mOutputRegionsAllocation; + private Allocation mInputRowsAllocation; + private Allocation mOutputRegionsAllocation; - private final ScriptC_errorCalculator mScript; + private ScriptC_errorCalculator mScript; - private final int[] mOutputRowRegions; + private int[] mOutputRowRegions; public ErrorCalculator(Context c, Resources resources) { int width = resources.getDimensionPixelSize(R.dimen.layer_width); int height = resources.getDimensionPixelSize(R.dimen.layer_height); mOutputRowRegions = new int[height / REGION_SIZE]; +/* mRS = RenderScript.create(c); int[] rowIndices = new int[height / REGION_SIZE]; for (int i = 0; i < rowIndices.length; i++) @@ -67,12 +68,15 @@ public class ErrorCalculator { mInputRowsAllocation.copyFrom(rowIndices); mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS), mOutputRowRegions.length, Allocation.USAGE_SCRIPT); +*/ } private static long startMillis, middleMillis; public float calcErrorRS(Bitmap ideal, Bitmap given) { + if (true) + return calcError(ideal, given); if (LOG_TIMING) { startMillis = System.currentTimeMillis(); } diff --git a/tests/DynamicDrawableTest/Android.mk b/tests/DynamicDrawableTest/Android.mk new file mode 100644 index 0000000..5c51301 --- /dev/null +++ b/tests/DynamicDrawableTest/Android.mk @@ -0,0 +1,26 @@ +# +# Copyright (C) 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. +# 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := DynamicDrawableTest + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_PACKAGE) diff --git a/tests/DynamicDrawableTest/AndroidManifest.xml b/tests/DynamicDrawableTest/AndroidManifest.xml new file mode 100644 index 0000000..4ca3e3c --- /dev/null +++ b/tests/DynamicDrawableTest/AndroidManifest.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 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. + 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.test.dynamic" > + <uses-sdk android:minSdkVersion="11" /> + + <application + android:hardwareAccelerated="true" + android:label="vector" > + <activity + android:name="VectorDrawableTest" + android:label="Vector Icon" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity + android:name="VectorDrawable01" + android:label="VectorTest1" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + </activity> + + <activity + android:name="VectorDrawablePerformance" + android:label="Vector Performance" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + + </activity> + + <activity + android:name="VectorDrawableDupPerf" + android:label="Vector Performance of clones" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + + </activity> + <activity + android:name="VectorDrawableStaticPerf" + android:label="Performance of vector images" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + + </activity> + + <activity + android:name="VectorCheckbox" + android:label="On a Checkbox" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + + </activity> + <activity + android:name="VectorPathChecking" + android:label="Path Checking graphics" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="com.android.test.dynamic.TEST" /> + </intent-filter> + + </activity> + </application> + +</manifest>
\ No newline at end of file diff --git a/tests/DynamicDrawableTest/lint.xml b/tests/DynamicDrawableTest/lint.xml new file mode 100644 index 0000000..ee0eead --- /dev/null +++ b/tests/DynamicDrawableTest/lint.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lint> +</lint>
\ No newline at end of file diff --git a/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png Binary files differnew file mode 100644 index 0000000..60fbdf5 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable-hdpi/icon.png diff --git a/tests/DynamicDrawableTest/res/drawable/icon.png b/tests/DynamicDrawableTest/res/drawable/icon.png Binary files differnew file mode 100644 index 0000000..cb40a19 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/icon.png diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml new file mode 100644 index 0000000..4f4b386 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable01.xml @@ -0,0 +1,73 @@ +<!-- + Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:trigger="state_checked" > + + <size + android:height="64dp" + android:width="64dp" /> + + <viewport + android:viewportHeight="480" + android:viewportWidth="480" /> + + <group> + <path + android:name="check" + android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z" + android:fill="#ffff00ff" + android:stroke="#FF00FF00" + android:strokeWidth="5" /> + </group> + <group> + <path + android:name="box1" + android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z" + android:fill="#ffffffff" + android:stroke="#FF00FF00" + android:strokeWidth="5" /> + </group> + <group> + <path + android:name="box2" + android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z" + android:fill="#ff000000" + android:rotation="46.757" + android:pivotX="162" + android:pivotY="173.5" + android:stroke="#FF00FF00" + android:strokeWidth="5" /> + </group> + <group> + <path + android:name="box3" + android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z" + android:stroke="#FF000000" + android:strokeWidth="4" /> + </group> + <group> + <path + android:name="box4" + android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z" + android:stroke="#FF000000" + android:strokeWidth="30" /> + </group> + + <animation + android:durations="300,100,0,300" + android:sequence="check,box1,box2,box3,box4" /> + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml new file mode 100644 index 0000000..49906d17 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable02.xml @@ -0,0 +1,46 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="320" + android:viewportHeight="320"/> + + <group> + <path + android:name="arrow" + android:pathData="M 100,225 L 100,115 L 130,115 L 70,15 L 10,115 L 40,115 L 40,225 z" + android:fill="#ffffffff" + android:stroke="#FF00FF00" + android:strokeWidth="1"/> + </group> + <group> + <path + android:name="house" + android:pathData="M 130,225 L 130,115 L 130,115 L 70,15 L 10,115 L 10,115 L 10,225 z" + android:fill="#ff440000" + android:stroke="#FF00FF00" + android:strokeWidth="10" + android:rotation="180" + android:pivotX="70" + android:pivotY="120" + android:trimPathStart=".1" + android:trimPathEnd=".9"/> + </group> + <animation android:sequence="arrow,house"/> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml new file mode 100644 index 0000000..137049d --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable03.xml @@ -0,0 +1,137 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport + android:viewportWidth="7.30625" + android:viewportHeight="12.25"/> + + <group> + + <path + android:name="clip1" + android:pathData=" + M 0, 0 + l 7.3, 0 + l 0, 0 + l -7.3, 0 + z" + android:clipToPath="true" + android:rotation="-30" + android:pivotX="3.65" + android:pivotY="6.125" + /> + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 + l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ff88ff" + /> + <path + android:name="clip2" + android:pathData=" + M 0, 0 + l 7.3, 0 + l 0, 12.25 + l -7.3, 0 + z" + android:clipToPath="true" + android:rotation="-30" + android:pivotX="3.65" + android:pivotY="6.125" + /> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ff88ff" + /> + </group> + <group> + <path + android:name="clip1" + android:pathData=" + M 0, 0 + l 7.3, 0 + l 0, 12.25 + l -7.3, 0 + z" + android:clipToPath="true" + android:rotation="-30" + android:pivotX="3.65" + android:pivotY="6.125" + /> + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 + l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ff88ff" + /> + <path + android:name="clip2" + android:pathData=" + M 0, 12.25 + l 7.3, 0 + l 0, 12.25 + l -7.3, 0 + z" + android:clipToPath="true" + android:rotation="-30" + android:pivotX="3.65" + android:pivotY="6.125" + /> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ff88ff" + /> + </group> + + + <animation + android:sequence="one,one" + android:durations="4000"/> + <animation + android:sequence="two,two" + android:durations="4000"/> + <animation + android:sequence="clip1,clip1" + android:durations="4000"/> + <animation + android:sequence="clip2,clip2" + android:durations="4000"/> + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml new file mode 100644 index 0000000..cffb73f --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable04.xml @@ -0,0 +1,126 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android"> + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport + android:viewportWidth="7.30625" + android:viewportHeight="12.25"/> + + <group> + <path + android:name="clip1" + android:pathData=" + M 3.65, 6.125 + m -.001, 0 + a .001,.001 0 1,0 .002,0 + a .001,.001 0 1,0 -.002,0z" + android:clipToPath="true" + android:fill="#112233" + /> + + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 + l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ff88ff" + /> + <path + android:name="clip2" + android:pathData=" + M 3.65, 6.125 + m -6, 0 + a 6,6 0 1,0 12,0 + a 6,6 0 1,0 -12,0z" + android:clipToPath="true" + android:fill="#112233" + /> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ff88ff" + /> + </group> + <group> + <path + android:name="clip1" + android:pathData=" + M 3.65, 6.125 + m -6, 0 + a 6,6 0 1,0 12,0 + a 6,6 0 1,0 -12,0z" + android:clipToPath="true" + android:fill="#332233" + /> + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 + l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ff88ff" + /> + <path + android:name="clip2" + android:pathData=" + M 3.65, 6.125 + m -.001, 0 + a .001,.001 0 1,0 .002,0 + a .001,.001 0 1,0 -.002,0z" + android:clipToPath="true" + android:fill="#662233" + /> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ff88ff" + /> + </group> + + + + <animation + android:sequence="one,one" + android:durations="4000"/> + <animation + android:sequence="two,two" + android:durations="4000"/> + <animation + android:sequence="clip1,clip1" + android:durations="4000"/> + <animation + android:sequence="clip2,clip2" + android:durations="4000"/> + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml new file mode 100644 index 0000000..bcf3ae6 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable05.xml @@ -0,0 +1,147 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport + android:viewportWidth="7.30625" + android:viewportHeight="12.25"/> + + <group> + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 + l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 + l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ffff00" + /> + + + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ffff00" + android:fillOpacity="0" + /> + </group> + <group> + <path + android:name="one" + android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125 +l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0 +l -5.046875,0.0 0.0,-1.0Z" + android:fill="#ffff00" + android:fillOpacity="0" + /> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ffff00" + /> + </group> + <group> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ffff00" + /> + <path + android:name="three" + android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625 + q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125 + q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125 + l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625 + q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125 + q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375 + l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375 + q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125 + q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375 + q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125 + q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375 + q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375 + q -0.40625,0.5 -1.171875,0.6875Z" + android:fill="#ffff00" + android:fillOpacity="0" + /> + </group> + <group> + <path + android:name="two" + android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375 + q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625 + q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625 + q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875 + q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875 + q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875 + q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625 + q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375 + q -0.78125024,0.8125 -2.2187502,2.265625Z" + android:fill="#ffff00" + android:fillOpacity="0" + /> + <path + android:name="three" + android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625 + q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125 + q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125 + l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625 + q 1.109375,0.0 1.6875,-0.4375 0.59375,-0.4375 0.59375,-1.28125 + q 0.0,-0.765625 -0.546875,-1.203125 -0.546875,-0.4375 -1.5,-0.4375 + l -1.03125,0.0 0.0,-0.96875 1.078125,0.0q 0.859375,0.0 1.328125,-0.34375 + q 0.46875,-0.359375 0.46875,-1.015625 0.0,-0.671875 -0.484375,-1.03125 + q -0.46875,-0.359375 -1.359375,-0.359375 -0.5,0.0 -1.0625,0.109375 + q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125 + q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375 + q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375 + q -0.40625,0.5 -1.171875,0.6875Z" + android:fill="#ffff00" + /> + </group> + + + <animation + android:sequence="one,one,three,three" + android:durations="2000,0,2000"/> + <animation + android:sequence="two,two,two,two" + android:durations="2000,0,2000"/> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml new file mode 100644 index 0000000..73ff5e2 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable06.xml @@ -0,0 +1,76 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport + android:viewportWidth="700" + android:viewportHeight="700"/> + + <group> + </group> + <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z" + android:name="path2451" + android:stroke="#FF000000" + android:strokeWidth="30.65500000000000"/> + <path android:pathData="M 365.015 311.066" + android:name="path2453" + android:stroke="#FF000000" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928" + android:name="path2455" + android:stroke="#FF000000" + android:fill="#FF0000FF" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 170.515 451.566L 305.61 313.46" + android:name="path2457" + android:stroke="#000000" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 557.968 449.974L 426.515 315.375" + android:name="path2459" + android:stroke="#000000" + android:strokeWidth="30.655000000000001"/> + <group> + <path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z" + android:name="path2451" + android:stroke="#FF000000" + android:strokeWidth="30.65500000000000"/> + <path android:pathData="M 365.015 311.066" + android:name="path2453" + android:stroke="#FF000000" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928" + android:name="path2455" + android:stroke="#FF000000" + android:fill="#FFFFFFFF" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 170.515 451.566L 305.61 313.46" + android:name="path2457" + android:stroke="#000000" + android:strokeWidth="30.655000000000001"/> + <path android:pathData="M 557.968 449.974L 426.515 315.375" + android:name="path2459" + android:stroke="#000000" + android:strokeWidth="30.655000000000001"/> + </group> + + <animation android:sequence="path2451,path2451" + android:durations="1000"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml new file mode 100644 index 0000000..99d37ef --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable07.xml @@ -0,0 +1,45 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="140" + android:viewportHeight="110"/> + <group> + <path + android:name="menu" + android:pathData="M 20,20 l 100,0 0,10 -100,0 z + M 20,50 l 100,0 0,10 -100,0 z + M 20,80 l 0,-10 100,0 0,10 z" + android:fill="#ffffffff"/> + </group> + <group> + <path + android:name="back" + android:pathData="M 20,55 l 35.3,-35.3 7.07,7.07 -35.3,35.3 z + M 27,50 l 97,0 0,10 -97,0 z + M 20,55 l 7.07,-7.07 35.3,35.3 -7.07,7.07 z" + android:fill="#ffffffff" + android:rotation="180" + android:pivotX="70" + android:pivotY="55" + /> + </group> + <animation android:sequence="menu,back"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml new file mode 100644 index 0000000..f8a03d7 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable08.xml @@ -0,0 +1,48 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + + <viewport android:viewportWidth="600" + android:viewportHeight="600"/> + + <group> + <path + android:name="pie1" + android:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z" + android:fill="#ffffcc00" + android:stroke="#FF00FF00" + android:strokeWidth="1"/> + </group> + + <group> + <path + android:name="pie2" + android:pathData="M564.441,287A280.868,280.868 0 1,1 564.441,285L284.493,286.29Z" + android:fill="#FFccaa00" + android:stroke="#FF000000" + android:strokeWidth="10" + android:pivotX="90" + android:pivotY="100"/> + </group> + + <animation android:sequence="pie1,pie2"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml new file mode 100644 index 0000000..09934de --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable09.xml @@ -0,0 +1,41 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + + <viewport android:viewportWidth="200" + android:viewportHeight="200"/> + + <group> + <path + android:name="arrow" + android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z" + android:fill="#ffffffff"/> + </group> + <group> + <path + android:name="house" + android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z" + android:fill="#ffffffff" + android:rotation="90" + android:pivotX="100" + android:pivotY="100"/> + </group> + <animation android:sequence="arrow,house"/> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml new file mode 100644 index 0000000..f17f67a --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable10.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:height="64dp" + android:width="64dp" /> + + <viewport + android:viewportHeight="200" + android:viewportWidth="200" /> + + <group> + <path + android:name="bar3" + android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar2" + android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" + android:fill="#FF555555" /> + <path + android:name="bar1" + android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" + android:fill="#FF555555" /> + <path + android:name="bar0" + android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" + android:fill="#FF555555" /> + </group> + <group> + <path + android:name="bar3" + android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar2" + android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar1" + android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" + android:fill="#FF555555" /> + <path + android:name="bar0" + android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" + android:fill="#FF555555" /> + </group> + + <group> + <path + android:name="bar3" + android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar2" + android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar1" + android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar0" + android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" + android:fill="#FF555555" /> + </group> + + <group> + <path + android:name="bar3" + android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar2" + android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar1" + android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" + android:fill="#FFFFFFFF" /> + <path + android:name="bar0" + android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" + android:fill="#FFFFFFFF" /> + </group> + + <animation + android:sequence="bar0,bar0,bar0,bar0" + android:durations="500,500,500"/> + <animation + android:sequence="bar1,bar1,bar1,bar1" + android:durations="500,500,500"/> + <animation + android:sequence="bar2,bar2,bar2,bar2" + android:durations="500,500,500"/> + <animation + android:sequence="bar3,bar3,bar3,bar3" + android:durations="500,500,500"/> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml new file mode 100644 index 0000000..a1a03be --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable11.xml @@ -0,0 +1,62 @@ +<!-- + Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:height="64dp" + android:width="64dp" /> + + <viewport + android:viewportHeight="80" + android:viewportWidth="40" /> + + <group> + <path + android:name="battery" + android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z" + android:fill="#3388ff" + android:stroke="#ff8833" + android:strokeWidth="1" + android:rotation="0"/> + <path + android:name="spark" + android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" + android:fill="#FFFF0000" /> + + </group> + <group> + <path + android:name="battery" + android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z" + android:fill="#ff8833" + android:stroke="#3388ff" + android:strokeWidth="1" + android:rotation="0" /> + <path + android:name="spark" + android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" + android:fill="#FFFF0000" /> + </group> + + <animation + android:durations="2000" + android:sequence="spark,spark" /> + <animation + android:durations="2000" + android:sequence="battery,battery" /> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml new file mode 100644 index 0000000..89748d5 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable12.xml @@ -0,0 +1,90 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + + <viewport android:viewportWidth="600" + android:viewportHeight="600"/> + + <group> + <path + android:name="pie1" + android:pathData="M300,70 a230,230 0 1,0 1,0 z" + android:stroke="#FF00FF00" + android:strokeWidth="70" + android:trimPathStart="0" + android:trimPathEnd=".75" + android:trimPathOffset="0"/> + + <path + android:name="v" + android:pathData="M300,70 l 0,-70 70,70 -70,70z" + android:fill="#FF00FF00" + android:pivotX="300" + android:pivotY="300" + android:rotation="0" + /> + </group> + + <group> + <path + android:name="v" + android:pathData="M300,70 l 0,-70 70,70 -70,70z" + android:pivotX="300" + android:pivotY="300" + android:rotation="360"/> + <path + android:name="pie2" + android:pathData="M300,70 a230,230 0 1,0 1,0 z" + android:stroke="#FF00FF00" + android:strokeWidth="70" + android:rotation="360" + android:pivotX="300" + android:pivotY="300" + android:trimPathStart="0" + android:trimPathEnd=".5" + android:trimPathOffset="0" + android:strokeLineCap="round" + /> + </group> + + <animation android:sequence="pie1,pie2" + android:durations="2000" + android:startOffset="500" + android:repeatCount="-1" + android:repeatStyle="forward" + android:animate="easeInOut" + /> + <animation android:sequence="v,v" + android:durations="2000" + android:startOffset="500" + android:repeatCount="-1" + android:repeatStyle="forward" + android:animate="easeInOut" + /> + <animation android:sequence="pie1,pie2" + android:durations="2800" + android:startOffset="500" + android:limitTo="trimPathEnd" + android:repeatCount="-1" + android:repeatStyle="reverse" + android:animate="easeInOut" + /> + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml new file mode 100644 index 0000000..43dda52 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable13.xml @@ -0,0 +1,82 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + + <viewport android:viewportWidth="600" + android:viewportHeight="400"/> + + <group> + <path + android:name="pie1" + android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z" + android:fill="#ffffffff" + android:stroke="#FF00FF00" + android:strokeWidth="1"/> + + <path + android:name="half" + android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z" + android:fill="#FFFF0000" + android:stroke="#FF0000FF" + android:strokeWidth="5" + android:rotation="0" + android:pivotX="300" + android:pivotY="200"/> + </group> + + <group> + <path + android:name="pie2" + android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z" + android:fill="#ffff0000" + android:stroke="#FF00FF00" + android:strokeWidth="10" + android:rotation="360" + android:pivotX="300" + android:pivotY="200"/> + + <path + android:name="half" + android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z" + android:fill="#FFFFFF00" + android:stroke="#FF0000FF" + android:strokeWidth="5" + android:rotation="-360" + android:pivotX="300" + android:pivotY="200"/> + </group> + <animation android:sequence="pie1,pie2" + android:durations="1000" + android:startOffset="500" + android:repeatCount="2" + android:repeatStyle="forward" + android:animate="easeInOut" + /> + <animation android:sequence="half,half" + android:durations="1000" + android:startOffset="500" + android:repeatCount="5" + android:repeatStyle="forward" + android:animate="easeInOut" + /> + + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml new file mode 100644 index 0000000..0f1f149 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable14.xml @@ -0,0 +1,54 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="800" + android:viewportHeight="500"/> + + <group> + <path + android:name="pie1" + android:pathData="M200,450 l 50,-25 + a25,25 -30 0,1 100,-50 l 50,-25 + a25,50 -30 0,1 100,-50 l 50,-25 + a25,75 -30 0,1 100,-50 l 50,-25 + a25,100 -30 0,1 100,-50 l 50,-25" + android:stroke="#FF00FF00" + android:strokeWidth="10"/> + </group> + + <group> + <path + android:name="pie2" + android:pathData="M200,350 l 50,-25 + a25,12 -30 0,1 100,-50 l 50,-25 + a25,25 -30 0,1 100,-50 l 50,-25 + a25,37 -30 0,1 100,-50 l 50,-25 + a25,50 -30 0,1 100,-50 l 50,-25" + android:stroke="#FF00FF00" + android:strokeWidth="10" + android:rotation="20" + android:pivotX="90" + android:pivotY="100"/> + + </group> + <animation android:sequence="pie1,pie2"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml new file mode 100644 index 0000000..6bc946f --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable15.xml @@ -0,0 +1,48 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="500" + android:viewportHeight="400"/> + + <group> + <path + android:name="arrow" + android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200" + android:fill="#ffffffff" + android:stroke="#FFFF0000" + android:strokeWidth="1"/> + </group> + + <group> + <path + android:name="house" + android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200" + android:fill="#ff440000" + android:stroke="#FFFF0000" + android:strokeWidth="10" + android:rotation="180" + android:pivotX="250" + android:pivotY="200"/> + </group> + + <animation android:sequence="arrow,house"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml new file mode 100644 index 0000000..c9c8e8a --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable16.xml @@ -0,0 +1,46 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="200" + android:viewportHeight="200"/> + + <group> + <path + android:name="arrow" + android:pathData="M 100,10 v 180 M 10,100 h 180" + android:stroke="#FF00FF00" + android:strokeWidth="1"/> + </group> + + <group> + <path + android:name="house" + android:pathData="M 100,10 v 90 M 10,100 h 90" + android:stroke="#FF00FF00" + android:strokeWidth="10" + android:rotation="360" + android:pivotX="100" + android:pivotY="100"/> + </group> + + <animation android:sequence="arrow,house"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml new file mode 100644 index 0000000..9427652 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable17.xml @@ -0,0 +1,46 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="1200" + android:viewportHeight="600"/> + + <group> + <path + android:name="arrow" + android:pathData="M200,300 Q400,50 600,300 T1000,300" + android:stroke="#FF00FF00" + android:strokeWidth="1"/> + </group> + + <group> + <path + android:name="house" + android:pathData="M200,300 Q400,50 600,300 T1000,300" + android:stroke="#FFFF0000" + android:strokeWidth="10" + android:rotation="360" + android:pivotX="600" + android:pivotY="300"/> + </group> + + <animation android:sequence="arrow,house"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml new file mode 100644 index 0000000..83dfbd2 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable18.xml @@ -0,0 +1,45 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="500" + android:viewportHeight="400"/> + + <group> + <path + android:name="arrow" + android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200" + android:stroke="#FFFFFF00" + android:strokeWidth="10"/> + </group> + + <group> + <path + android:name="house" + android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200" + android:strokeWidth="10" + android:rotation="360" + android:pivotX="250" + android:pivotY="200"/> + </group> + + <animation android:sequence="arrow,house"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml new file mode 100644 index 0000000..013254f --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable19.xml @@ -0,0 +1,45 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="1000" + android:viewportHeight="800"/> + + <group> + <path + android:name="arrow" + android:pathData="M10,300 Q400,50 600,300 T1000,300" + android:stroke="#FF00FFFF" + android:strokeWidth="40"/> + </group> + + <group> + <path + android:name="house" + android:pathData="M10,300 Q400,550 600,300 T1000,300" + android:stroke="#FFFF0000" + android:strokeWidth="60" + android:pivotX="90" + android:pivotY="100"/> + </group> + + <animation android:sequence="arrow,house"/> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml new file mode 100644 index 0000000..aba7e5f --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_drawable20.xml @@ -0,0 +1,37 @@ +<!-- Copyright (C) 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. + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + + <size + android:width="64dp" + android:height="64dp"/> + + <viewport android:viewportWidth="480" + android:viewportHeight="480"/> + + <group> + <path + android:name="edit" + android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333 + c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40 + c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522 + c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z" + android:stroke="#FF000000" + android:fill="#FF00FFFF" + android:strokeWidth="10"/> + </group> + + +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml new file mode 100644 index 0000000..8897181 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_create.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="64dp" +android:height="64dp"/> + + <viewport android:viewportWidth="24" + android:viewportHeight="24"/> + +<group> +<path + android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z" + android:fill="#FF000000" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml new file mode 100644 index 0000000..2c7ebbd --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_delete.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="64dp" +android:height="64dp"/> + + <viewport android:viewportWidth="24" + android:viewportHeight="24"/> + +<group> +<path + android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" + android:fill="#FF000000" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml new file mode 100644 index 0000000..e4cf78c --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_heart.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="64dp" +android:height="64dp"/> + + <viewport android:viewportWidth="24" + android:viewportHeight="24"/> + +<group> +<path + android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" + android:fill="#FF000000" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml new file mode 100644 index 0000000..cec12ba --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_schedule.xml @@ -0,0 +1,33 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="64dp" +android:height="64dp"/> + + <viewport android:viewportWidth="24" + android:viewportHeight="24"/> + +<group> +<path + android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z" + android:fillOpacity="0.9" + /> +<path + android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z" + android:fillOpacity="0.9" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml new file mode 100644 index 0000000..5fe1fb6 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_icon_settings.xml @@ -0,0 +1,29 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="64dp" +android:height="64dp"/> + + <viewport android:viewportWidth="24" + android:viewportHeight="24"/> + +<group> +<path + android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z" + android:fill="#FF000000" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test01.xml b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml new file mode 100644 index 0000000..6beb9d8 --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_test01.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="128dp" +android:height="128dp"/> + + <viewport android:viewportWidth="512" + android:viewportHeight="512"/> + +<group> +<path + android:name="002b" + android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299" + android:stroke="#FF0000FF" + android:strokeWidth="4" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/drawable/vector_test02.xml b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml new file mode 100644 index 0000000..2c1a28e --- /dev/null +++ b/tests/DynamicDrawableTest/res/drawable/vector_test02.xml @@ -0,0 +1,31 @@ +<!-- Copyright (C) 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. +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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > +<size +android:width="128dp" +android:height="128dp"/> + + <viewport android:viewportWidth="512" + android:viewportHeight="512"/> + +<group> +<path + android:name="002b" + android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299" + android:stroke="#FF0000FF" + android:strokeWidth="4" + /> +</group> +</vector> diff --git a/tests/DynamicDrawableTest/res/values/strings.xml b/tests/DynamicDrawableTest/res/values/strings.xml new file mode 100644 index 0000000..64163c2 --- /dev/null +++ b/tests/DynamicDrawableTest/res/values/strings.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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. + 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> +</resources> diff --git a/tests/DynamicDrawableTest/res/values/styles.xml b/tests/DynamicDrawableTest/res/values/styles.xml new file mode 100644 index 0000000..460c0db --- /dev/null +++ b/tests/DynamicDrawableTest/res/values/styles.xml @@ -0,0 +1,16 @@ +<!-- Copyright (C) 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. + 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> +</resources> diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java new file mode 100644 index 0000000..1060d19 --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + +import android.app.Activity; +import android.graphics.drawable.VectorDrawable; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.GridLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorCheckbox extends Activity { + private static final String LOGCAT = "VectorDrawable1"; + int[] icon = { + R.drawable.vector_drawable01, + R.drawable.vector_drawable02, + R.drawable.vector_drawable03, + R.drawable.vector_drawable04, + R.drawable.vector_drawable05, + R.drawable.vector_drawable06, + R.drawable.vector_drawable07, + R.drawable.vector_drawable08, + R.drawable.vector_drawable09, + R.drawable.vector_drawable10, + R.drawable.vector_drawable11, + R.drawable.vector_drawable12, + R.drawable.vector_drawable13, + R.drawable.vector_drawable14, + R.drawable.vector_drawable15, + R.drawable.vector_drawable16, + R.drawable.vector_drawable17, + R.drawable.vector_drawable18, + R.drawable.vector_drawable19, + R.drawable.vector_drawable20 + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GridLayout container = new GridLayout(this); + container.setColumnCount(5); + container.setBackgroundColor(0xFF888888); + final Button []bArray = new Button[icon.length]; + + for (int i = 0; i < icon.length; i++) { + CheckBox checkBox = new CheckBox(this); + bArray[i] = checkBox; + checkBox.setWidth(200); + checkBox.setWidth(200); + checkBox.setButtonDrawable(icon[i]); + container.addView(checkBox); + } + setContentView(container); + } +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java new file mode 100644 index 0000000..0ae4b6d --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + +import android.app.Activity; +import android.graphics.drawable.VectorDrawable; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.GridLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorDrawable01 extends Activity implements View.OnClickListener { + private static final String LOGCAT = "VectorDrawable1"; + int[] icon = { + R.drawable.vector_drawable01, + R.drawable.vector_drawable02, + R.drawable.vector_drawable03, + R.drawable.vector_drawable04, + R.drawable.vector_drawable05, + R.drawable.vector_drawable06, + R.drawable.vector_drawable07, + R.drawable.vector_drawable08, + R.drawable.vector_drawable09, + R.drawable.vector_drawable10, + R.drawable.vector_drawable11, + R.drawable.vector_drawable12, + R.drawable.vector_drawable13, + R.drawable.vector_drawable14, + R.drawable.vector_drawable15, + R.drawable.vector_drawable16, + R.drawable.vector_drawable17, + R.drawable.vector_drawable18, + R.drawable.vector_drawable19, + R.drawable.vector_drawable20 + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + GridLayout container = new GridLayout(this); + container.setColumnCount(5); + container.setBackgroundColor(0xFF888888); + final Button []bArray = new Button[icon.length]; + + for (int i = 0; i < icon.length; i++) { + Button button = new Button(this); + bArray[i] = button; + button.setWidth(200); + button.setWidth(200); + button.setBackgroundResource(icon[i]); + container.addView(button); + button.setOnClickListener(this); + } + Button b = new Button(this); + b.setText("Run All"); + b.setOnClickListener(new View.OnClickListener(){ + + @Override + public void onClick(View v) { + for (int i = 0; i < bArray.length; i++) { + VectorDrawable d = (VectorDrawable) bArray[i].getBackground(); + d.start(); + } + }}); + container.addView(b); + setContentView(container); + + } + + @Override + public void onClick(View v) { + VectorDrawable d = (VectorDrawable) v.getBackground(); + d.start(); + } + +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java new file mode 100644 index 0000000..a00bc5e --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorDrawableDupPerf extends VectorDrawablePerformance { + { + icon = new int[]{ + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + R.drawable.vector_drawable04, + }; + } +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java new file mode 100644 index 0000000..9e8ea75 --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + +import android.app.Activity; +import android.content.res.Resources; +import android.graphics.drawable.VectorDrawable; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Button; +import android.widget.GridLayout; +import android.widget.ScrollView; +import java.text.DecimalFormat; + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorDrawablePerformance extends Activity implements View.OnClickListener { + private static final String LOGCAT = "VectorDrawable1"; + protected int[] icon = { + R.drawable.vector_drawable01, + R.drawable.vector_drawable02, + R.drawable.vector_drawable03, + R.drawable.vector_drawable04, + R.drawable.vector_drawable05, + R.drawable.vector_drawable06, + R.drawable.vector_drawable07, + R.drawable.vector_drawable08, + R.drawable.vector_drawable09, + R.drawable.vector_drawable10, + R.drawable.vector_drawable11, + R.drawable.vector_drawable12, + R.drawable.vector_drawable13, + R.drawable.vector_drawable14, + R.drawable.vector_drawable15, + R.drawable.vector_drawable16, + R.drawable.vector_drawable17, + R.drawable.vector_drawable18, + R.drawable.vector_drawable19, + R.drawable.vector_drawable20 + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ScrollView scrollView = new ScrollView(this); + GridLayout container = new GridLayout(this); + scrollView.addView(container); + container.setColumnCount(5); + Resources res = this.getResources(); + container.setBackgroundColor(0xFF888888); + VectorDrawable []d = new VectorDrawable[icon.length]; + long time = android.os.SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < icon.length; i++) { + d[i] = VectorDrawable.create(res,icon[i]); + } + time = android.os.SystemClock.elapsedRealtimeNanos()-time; + TextView t = new TextView(this); + DecimalFormat df = new DecimalFormat("#.##"); + t.setText("avgL=" + df.format(time / (icon.length * 1000000.)) + " ms"); + t.setBackgroundColor(0xFF000000); + container.addView(t); + time = android.os.SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < icon.length; i++) { + Button button = new Button(this); + button.setWidth(200); + button.setWidth(200); + button.setBackgroundResource(icon[i]); + container.addView(button); + button.setOnClickListener(this); + } + setContentView(scrollView); + time = android.os.SystemClock.elapsedRealtimeNanos()-time; + t = new TextView(this); + t.setText("avgS=" + df.format(time / (icon.length * 1000000.)) + " ms"); + t.setBackgroundColor(0xFF000000); + container.addView(t); + } + + @Override + public void onClick(View v) { + VectorDrawable d = (VectorDrawable) v.getBackground(); + d.start(); + } +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java new file mode 100644 index 0000000..9d3eded --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + +import android.app.Activity; +import android.content.res.Resources; +import android.graphics.drawable.VectorDrawable; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; +import android.widget.Button; +import android.widget.GridLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorDrawableStaticPerf extends VectorDrawablePerformance { + { + icon = new int[]{ + R.drawable.vector_icon_create, + R.drawable.vector_icon_delete, + R.drawable.vector_icon_heart, + R.drawable.vector_icon_schedule, + R.drawable.vector_icon_settings, + }; + } +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java new file mode 100644 index 0000000..704d3d7 --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 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. + * 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.test.dynamic; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.view.View; +import android.widget.ListView; +import android.widget.SimpleAdapter; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("UnusedDeclaration") +public class VectorDrawableTest extends android.app.ListActivity { + private static final String EXTRA_PATH = "com.android.test.dynamic.Path"; + private static final String CATEGORY_HWUI_TEST = "com.android.test.dynamic.TEST"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + String path = intent.getStringExtra("com.android.test.hwui.Path"); + + if (path == null) { + path = ""; + } + + setListAdapter(new SimpleAdapter(this, getData(path), + android.R.layout.simple_list_item_1, new String[] { "title" }, + new int[] { android.R.id.text1 })); + getListView().setTextFilterEnabled(true); + } + + protected List<Map<String, Object>> getData(String prefix) { + List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>(); + + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(CATEGORY_HWUI_TEST); + + PackageManager pm = getPackageManager(); + List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); + + if (null == list) + return myData; + + String[] prefixPath; + String prefixWithSlash = prefix; + + if (prefix.equals("")) { + prefixPath = null; + } else { + prefixPath = prefix.split("/"); + prefixWithSlash = prefix + "/"; + } + + int len = list.size(); + + Map<String, Boolean> entries = new HashMap<String, Boolean>(); + + for (int i = 0; i < len; i++) { + ResolveInfo info = list.get(i); + CharSequence labelSeq = info.loadLabel(pm); + String label = labelSeq != null + ? labelSeq.toString() + : info.activityInfo.name; + + if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) { + + String[] labelPath = label.split("/"); + + String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length]; + + if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) { + addItem(myData, nextLabel, activityIntent( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name)); + } else { + if (entries.get(nextLabel) == null) { + addItem(myData, nextLabel, browseIntent(prefix.equals("") ? + nextLabel : prefix + "/" + nextLabel)); + entries.put(nextLabel, true); + } + } + } + } + + Collections.sort(myData, sDisplayNameComparator); + + return myData; + } + + private final static Comparator<Map<String, Object>> sDisplayNameComparator = + new Comparator<Map<String, Object>>() { + private final Collator collator = Collator.getInstance(); + + public int compare(Map<String, Object> map1, Map<String, Object> map2) { + return collator.compare(map1.get("title"), map2.get("title")); + } + }; + + protected Intent activityIntent(String pkg, String componentName) { + Intent result = new Intent(); + result.setClassName(pkg, componentName); + return result; + } + + protected Intent browseIntent(String path) { + Intent result = new Intent(); + result.setClass(this, VectorDrawableTest.class); + result.putExtra(EXTRA_PATH, path); + return result; + } + + protected void addItem(List<Map<String, Object>> data, String name, Intent intent) { + Map<String, Object> temp = new HashMap<String, Object>(); + temp.put("title", name); + temp.put("intent", intent); + data.add(temp); + } + + @Override + @SuppressWarnings({ "unchecked", "UnusedParameters" }) + protected void onListItemClick(ListView l, View v, int position, long id) { + Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position); + + Intent intent = (Intent) map.get("intent"); + startActivity(intent); + } +} diff --git a/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java new file mode 100644 index 0000000..3430192 --- /dev/null +++ b/tests/DynamicDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 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. 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.test.dynamic; + + +@SuppressWarnings({"UnusedDeclaration"}) +public class VectorPathChecking extends VectorDrawablePerformance { + { + icon = new int[]{ + R.drawable.vector_test01, + R.drawable.vector_test02 + }; + } +} diff --git a/tests/GridLayoutTest/src/com/android/test/layout/AbstractLayoutTest.java b/tests/GridLayoutTest/src/com/android/test/layout/AbstractLayoutTest.java index 4d3a843..196a5c1 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/AbstractLayoutTest.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/AbstractLayoutTest.java @@ -24,7 +24,13 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import static android.view.Gravity.*; +import static android.view.Gravity.BOTTOM; +import static android.view.Gravity.CENTER; +import static android.view.Gravity.FILL; +import static android.view.Gravity.LEFT; +import static android.view.Gravity.NO_GRAVITY; +import static android.view.Gravity.RIGHT; +import static android.view.Gravity.TOP; public abstract class AbstractLayoutTest extends Activity { diff --git a/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java b/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java index b1c4486..5559707 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/AlignmentTest.java @@ -20,15 +20,25 @@ import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.GridLayout; +import android.widget.GridLayout.Alignment; +import android.widget.GridLayout.LayoutParams; import android.widget.TextView; -import static android.widget.GridLayout.*; +import static android.widget.GridLayout.BASELINE; +import static android.widget.GridLayout.BOTTOM; +import static android.widget.GridLayout.CENTER; +import static android.widget.GridLayout.FILL; +import static android.widget.GridLayout.LEFT; +import static android.widget.GridLayout.RIGHT; +import static android.widget.GridLayout.TOP; +import static android.widget.GridLayout.spec; -public class AlignmentTest extends Activity { +public class AlignmentTest extends Activity { public static final String[] HORIZONTAL_NAMES = {"LEFT", "center", "east", "fill"}; public static final Alignment[] HORIZONTAL_ALIGNMENTS = {LEFT, CENTER, RIGHT, FILL}; diff --git a/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java b/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java index 4ce449a..8047c5f 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/GridLayoutTest.java @@ -21,7 +21,10 @@ import android.view.View; import android.view.ViewGroup; import android.widget.GridLayout; -import static android.widget.GridLayout.*; +import static android.widget.GridLayout.Spec; +import static android.widget.GridLayout.UNDEFINED; +import static android.widget.GridLayout.VERTICAL; +import static android.widget.GridLayout.spec; public class GridLayoutTest extends AbstractLayoutTest { public ViewGroup create(Context context) { diff --git a/tests/GridLayoutTest/src/com/android/test/layout/LinearLayoutTest.java b/tests/GridLayoutTest/src/com/android/test/layout/LinearLayoutTest.java index c7f4665..dc5b12c 100644 --- a/tests/GridLayoutTest/src/com/android/test/layout/LinearLayoutTest.java +++ b/tests/GridLayoutTest/src/com/android/test/layout/LinearLayoutTest.java @@ -20,9 +20,9 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; -import static android.widget.LinearLayout.*; -import static android.widget.LinearLayout.LayoutParams.*; +import static android.widget.LinearLayout.LayoutParams.WRAP_CONTENT; public class LinearLayoutTest extends AbstractLayoutTest { public ViewGroup create(Context context) { diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 1bb0db0..c8eefe0 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -706,6 +706,15 @@ </activity> <activity + android:name="ColorFiltersMutateActivity" + android:label="ColorFilters/Mutate Filters"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + + <activity android:name="LinesActivity" android:label="Draw/Lines"> <intent-filter> @@ -849,5 +858,23 @@ </intent-filter> </activity> + <activity + android:name="ProjectionActivity" + android:label="Reordering/Projection"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + + <activity + android:name="IsolationVolumeActivity" + android:label="Reordering/IsolationVolume"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/tests/HwAccelerationTest/res/layout/isolation.xml b/tests/HwAccelerationTest/res/layout/isolation.xml new file mode 100644 index 0000000..e66db19 --- /dev/null +++ b/tests/HwAccelerationTest/res/layout/isolation.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#f55"> + <!-- Left and right layouts are not isolated volumes, so the text views + will interleave since they share an isolated z volume--> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <LinearLayout + android:layout_width="0dp" + android:layout_height="200dp" + android:layout_weight="1" + android:orientation="vertical"> + <TextView style="@style/TopLeftReorderTextView"/> + <TextView style="@style/BottomLeftReorderTextView"/> + </LinearLayout> + <LinearLayout + android:layout_width="0dp" + android:layout_height="200dp" + android:layout_weight="1" + android:translationY="50dp" + android:orientation="vertical"> + <TextView style="@style/TopRightReorderTextView"/> + <TextView style="@style/BottomRightReorderTextView"/> + </LinearLayout> + </LinearLayout> + + <!-- Left and right volumes are isolated by default, so no interleaving will be seen. --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <LinearLayout + android:layout_width="0dp" + android:layout_height="200dp" + android:layout_weight="1" + android:orientation="vertical"> + <TextView style="@style/TopLeftReorderTextView"/> + <TextView style="@style/BottomLeftReorderTextView"/> + </LinearLayout> + <LinearLayout + android:layout_width="0dp" + android:layout_height="200dp" + android:layout_weight="1" + android:translationY="50dp" + android:orientation="vertical"> + <TextView style="@style/TopRightReorderTextView"/> + <TextView style="@style/BottomRightReorderTextView"/> + </LinearLayout> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/tests/HwAccelerationTest/res/layout/projection.xml b/tests/HwAccelerationTest/res/layout/projection.xml new file mode 100644 index 0000000..b6e4c5e --- /dev/null +++ b/tests/HwAccelerationTest/res/layout/projection.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:background="#66ff0000" + tools:context="com.example.projection.ProjectionActivity" + tools:ignore="MergeRootFrame"> + <TextView + android:layout_width="match_parent" + android:layout_height="100dp" + android:textSize="50sp" + android:text="TextView"/> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="100dp" + android:clipChildren="false"> + <view class="com.android.test.hwui.ProjectionActivity$ProjectedView" + android:id="@+id/projection" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + <TextView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:textSize="50sp" + android:text="TextView"/> + </FrameLayout> + + <TextView + android:layout_width="match_parent" + android:layout_height="100dp" + android:textSize="50sp" + android:text="TextView"/> +</LinearLayout>
\ No newline at end of file diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/HwAccelerationTest/res/values/styles.xml new file mode 100644 index 0000000..cde5d20 --- /dev/null +++ b/tests/HwAccelerationTest/res/values/styles.xml @@ -0,0 +1,34 @@ +<resources> + <style name="ReorderTextView" parent="@android:style/TextAppearance.Medium"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">100dp</item> + <item name="android:gravity">center</item> + </style> + <style name="LeftReorderTextView" parent="@style/ReorderTextView"> + <item name="android:translationX">20dp</item> + </style> + <style name="RightReorderTextView" parent="@style/ReorderTextView"> + <item name="android:translationX">-20dp</item> + </style> + + <style name="TopLeftReorderTextView" parent="@style/LeftReorderTextView"> + <item name="android:background">#666</item> + <item name="android:text">100</item> + <item name="android:translationZ">100dp</item> + </style> + <style name="BottomLeftReorderTextView" parent="@style/LeftReorderTextView"> + <item name="android:background">#bbb</item> + <item name="android:text">300</item> + <item name="android:translationZ">300dp</item> + </style> + <style name="TopRightReorderTextView" parent="@style/RightReorderTextView"> + <item name="android:background">#888</item> + <item name="android:text">200</item> + <item name="android:translationZ">200dp</item> + </style> + <style name="BottomRightReorderTextView" parent="@style/RightReorderTextView"> + <item name="android:background">#ccc</item> + <item name="android:text">400</item> + <item name="android:translationZ">400dp</item> + </style> +</resources> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java new file mode 100644 index 0000000..808b5d3 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 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.test.hwui; + +import android.animation.ArgbEvaluator; +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.LightingColorFilter; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.os.Bundle; +import android.view.View; + +@SuppressWarnings({"UnusedDeclaration"}) +public class ColorFiltersMutateActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final BitmapsView view = new BitmapsView(this); + setContentView(view); + } + + static class BitmapsView extends View { + private final Bitmap mBitmap1; + private final Bitmap mBitmap2; + private final Paint mColorMatrixPaint; + private final Paint mLightingPaint; + private final Paint mBlendPaint; + + private float mSaturation = 0.0f; + private int mLightAdd = 0; + private int mLightMul = 0; + private int mPorterDuffColor = 0; + + BitmapsView(Context c) { + super(c); + + mBitmap1 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1); + mBitmap2 = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset2); + + mColorMatrixPaint = new Paint(); + final ColorMatrix colorMatrix = new ColorMatrix(); + colorMatrix.setSaturation(0); + mColorMatrixPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); + + mLightingPaint = new Paint(); + mLightingPaint.setColorFilter(new LightingColorFilter(0, 0)); + + mBlendPaint = new Paint(); + mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER)); + + ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f); + sat.setDuration(1000); + sat.setRepeatCount(ObjectAnimator.INFINITE); + sat.setRepeatMode(ObjectAnimator.REVERSE); + sat.start(); + + ObjectAnimator light = ObjectAnimator.ofInt(this, "lightAdd", 0x00101030); + light.setEvaluator(new ArgbEvaluator()); + light.setDuration(1000); + light.setRepeatCount(ObjectAnimator.INFINITE); + light.setRepeatMode(ObjectAnimator.REVERSE); + light.start(); + + ObjectAnimator mult = ObjectAnimator.ofInt(this, "lightMul", 0x0060ffff); + mult.setEvaluator(new ArgbEvaluator()); + mult.setDuration(1000); + mult.setRepeatCount(ObjectAnimator.INFINITE); + mult.setRepeatMode(ObjectAnimator.REVERSE); + mult.start(); + + ObjectAnimator color = ObjectAnimator.ofInt(this, "porterDuffColor", 0x7f990040); + color.setEvaluator(new ArgbEvaluator()); + color.setDuration(1000); + color.setRepeatCount(ObjectAnimator.INFINITE); + color.setRepeatMode(ObjectAnimator.REVERSE); + color.start(); + } + + public int getPorterDuffColor() { + return mPorterDuffColor; + } + + public void setPorterDuffColor(int porterDuffColor) { + mPorterDuffColor = porterDuffColor; + final PorterDuffColorFilter filter = + (PorterDuffColorFilter) mBlendPaint.getColorFilter(); + filter.setColor(mPorterDuffColor); + invalidate(); + } + + public int getLightAdd() { + return mLightAdd; + } + + public void setLightAdd(int lightAdd) { + mLightAdd = lightAdd; + final LightingColorFilter filter = + (LightingColorFilter) mLightingPaint.getColorFilter(); + filter.setColorAdd(lightAdd); + invalidate(); + } + + public int getLightMul() { + return mLightAdd; + } + + public void setLightMul(int lightMul) { + mLightMul = lightMul; + final LightingColorFilter filter = + (LightingColorFilter) mLightingPaint.getColorFilter(); + filter.setColorMultiply(lightMul); + invalidate(); + } + + public void setSaturation(float saturation) { + mSaturation = saturation; + final ColorMatrixColorFilter filter = + (ColorMatrixColorFilter) mColorMatrixPaint.getColorFilter(); + final ColorMatrix m = filter.getColorMatrix(); + m.setSaturation(saturation); + filter.setColorMatrix(m); + invalidate(); + } + + public float getSaturation() { + return mSaturation; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.drawARGB(255, 255, 255, 255); + + canvas.save(); + canvas.translate(120.0f, 50.0f); + canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mColorMatrixPaint); + + canvas.translate(0.0f, 50.0f + mBitmap1.getHeight()); + canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mLightingPaint); + + canvas.translate(0.0f, 50.0f + mBitmap1.getHeight()); + canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBlendPaint); + canvas.restore(); + + canvas.save(); + canvas.translate(120.0f + mBitmap1.getWidth() + 120.0f, 50.0f); + canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mColorMatrixPaint); + + canvas.translate(0.0f, 50.0f + mBitmap2.getHeight()); + canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mLightingPaint); + + canvas.translate(0.0f, 50.0f + mBitmap2.getHeight()); + canvas.drawBitmap(mBitmap2, 0.0f, 0.0f, mBlendPaint); + canvas.restore(); + } + } +} diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java new file mode 100644 index 0000000..d5c93f2 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java @@ -0,0 +1,12 @@ +package com.android.test.hwui; + +import android.os.Bundle; +import android.app.Activity; + +public class IsolationVolumeActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.isolation); + } +} diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java new file mode 100644 index 0000000..5ba3ad9 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java @@ -0,0 +1,83 @@ +package com.android.test.hwui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.os.Bundle; + +import android.app.Activity; +import android.util.AttributeSet; +import android.view.RenderNode; +import android.view.View; +import android.widget.LinearLayout; + +public class ProjectionActivity extends Activity { + /** + * The content from this view should be projected in between the background of the + * ProjecteeLayout and its children, unclipped. + * + * This view doesn't clip to its bounds (because its parent has clipChildren=false) so that + * when it is projected onto the ProjecteeLayout, it draws outside its view bounds. + */ + public static class ProjectedView extends View { + private final Paint mPaint = new Paint(); + private final RectF mRectF = new RectF(); + + public ProjectedView(Context context) { + this(context, null); + } + + public ProjectedView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ProjectedView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + setOnClickListener(new OnClickListener() { + boolean toggle = false; + @Override + public void onClick(View v) { + toggle = !toggle; + setProject(toggle); + } + }); + } + + private void setProject(boolean value) { + RenderNode displayList = getDisplayList(); + if (displayList != null) { + displayList.setProjectBackwards(value); + } + // NOTE: we can't invalidate ProjectedView for the redraw because: + // 1) the view won't preserve displayList properties that it doesn't know about + // 2) the damage rect won't be big enough + + // instead, twiddle properties on the container, so that enough area of the screen is + // redrawn without rerecording any DisplayLists. + container.setTranslationX(100f); + container.setTranslationX(0.0f); + } + + @Override + protected void onDraw(Canvas canvas) { + // TODO: set projection flag + final int w = getWidth(); + final int h = getHeight(); + mRectF.set(0, -h, w, 2 * h); + mPaint.setAntiAlias(true); + mPaint.setColor(0x5f00ff00); + canvas.drawOval(mRectF, mPaint); + } + } + + static View container; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.projection); + container = findViewById(R.id.container); + } +} diff --git a/tests/IdleServiceTest/Android.mk b/tests/IdleServiceTest/Android.mk new file mode 100644 index 0000000..a7879c5 --- /dev/null +++ b/tests/IdleServiceTest/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := IdleServiceTest +LOCAL_CERTIFICATE := platform + +LOCAL_PROGUARD_ENABLED := disabled + +include $(BUILD_PACKAGE) diff --git a/tests/IdleServiceTest/AndroidManifest.xml b/tests/IdleServiceTest/AndroidManifest.xml new file mode 100644 index 0000000..16d2324 --- /dev/null +++ b/tests/IdleServiceTest/AndroidManifest.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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. + 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.idleservicetest"> + + <application> + <service android:name="TestService" + android:exported="true" + android:enabled="true" + android:permission="android.permission.BIND_IDLE_SERVICE" > + <intent-filter> + <action android:name="android.service.idle.IdleService" /> + </intent-filter> + </service> + + <service android:name="CrashingTestService" + android:exported="true" + android:enabled="true" + android:permission="android.permission.BIND_IDLE_SERVICE" > + <intent-filter> + <action android:name="android.service.idle.IdleService" /> + </intent-filter> + </service> + + <service android:name="TimeoutTestService" + android:exported="true" + android:enabled="true" + android:permission="android.permission.BIND_IDLE_SERVICE" > + <intent-filter> + <action android:name="android.service.idle.IdleService" /> + </intent-filter> + </service> + + <!-- UnpermissionedTestService should never run because it does + not require the necessary permission in its <service> block --> + <service android:name="UnpermissionedTestService" + android:exported="true" + android:enabled="true" > + <intent-filter> + <action android:name="android.service.idle.IdleService" /> + </intent-filter> + </service> + + </application> +</manifest> diff --git a/tests/IdleServiceTest/src/com/android/idleservicetest/CrashingTestService.java b/tests/IdleServiceTest/src/com/android/idleservicetest/CrashingTestService.java new file mode 100644 index 0000000..022ebcf --- /dev/null +++ b/tests/IdleServiceTest/src/com/android/idleservicetest/CrashingTestService.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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. + * 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.idleservicetest; + +import android.app.maintenance.IdleService; +import android.os.Handler; +import android.util.Log; + +public class CrashingTestService extends IdleService { + static final String TAG = "CrashingTestService"; + + String mNull = null; + + @Override + public boolean onIdleStart() { + Log.i(TAG, "Idle maintenance: onIdleStart()"); + + Handler h = new Handler(); + Runnable r = new Runnable() { + @Override + public void run() { + Log.i(TAG, "Explicitly crashing"); + if (mNull.equals("")) { + Log.i(TAG, "won't happen"); + } + } + }; + Log.i(TAG, "Posting explicit crash in 15 seconds"); + h.postDelayed(r, 15 * 1000); + return true; + } + + @Override + public void onIdleStop() { + Log.i(TAG, "Idle maintenance: onIdleStop()"); + } + +} diff --git a/tests/IdleServiceTest/src/com/android/idleservicetest/TestService.java b/tests/IdleServiceTest/src/com/android/idleservicetest/TestService.java new file mode 100644 index 0000000..7e9805f --- /dev/null +++ b/tests/IdleServiceTest/src/com/android/idleservicetest/TestService.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 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. + * 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.idleservicetest; + +import android.app.maintenance.IdleService; +import android.os.Handler; +import android.util.Log; + +public class TestService extends IdleService { + static final String TAG = "TestService"; + + @Override + public boolean onIdleStart() { + Log.i(TAG, "Idle maintenance: onIdleStart()"); + + Handler h = new Handler(); + Runnable r = new Runnable() { + @Override + public void run() { + Log.i(TAG, "Explicitly finishing idle"); + finishIdle(); + } + }; + Log.i(TAG, "Posting explicit finish in 15 seconds"); + h.postDelayed(r, 15 * 1000); + return true; + } + + @Override + public void onIdleStop() { + Log.i(TAG, "Idle maintenance: onIdleStop()"); + } + +} diff --git a/tests/IdleServiceTest/src/com/android/idleservicetest/TimeoutTestService.java b/tests/IdleServiceTest/src/com/android/idleservicetest/TimeoutTestService.java new file mode 100644 index 0000000..b2ba21b --- /dev/null +++ b/tests/IdleServiceTest/src/com/android/idleservicetest/TimeoutTestService.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 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. + * 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.idleservicetest; + +import android.app.maintenance.IdleService; +import android.util.Log; + +public class TimeoutTestService extends IdleService { + private static final String TAG = "TimeoutTestService"; + + @Override + public boolean onIdleStart() { + Log.i(TAG, "onIdleStart() but anticipating time-slice timeout"); + return true; + } + + @Override + public void onIdleStop() { + Log.i(TAG, "onIdleStop() so we're done"); + } + +} diff --git a/tests/IdleServiceTest/src/com/android/idleservicetest/UnpermissionedTestService.java b/tests/IdleServiceTest/src/com/android/idleservicetest/UnpermissionedTestService.java new file mode 100644 index 0000000..b9fe32b --- /dev/null +++ b/tests/IdleServiceTest/src/com/android/idleservicetest/UnpermissionedTestService.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 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. + * 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.idleservicetest; + +import android.app.maintenance.IdleService; +import android.util.Log; + +// Should never be invoked because its manifest declaration does not +// require the necessary permission. +public class UnpermissionedTestService extends IdleService { + private static final String TAG = "UnpermissionedTestService"; + + @Override + public boolean onIdleStart() { + Log.e(TAG, "onIdleStart() for this service should never be called!"); + return false; + } + + @Override + public void onIdleStop() { + Log.e(TAG, "onIdleStop() for this service should never be called!"); + } + +} diff --git a/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java b/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java index 25ac2f0..299e6bb 100644 --- a/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java +++ b/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java @@ -81,11 +81,11 @@ public class InputTypeActivity extends Activity { /* Uri Edit Text */ mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_URI, - R.string.uri_edit_text_label)); + R.string.uri_edit_text_label)); /* Email Address Edit Text */ mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS, - R.string.email_address_edit_text_label)); + R.string.email_address_edit_text_label)); /* Email Subject Text */ mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT, @@ -142,7 +142,7 @@ public class InputTypeActivity extends Activity { private View buildEntryView(int inputType, int label) { - View view = mInflater.inflate(R.layout.sample_edit_text, mParent, false); + View view = mInflater.inflate(R.layout.sample_edit_text, mParent, false); EditText editText = (EditText) view.findViewById(R.id.data); editText.setInputType(inputType); diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java index a1c5fd2..2db11c5 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java @@ -24,26 +24,26 @@ import com.android.imftest.R; public class BigEditTextActivityNonScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityNonScrollablePanScan> { - public final String TAG = "BigEditTextActivityNonScrollablePanScanTests"; - + public final String TAG = "BigEditTextActivityNonScrollablePanScanTests"; + public BigEditTextActivityNonScrollablePanScanTests() { super(BigEditTextActivityNonScrollablePanScan.class); } - - @LargeTest - public void testAppAdjustmentPanScan() { - // Give the IME 2 seconds to appear. - pause(2000); + + @LargeTest + public void testAppAdjustmentPanScan() { + // Give the IME 2 seconds to appear. + pause(2000); + + View rootView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getRootView(); + View servedView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getDefaultFocusedView(); + + assertNotNull(rootView); + assertNotNull(servedView); + + destructiveCheckImeInitialState(rootView, servedView); - View rootView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getRootView(); - View servedView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getDefaultFocusedView(); - - assertNotNull(rootView); - assertNotNull(servedView); - - destructiveCheckImeInitialState(rootView, servedView); - verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java index 2e0b0eb..1050794 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java @@ -24,14 +24,14 @@ import com.android.imftest.R; public class BigEditTextActivityNonScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityNonScrollableResize> { - public final String TAG = "BigEditTextActivityNonScrollableResizeTests"; - + public final String TAG = "BigEditTextActivityNonScrollableResizeTests"; + public BigEditTextActivityNonScrollableResizeTests() { super(BigEditTextActivityNonScrollableResize.class); } - - @LargeTest - public void testAppAdjustmentPanScan() { // Give the IME 2 seconds to appear. + + @LargeTest + public void testAppAdjustmentPanScan() { // Give the IME 2 seconds to appear. pause(2000); View rootView = ((BigEditTextActivityNonScrollableResize) mTargetActivity).getRootView(); @@ -43,6 +43,6 @@ public class BigEditTextActivityNonScrollableResizeTests extends ImfBaseTestCase destructiveCheckImeInitialState(rootView, servedView); verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java index d3eefb5..1e848b0 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java @@ -24,14 +24,14 @@ import com.android.imftest.R; public class BigEditTextActivityScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityScrollablePanScan> { - public final String TAG = "BigEditTextActivityScrollablePanScanTests"; - + public final String TAG = "BigEditTextActivityScrollablePanScanTests"; + public BigEditTextActivityScrollablePanScanTests() { super(BigEditTextActivityScrollablePanScan.class); } - - @LargeTest - public void testAppAdjustmentPanScan() { // Give the IME 2 seconds to appear. + + @LargeTest + public void testAppAdjustmentPanScan() { // Give the IME 2 seconds to appear. pause(2000); View rootView = ((BigEditTextActivityScrollablePanScan) mTargetActivity).getRootView(); @@ -43,6 +43,6 @@ public class BigEditTextActivityScrollablePanScanTests extends ImfBaseTestCase<B destructiveCheckImeInitialState(rootView, servedView); verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java index 5c40e6d..de607d6 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java @@ -24,15 +24,15 @@ import com.android.imftest.R; public class BigEditTextActivityScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityScrollableResize> { - public final String TAG = "BigEditTextActivityScrollableResizeTests"; - + public final String TAG = "BigEditTextActivityScrollableResizeTests"; + public BigEditTextActivityScrollableResizeTests() { super(BigEditTextActivityScrollableResize.class); } - - @LargeTest - public void testAppAdjustmentPanScan() { - // Give the IME 2 seconds to appear. + + @LargeTest + public void testAppAdjustmentPanScan() { + // Give the IME 2 seconds to appear. pause(2000); View rootView = ((BigEditTextActivityScrollableResize) mTargetActivity).getRootView(); @@ -44,6 +44,6 @@ public class BigEditTextActivityScrollableResizeTests extends ImfBaseTestCase<Bi destructiveCheckImeInitialState(rootView, servedView); verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java index 9a93133..c521905 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java @@ -24,14 +24,14 @@ import com.android.imftest.R; public class BottomEditTextActivityPanScanTests extends ImfBaseTestCase<BottomEditTextActivityPanScan> { - public final String TAG = "BottomEditTextActivityPanScanTests"; - + public final String TAG = "BottomEditTextActivityPanScanTests"; + public BottomEditTextActivityPanScanTests() { super(BottomEditTextActivityPanScan.class); } - - @LargeTest - public void testAppAdjustmentPanScan() { + + @LargeTest + public void testAppAdjustmentPanScan() { // Give the IME 2 seconds to appear. pause(2000); @@ -44,6 +44,6 @@ public class BottomEditTextActivityPanScanTests extends ImfBaseTestCase<BottomEd destructiveCheckImeInitialState(rootView, servedView); verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java index ae900c3..f6f97b5 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java @@ -23,8 +23,8 @@ import android.widget.Button; public class ButtonActivityTest extends ImfBaseTestCase<ButtonActivity> { - final public String TAG = "ButtonActivityTest"; - + final public String TAG = "ButtonActivityTest"; + public ButtonActivityTest() { super(ButtonActivity.class); } diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java index ed5b0c9..6147d3c 100644 --- a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java +++ b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java @@ -22,21 +22,21 @@ import android.view.View; public class OneEditTextActivityNotSelectedTests extends ImfBaseTestCase<OneEditTextActivityNotSelected> { - public final String TAG = "OneEditTextActivityNotSelectedTests"; - + public final String TAG = "OneEditTextActivityNotSelectedTests"; + public OneEditTextActivityNotSelectedTests() { super(OneEditTextActivityNotSelected.class); } - @LargeTest - public void testSoftKeyboardNoAutoPop() { - - // Give the IME 2 seconds to appear. - pause(2000); - - assertFalse(mImm.isAcceptingText()); - - View rootView = ((OneEditTextActivityNotSelected) mTargetActivity).getRootView(); + @LargeTest + public void testSoftKeyboardNoAutoPop() { + + // Give the IME 2 seconds to appear. + pause(2000); + + assertFalse(mImm.isAcceptingText()); + + View rootView = ((OneEditTextActivityNotSelected) mTargetActivity).getRootView(); View servedView = ((OneEditTextActivityNotSelected) mTargetActivity).getDefaultFocusedView(); assertNotNull(rootView); @@ -45,6 +45,6 @@ public class OneEditTextActivityNotSelectedTests extends ImfBaseTestCase<OneEdit destructiveCheckImeInitialState(rootView, servedView); verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight()); - } - + } + } diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk new file mode 100644 index 0000000..93b9c9a --- /dev/null +++ b/tests/OneMedia/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-subdir-java-files) \ + $(call all-Iaidl-files-under, src) + +LOCAL_PACKAGE_NAME := OneMedia +LOCAL_CERTIFICATE := platform + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v7-appcompat \ + android-support-v7-mediarouter + +LOCAL_PROGUARD_ENABLED := disabled + +include $(BUILD_PACKAGE) diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml new file mode 100644 index 0000000..7d6ba1d --- /dev/null +++ b/tests/OneMedia/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.onemedia" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk android:minSdkVersion="19"/> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> + + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name="com.android.onemedia.OnePlayerActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <service + android:name="com.android.onemedia.OnePlayerService" + android:exported="false" + android:process="com.android.onemedia.service" /> + </application> + +</manifest> diff --git a/tests/OneMedia/res/drawable-hdpi/ic_launcher.png b/tests/OneMedia/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..288b665 --- /dev/null +++ b/tests/OneMedia/res/drawable-hdpi/ic_launcher.png diff --git a/tests/OneMedia/res/drawable-mdpi/ic_launcher.png b/tests/OneMedia/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..6ae570b --- /dev/null +++ b/tests/OneMedia/res/drawable-mdpi/ic_launcher.png diff --git a/tests/OneMedia/res/drawable-xhdpi/ic_launcher.png b/tests/OneMedia/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..d4fb7cd --- /dev/null +++ b/tests/OneMedia/res/drawable-xhdpi/ic_launcher.png diff --git a/tests/OneMedia/res/drawable-xxhdpi/ic_launcher.png b/tests/OneMedia/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..85a6081 --- /dev/null +++ b/tests/OneMedia/res/drawable-xxhdpi/ic_launcher.png diff --git a/tests/OneMedia/res/layout/activity_main.xml b/tests/OneMedia/res/layout/activity_main.xml new file mode 100644 index 0000000..168c9b8 --- /dev/null +++ b/tests/OneMedia/res/layout/activity_main.xml @@ -0,0 +1,16 @@ +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context=".MainActivity" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/hello_world" /> + +</RelativeLayout> diff --git a/tests/OneMedia/res/layout/activity_one_player.xml b/tests/OneMedia/res/layout/activity_one_player.xml new file mode 100644 index 0000000..4208355 --- /dev/null +++ b/tests/OneMedia/res/layout/activity_one_player.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2014 Google Inc. All Rights Reserved. --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_horizontal" + android:orientation="vertical"> + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:text="@string/app_name" + style="@style/Title" /> + <EditText + android:id="@+id/content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textUri" + android:hint="@string/media_content_hint" + android:gravity="center" + android:textSize="24sp" /> + <EditText + android:id="@+id/next_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textNoSuggestions" + android:hint="@string/media_next_hint" + android:gravity="center" + android:textSize="24sp" /> + <CheckBox + android:id="@+id/has_video" + android:layout_marginRight="8dip" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/has_video" /> + <LinearLayout + android:id="@+id/controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" > + <Button + android:id="@+id/start_button" + style="@style/BottomBarButton" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/start_button" /> + <Button + android:id="@+id/play_button" + style="@style/BottomBarButton" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/play_button" /> + </LinearLayout> + <TextView + android:id="@+id/status" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + +</LinearLayout> diff --git a/tests/OneMedia/res/menu/main.xml b/tests/OneMedia/res/menu/main.xml new file mode 100644 index 0000000..c002028 --- /dev/null +++ b/tests/OneMedia/res/menu/main.xml @@ -0,0 +1,9 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" > + + <item + android:id="@+id/action_settings" + android:orderInCategory="100" + android:showAsAction="never" + android:title="@string/action_settings"/> + +</menu> diff --git a/tests/OneMedia/res/values/colors.xml b/tests/OneMedia/res/values/colors.xml new file mode 100644 index 0000000..9b9dc2a --- /dev/null +++ b/tests/OneMedia/res/values/colors.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2014 Google Inc. + * + * 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> + <color name="title_color">#33B5E5</color> +</resources> diff --git a/tests/OneMedia/res/values/dimens.xml b/tests/OneMedia/res/values/dimens.xml new file mode 100644 index 0000000..562edef --- /dev/null +++ b/tests/OneMedia/res/values/dimens.xml @@ -0,0 +1,9 @@ +<resources> + + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> + <dimen name="title_size">22sp</dimen> + <dimen name="small_size">11sp</dimen> + +</resources> diff --git a/tests/OneMedia/res/values/strings.xml b/tests/OneMedia/res/values/strings.xml new file mode 100644 index 0000000..1b0cebb --- /dev/null +++ b/tests/OneMedia/res/values/strings.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name">OneMedia</string> + <string name="action_settings">Settings</string> + <string name="hello_world">Test app for trying out new media components</string> + + <string name="start_button">Start</string> + <string name="play_button">Play</string> + <string name="media_content_hint">Content</string> + <string name="media_next_hint">Next content</string> + <string name="has_video">Is video</string> + <string name="has_duration">Has duration</string> + +</resources> diff --git a/tests/OneMedia/res/values/styles.xml b/tests/OneMedia/res/values/styles.xml new file mode 100644 index 0000000..60f3139 --- /dev/null +++ b/tests/OneMedia/res/values/styles.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- + Base application theme, dependent on API level. This theme is replaced + by AppBaseTheme from res/values-vXX/styles.xml on newer devices. + --> + <style name="AppBaseTheme" parent="android:Theme.Light"> + <!-- + Theme customizations available in newer API levels can go in + res/values-vXX/styles.xml, while customizations related to + backward-compatibility can go here. + --> + </style> + + <!-- Application theme. --> + <style name="AppTheme" parent="AppBaseTheme"> + <!-- All customizations that are NOT specific to a particular API-level can go here. --> + </style> + + <style name="Title"> + <item name="android:textSize">@dimen/title_size</item> + <item name="android:textColor">@color/title_color</item> + <item name="android:clickable">false</item> + <item name="android:longClickable">false</item> + </style> + + <style name="Text"> + <item name="android:textSize">@dimen/small_size</item> + <item name="android:textColor">@color/title_color</item> + <item name="android:clickable">false</item> + <item name="android:longClickable">false</item> + </style> + + <style name="BottomBarButton"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">match_parent</item> + <item name="android:paddingTop">0dip</item> + <item name="android:paddingLeft">0dip</item> + <item name="android:paddingRight">0dip</item> + <item name="android:paddingBottom">0dip</item> + <item name="android:textSize">12sp</item> + <item name="android:textStyle">bold</item> + </style> +</resources> diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl new file mode 100644 index 0000000..2b14384 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl @@ -0,0 +1,22 @@ +/* Copyright (C) 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. + * 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.onemedia; + +import android.media.session.MediaSessionToken; + +interface IPlayerCallback { + void onSessionChanged(in MediaSessionToken session); +}
\ No newline at end of file diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl new file mode 100644 index 0000000..efdbe9a --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl @@ -0,0 +1,29 @@ +/* Copyright (C) 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. + * 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.onemedia; + +import android.media.session.MediaSessionToken; +import android.os.Bundle; + +import com.android.onemedia.IPlayerCallback; +import com.android.onemedia.playback.IRequestCallback; + +interface IPlayerService { + MediaSessionToken getSessionToken(); + void registerCallback(in IPlayerCallback cb); + void unregisterCallback(in IPlayerCallback cb); + void sendRequest(String action, in Bundle params, in IRequestCallback cb); +}
\ No newline at end of file diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java new file mode 100644 index 0000000..3114ca9 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 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. + * 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.onemedia; + + +import android.app.Activity; +import android.media.session.MediaMetadata; +import android.media.session.PlaybackState; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.TextView; + +import com.android.onemedia.playback.Renderer; + +public class OnePlayerActivity extends Activity { + private static final String TAG = "OnePlayerActivity"; + + protected PlayerController mPlayer; + + private Button mStartButton; + private Button mPlayButton; + private TextView mStatusView; + + private EditText mContentText; + private EditText mNextContentText; + private CheckBox mHasVideo; + + private int mPlaybackState; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_one_player); + mPlayer = new PlayerController(this, OnePlayerService.getServiceIntent(this)); + + + mStartButton = (Button) findViewById(R.id.start_button); + mPlayButton = (Button) findViewById(R.id.play_button); + mStatusView = (TextView) findViewById(R.id.status); + mContentText = (EditText) findViewById(R.id.content); + mNextContentText = (EditText) findViewById(R.id.next_content); + mHasVideo = (CheckBox) findViewById(R.id.has_video); + + mStartButton.setOnClickListener(mButtonListener); + mPlayButton.setOnClickListener(mButtonListener); + + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + @Override + public void onResume() { + super.onResume(); + mPlayer.onResume(); + mPlayer.setListener(mListener); + } + + @Override + public void onPause() { + mPlayer.setListener(null); + mPlayer.onPause(); + super.onPause(); + } + + private void setControlsEnabled(boolean enabled) { + mStartButton.setEnabled(enabled); + mPlayButton.setEnabled(enabled); + } + + private View.OnClickListener mButtonListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.play_button: + Log.d(TAG, "Play button pressed, in state " + mPlaybackState); + if (mPlaybackState == PlaybackState.PLAYSTATE_PAUSED + || mPlaybackState == PlaybackState.PLAYSTATE_STOPPED) { + mPlayer.play(); + } else if (mPlaybackState == PlaybackState.PLAYSTATE_PLAYING) { + mPlayer.pause(); + } + break; + case R.id.start_button: + Log.d(TAG, "Start button pressed, in state " + mPlaybackState); + mPlayer.setContent(mContentText.getText().toString()); + break; + } + + } + }; + + private PlayerController.Listener mListener = new PlayerController.Listener() { + @Override + public void onPlaybackStateChange(PlaybackState state) { + mPlaybackState = state.getState(); + boolean enablePlay = false; + StringBuilder statusBuilder = new StringBuilder(); + switch (mPlaybackState) { + case PlaybackState.PLAYSTATE_PLAYING: + statusBuilder.append("playing"); + mPlayButton.setText("Pause"); + enablePlay = true; + break; + case PlaybackState.PLAYSTATE_PAUSED: + statusBuilder.append("paused"); + mPlayButton.setText("Play"); + enablePlay = true; + break; + case PlaybackState.PLAYSTATE_STOPPED: + statusBuilder.append("ended"); + mPlayButton.setText("Play"); + enablePlay = true; + break; + case PlaybackState.PLAYSTATE_ERROR: + statusBuilder.append("error: ").append(state.getErrorMessage()); + break; + case PlaybackState.PLAYSTATE_BUFFERING: + statusBuilder.append("buffering"); + break; + case PlaybackState.PLAYSTATE_NONE: + statusBuilder.append("none"); + break; + default: + statusBuilder.append(mPlaybackState); + } + statusBuilder.append(" -- At position: ").append(state.getPosition()); + mStatusView.setText(statusBuilder.toString()); + mPlayButton.setEnabled(enablePlay); + } + + @Override + public void onConnectionStateChange(int state) { + if (state == PlayerController.STATE_DISCONNECTED) { + setControlsEnabled(false); + } else if (state == PlayerController.STATE_CONNECTED) { + setControlsEnabled(true); + } + } + + @Override + public void onMetadataChange(MediaMetadata metadata) { + Log.d(TAG, "Metadata update! Title: " + metadata); + } + }; +} diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java new file mode 100644 index 0000000..573f7ff --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerService.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 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. + * 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.onemedia; + +import android.content.Context; +import android.content.Intent; + +import java.util.ArrayList; + +public class OnePlayerService extends PlayerService { + private static final String TAG = "OnePlayerService"; + + public static Intent getServiceIntent(Context context) { + return new Intent(context, OnePlayerService.class).setPackage( + OnePlayerService.class.getPackage().getName()); + } + + @Override + protected Intent onCreateServiceIntent() { + return getServiceIntent(this); + } + + @Override + protected ArrayList<String> getAllowedPackages() { + ArrayList<String> allowedPackages = new ArrayList<String>(); + allowedPackages.add("com.android.onemedia"); + return allowedPackages; + } +} diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java new file mode 100644 index 0000000..e831ec6 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java @@ -0,0 +1,209 @@ + +/* + * Copyright (C) 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. + * 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.onemedia; + +import android.media.session.MediaController; +import android.media.session.MediaMetadata; +import android.media.session.MediaSessionManager; +import android.media.session.PlaybackState; +import android.media.session.TransportController; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.util.Log; + +import com.android.onemedia.playback.RequestUtils; + +public class PlayerController { + private static final String TAG = "PlayerController"; + + public static final int STATE_DISCONNECTED = 0; + public static final int STATE_CONNECTED = 1; + + protected MediaController mController; + protected IPlayerService mBinder; + protected TransportController mTransportControls; + + private final Intent mServiceIntent; + private Context mContext; + private Listener mListener; + private TransportListener mTransportListener = new TransportListener(); + private SessionCallback mControllerCb; + private MediaSessionManager mManager; + private Handler mHandler = new Handler(); + + private boolean mResumed; + + public PlayerController(Context context, Intent serviceIntent) { + mContext = context; + if (serviceIntent == null) { + mServiceIntent = new Intent(mContext, PlayerService.class); + } else { + mServiceIntent = serviceIntent; + } + mControllerCb = new SessionCallback(); + mManager = (MediaSessionManager) context + .getSystemService(Context.MEDIA_SESSION_SERVICE); + + mResumed = false; + } + + public void setListener(Listener listener) { + mListener = listener; + Log.d(TAG, "Listener set to " + listener + " session is " + mController); + if (mListener != null) { + mHandler = new Handler(); + mListener.onConnectionStateChange( + mController == null ? STATE_DISCONNECTED : STATE_CONNECTED); + } + } + + public void onResume() { + mResumed = true; + Log.d(TAG, "onResume. Binding to service with intent " + mServiceIntent.toString()); + bindToService(); + } + + public void onPause() { + mResumed = false; + Log.d(TAG, "onPause, unbinding from service"); + unbindFromService(); + } + + public void play() { + if (mTransportControls != null) { + mTransportControls.play(); + } + } + + public void pause() { + if (mTransportControls != null) { + mTransportControls.pause(); + } + } + + public void setContent(String source) { + RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder(); + bob.setSource(source); + try { + mBinder.sendRequest(RequestUtils.ACTION_SET_CONTENT, bob.build(), null); + } catch (RemoteException e) { + Log.d(TAG, "setContent failed, service may have died.", e); + } + } + + public void setNextContent(String source) { + RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder(); + bob.setSource(source); + try { + mBinder.sendRequest(RequestUtils.ACTION_SET_NEXT_CONTENT, bob.build(), null); + } catch (RemoteException e) { + Log.d(TAG, "setNexctContent failed, service may have died.", e); + } + } + + private void unbindFromService() { + mContext.unbindService(mServiceConnection); + } + + private void bindToService() { + mContext.bindService(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + } + + private ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceDisconnected(ComponentName name) { + if (mController != null) { + mController.removeCallback(mControllerCb); + } + mBinder = null; + mController = null; + mTransportControls = null; + Log.d(TAG, "Disconnected from PlayerService"); + + if (mListener != null) { + mListener.onConnectionStateChange(STATE_DISCONNECTED); + } + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + mBinder = IPlayerService.Stub.asInterface(service); + Log.d(TAG, "service is " + service + " binder is " + mBinder); + try { + mController = MediaController.fromToken(mBinder.getSessionToken()); + } catch (RemoteException e) { + Log.e(TAG, "Error getting session", e); + return; + } + mController.addCallback(mControllerCb, mHandler); + mTransportControls = mController.getTransportController(); + if (mTransportControls != null) { + mTransportControls.addStateListener(mTransportListener); + } + Log.d(TAG, "Ready to use PlayerService"); + + if (mListener != null) { + mListener.onConnectionStateChange(STATE_CONNECTED); + if (mTransportControls != null) { + mListener.onPlaybackStateChange(mTransportControls.getPlaybackState()); + } + } + } + }; + + private class SessionCallback extends MediaController.Callback { + @Override + public void onRouteChanged(Bundle route) { + // TODO + } + } + + private class TransportListener extends TransportController.TransportStateListener { + @Override + public void onPlaybackStateChanged(PlaybackState state) { + if (state == null) { + return; + } + Log.d(TAG, "Received playback state change to state " + state.getState()); + if (mListener != null) { + mListener.onPlaybackStateChange(state); + } + } + + @Override + public void onMetadataChanged(MediaMetadata metadata) { + if (metadata == null) { + return; + } + Log.d(TAG, "Received metadata change, title is " + + metadata.getString(MediaMetadata.METADATA_KEY_TITLE)); + } + } + + public interface Listener { + public void onPlaybackStateChange(PlaybackState state); + public void onMetadataChange(MediaMetadata metadata); + public void onConnectionStateChange(int state); + } + +} diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java new file mode 100644 index 0000000..0ad6dd1 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 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. + * 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.onemedia; + +import android.app.Service; +import android.content.Intent; +import android.media.session.MediaSessionToken; +import android.media.session.PlaybackState; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.android.onemedia.playback.IRequestCallback; +import com.android.onemedia.playback.RequestUtils; + +import java.util.ArrayList; + +public class PlayerService extends Service { + private static final String TAG = "PlayerService"; + + private PlayerBinder mBinder; + private PlayerSession mSession; + private Intent mIntent; + private boolean mStarted = false; + + private ArrayList<IPlayerCallback> mCbs = new ArrayList<IPlayerCallback>(); + + @Override + public void onCreate() { + Log.d(TAG, "onCreate"); + mIntent = onCreateServiceIntent(); + if (mSession == null) { + mSession = onCreatePlayerController(); + mSession.createSession(); + mSession.setListener(mPlayerListener); + } + } + + @Override + public IBinder onBind(Intent intent) { + if (mBinder == null) { + mBinder = new PlayerBinder(); + } + return mBinder; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(TAG, "onStartCommand"); + return START_STICKY; + } + + @Override + public void onDestroy() { + Log.d(TAG, "onDestroy"); + mSession.onDestroy(); + mSession = null; + } + + public void onPlaybackStarted() { + if (!mStarted) { + Log.d(TAG, "Starting self"); + startService(onCreateServiceIntent()); + mStarted = true; + } + } + + public void onPlaybackEnded() { + if (mStarted) { + Log.d(TAG, "Stopping self"); + stopSelf(); + mStarted = false; + } + } + + protected Intent onCreateServiceIntent() { + return new Intent(this, PlayerService.class).setPackage(getBasePackageName()); + } + + protected PlayerSession onCreatePlayerController() { + return new PlayerSession(this); + } + + protected ArrayList<String> getAllowedPackages() { + return null; + } + + private final PlayerSession.Listener mPlayerListener = new PlayerSession.Listener() { + @Override + public void onPlayStateChanged(PlaybackState state) { + switch (state.getState()) { + case PlaybackState.PLAYSTATE_PLAYING: + onPlaybackStarted(); + break; + case PlaybackState.PLAYSTATE_STOPPED: + case PlaybackState.PLAYSTATE_ERROR: + onPlaybackEnded(); + break; + } + } + }; + + public class PlayerBinder extends IPlayerService.Stub { + @Override + public void sendRequest(String action, Bundle params, IRequestCallback cb) { + if (RequestUtils.ACTION_SET_CONTENT.equals(action)) { + mSession.setContent(params); + } else if (RequestUtils.ACTION_SET_NEXT_CONTENT.equals(action)) { + mSession.setNextContent(params); + } + } + + @Override + public void registerCallback(final IPlayerCallback cb) throws RemoteException { + if (!mCbs.contains(cb)) { + mCbs.add(cb); + cb.asBinder().linkToDeath(new IBinder.DeathRecipient() { + @Override + public void binderDied() { + mCbs.remove(cb); + } + }, 0); + } + try { + cb.onSessionChanged(getSessionToken()); + } catch (RemoteException e) { + mCbs.remove(cb); + throw e; + } + } + + @Override + public void unregisterCallback(IPlayerCallback cb) throws RemoteException { + mCbs.remove(cb); + } + + @Override + public MediaSessionToken getSessionToken() throws RemoteException { + return mSession.getSessionToken(); + } + } + +} diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java new file mode 100644 index 0000000..a2d7897 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 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. + * 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.onemedia; + +import android.content.Context; +import android.content.Intent; +import android.media.session.MediaSession; +import android.media.session.MediaSessionManager; +import android.media.session.MediaSessionToken; +import android.media.session.PlaybackState; +import android.media.session.TransportPerformer; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; + +import com.android.onemedia.playback.LocalRenderer; +import com.android.onemedia.playback.Renderer; +import com.android.onemedia.playback.RendererFactory; + +public class PlayerSession { + private static final String TAG = "PlayerSession"; + + protected MediaSession mSession; + protected Context mContext; + protected RendererFactory mRendererFactory; + protected LocalRenderer mRenderer; + protected MediaSession.Callback mCallback; + protected Renderer.Listener mRenderListener; + protected TransportPerformer mPerformer; + + protected PlaybackState mPlaybackState; + protected Listener mListener; + + public PlayerSession(Context context) { + mContext = context; + mRendererFactory = new RendererFactory(); + mRenderer = new LocalRenderer(context, null); + mCallback = new ControllerCb(); + mRenderListener = new RenderListener(); + mPlaybackState = new PlaybackState(); + mPlaybackState.setActions(PlaybackState.ACTION_PAUSE + | PlaybackState.ACTION_PLAY); + + mRenderer.registerListener(mRenderListener); + } + + public void createSession() { + if (mSession != null) { + mSession.release(); + } + MediaSessionManager man = (MediaSessionManager) mContext + .getSystemService(Context.MEDIA_SESSION_SERVICE); + Log.d(TAG, "Creating session for package " + mContext.getBasePackageName()); + mSession = man.createSession("OneMedia"); + mSession.addCallback(mCallback); + mPerformer = mSession.setTransportPerformerEnabled(); + mPerformer.addListener(new TransportListener()); + mPerformer.setPlaybackState(mPlaybackState); + mSession.publish(); + } + + public void onDestroy() { + if (mSession != null) { + mSession.release(); + } + if (mRenderer != null) { + mRenderer.unregisterListener(mRenderListener); + mRenderer.onDestroy(); + } + } + + public void setListener(Listener listener) { + mListener = listener; + } + + public MediaSessionToken getSessionToken() { + return mSession.getSessionToken(); + } + + public void setContent(Bundle request) { + mRenderer.setContent(request); + } + + public void setNextContent(Bundle request) { + mRenderer.setNextContent(request); + } + + public interface Listener { + public void onPlayStateChanged(PlaybackState state); + } + + private class RenderListener implements Renderer.Listener { + + @Override + public void onError(int type, int extra, Bundle extras, Throwable error) { + Log.d(TAG, "Sending onError with type " + type + " and extra " + extra); + mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR); + if (error != null) { + mPlaybackState.setErrorMessage(error.getLocalizedMessage()); + } + mPerformer.setPlaybackState(mPlaybackState); + if (mListener != null) { + mListener.onPlayStateChanged(mPlaybackState); + } + } + + @Override + public void onStateChanged(int newState) { + if (newState != Renderer.STATE_ERROR) { + mPlaybackState.setErrorMessage(null); + } + switch (newState) { + case Renderer.STATE_ENDED: + case Renderer.STATE_STOPPED: + mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED); + break; + case Renderer.STATE_INIT: + case Renderer.STATE_PREPARING: + mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING); + break; + case Renderer.STATE_ERROR: + mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR); + break; + case Renderer.STATE_PAUSED: + mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED); + break; + case Renderer.STATE_PLAYING: + mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING); + break; + default: + mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR); + mPlaybackState.setErrorMessage("unkown state"); + break; + } + mPlaybackState.setPosition(mRenderer.getSeekPosition()); + mPerformer.setPlaybackState(mPlaybackState); + if (mListener != null) { + mListener.onPlayStateChanged(mPlaybackState); + } + } + + @Override + public void onBufferingUpdate(int percent) { + } + + @Override + public void onFocusLost() { + Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED); + mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED); + mPlaybackState.setPosition(mRenderer.getSeekPosition()); + mPerformer.setPlaybackState(mPlaybackState); + if (mListener != null) { + mListener.onPlayStateChanged(mPlaybackState); + } + } + + @Override + public void onNextStarted() { + } + + } + + private class ControllerCb extends MediaSession.Callback { + + @Override + public void onMediaButton(Intent mediaRequestIntent) { + if (Intent.ACTION_MEDIA_BUTTON.equals(mediaRequestIntent.getAction())) { + KeyEvent event = (KeyEvent) mediaRequestIntent + .getParcelableExtra(Intent.EXTRA_KEY_EVENT); + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_MEDIA_PLAY: + Log.d(TAG, "play button received"); + mRenderer.onPlay(); + break; + case KeyEvent.KEYCODE_MEDIA_PAUSE: + Log.d(TAG, "pause button received"); + mRenderer.onPause(); + break; + } + } + } + } + + private class TransportListener extends TransportPerformer.Listener { + @Override + public void onPlay() { + mRenderer.onPlay(); + } + + @Override + public void onPause() { + mRenderer.onPause(); + } + } + +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/IRequestCallback.aidl b/tests/OneMedia/src/com/android/onemedia/playback/IRequestCallback.aidl new file mode 100644 index 0000000..c5a30a8 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/IRequestCallback.aidl @@ -0,0 +1,22 @@ +/* Copyright (C) 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. + * 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.onemedia.playback; + +import android.os.Bundle; + +oneway interface IRequestCallback { + void onResult(in Bundle result); +}
\ No newline at end of file diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java new file mode 100644 index 0000000..7f62f66 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java @@ -0,0 +1,704 @@ +package com.android.onemedia.playback; + +import org.apache.http.Header; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; + +import android.content.Context; +import android.media.AudioManager; +import android.media.AudioManager.OnAudioFocusChangeListener; +import android.media.MediaPlayer; +import android.media.MediaPlayer.OnBufferingUpdateListener; +import android.media.MediaPlayer.OnCompletionListener; +import android.media.MediaPlayer.OnErrorListener; +import android.media.MediaPlayer.OnPreparedListener; +import android.net.Uri; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.SurfaceHolder; + +import java.io.IOException; +import java.util.Map; + +/** + * Helper class for wrapping a MediaPlayer and doing a lot of the default work + * to play audio. This class is not currently thread safe and all calls to it + * should be made on the same thread. + */ +public class LocalRenderer extends Renderer implements OnPreparedListener, + OnBufferingUpdateListener, OnCompletionListener, OnErrorListener, + OnAudioFocusChangeListener { + private static final String TAG = "MediaPlayerManager"; + private static final boolean DEBUG = true; + private static long sDebugInstanceId = 0; + + private static final String[] SUPPORTED_FEATURES = { + FEATURE_SET_CONTENT, + FEATURE_SET_NEXT_CONTENT, + FEATURE_PLAY, + FEATURE_PAUSE, + FEATURE_NEXT, + FEATURE_PREVIOUS, + FEATURE_SEEK_TO, + FEATURE_STOP + }; + + /** + * These are the states where it is valid to call play directly on the + * MediaPlayer. + */ + private static final int CAN_PLAY = STATE_READY | STATE_PAUSED | STATE_ENDED; + /** + * These are the states where we expect the MediaPlayer to be ready in the + * future, so we can set a flag to start playing when it is. + */ + private static final int CAN_READY_PLAY = STATE_INIT | STATE_PREPARING; + /** + * The states when it is valid to call pause on the MediaPlayer. + */ + private static final int CAN_PAUSE = STATE_PLAYING; + /** + * The states where it is valid to call seek on the MediaPlayer. + */ + private static final int CAN_SEEK = STATE_READY | STATE_PLAYING | STATE_PAUSED | STATE_ENDED; + /** + * The states where we expect the MediaPlayer to be ready in the future and + * can store a seek position to set later. + */ + private static final int CAN_READY_SEEK = STATE_INIT | STATE_PREPARING; + /** + * The states where it is valid to call stop on the MediaPlayer. + */ + private static final int CAN_STOP = STATE_READY | STATE_PLAYING | STATE_PAUSED | STATE_ENDED; + /** + * The states where it is valid to get the current play position and the + * duration from the MediaPlayer. + */ + private static final int CAN_GET_POSITION = STATE_READY | STATE_PLAYING | STATE_PAUSED; + + + + private class PlayerContent { + public final String source; + public final Map<String, String> headers; + + public PlayerContent(String source, Map<String, String> headers) { + this.source = source; + this.headers = headers; + } + } + + private class AsyncErrorRetriever extends AsyncTask<HttpGet, Void, Void> { + private final long errorId; + private boolean closeHttpClient; + + public AsyncErrorRetriever(long errorId) { + this.errorId = errorId; + closeHttpClient = false; + } + + public boolean cancelRequestLocked(boolean closeHttp) { + closeHttpClient = closeHttp; + return this.cancel(false); + } + + @Override + protected Void doInBackground(HttpGet[] params) { + synchronized (mErrorLock) { + if (isCancelled() || mHttpClient == null) { + if (mErrorRetriever == this) { + mErrorRetriever = null; + } + return null; + } + mSafeToCloseClient = false; + } + final PlaybackError error = new PlaybackError(); + try { + HttpResponse response = mHttpClient.execute(params[0]); + synchronized (mErrorLock) { + if (mErrorId != errorId || mError == null) { + // A new error has occurred, abort + return null; + } + error.type = mError.type; + error.extra = mError.extra; + error.errorMessage = mError.errorMessage; + } + final int code = response.getStatusLine().getStatusCode(); + if (code >= 300) { + error.extra = code; + } + final Bundle errorExtras = new Bundle(); + Header[] headers = response.getAllHeaders(); + if (headers != null && headers.length > 0) { + for (Header header : headers) { + errorExtras.putString(header.getName(), header.getValue()); + } + error.errorExtras = errorExtras; + } + } catch (IOException e) { + Log.e(TAG, "IOException requesting from server, unable to get more exact error"); + } finally { + synchronized (mErrorLock) { + mSafeToCloseClient = true; + if (mErrorRetriever == this) { + mErrorRetriever = null; + } + if (isCancelled()) { + if (closeHttpClient) { + mHttpClient.close(); + mHttpClient = null; + } + return null; + } + } + } + mHandler.post(new Runnable() { + @Override + public void run() { + synchronized (mErrorLock) { + if (mErrorId == errorId) { + setError(error.type, error.extra, error.errorExtras, null); + } + } + } + }); + return null; + } + } + + private int mState = STATE_INIT; + + private AudioManager mAudioManager; + private MediaPlayer mPlayer; + private PlayerContent mContent; + private MediaPlayer mNextPlayer; + private PlayerContent mNextContent; + private SurfaceHolder mHolder; + private SurfaceHolder.Callback mHolderCB; + private Context mContext; + + private Handler mHandler = new Handler(); + + private AndroidHttpClient mHttpClient = AndroidHttpClient.newInstance("TUQ"); + // The ongoing error request thread if there is one. This should only be + // modified while mErrorLock is held. + private AsyncErrorRetriever mErrorRetriever; + // This is set to false while a server request is being made to retrieve + // the current error. It should only be set while mErrorLock is held. + private boolean mSafeToCloseClient = true; + private final Object mErrorLock = new Object(); + // A tracking id for the current error. This should only be modified while + // mErrorLock is held. + private long mErrorId = 0; + // The current error state of this player. This is cleared when the state + // leaves an error state and set when it enters one. This should only be + // modified when mErrorLock is held. + private PlaybackError mError; + + private boolean mPlayOnReady; + private int mSeekOnReady; + private boolean mHasAudioFocus; + private long mDebugId = sDebugInstanceId++; + + public LocalRenderer(Context context, Bundle params) { + super(context, params); + mContext = context; + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + } + + @Override + protected void initFeatures(Bundle params) { + for (String feature : SUPPORTED_FEATURES) { + mFeatures.add(feature); + } + } + + /** + * Call this when completely finished with the MediaPlayerManager to have it + * clean up. The instance may not be used again after this is called. + */ + @Override + public void onDestroy() { + synchronized (mErrorLock) { + if (DEBUG) { + Log.d(TAG, "onDestroy, error retriever? " + mErrorRetriever + " safe to close? " + + mSafeToCloseClient + " client? " + mHttpClient); + } + if (mErrorRetriever != null) { + mErrorRetriever.cancelRequestLocked(true); + mErrorRetriever = null; + } + // Increment the error id to ensure no errors are sent after this + // point. + mErrorId++; + if (mSafeToCloseClient) { + mHttpClient.close(); + mHttpClient = null; + } + } + } + + @Override + public void onPrepared(MediaPlayer player) { + if (!isCurrentPlayer(player)) { + return; + } + setState(STATE_READY); + if (DEBUG) { + Log.d(TAG, mDebugId + ": Finished preparing, seekOnReady is " + mSeekOnReady); + } + if (mSeekOnReady >= 0) { + onSeekTo(mSeekOnReady); + mSeekOnReady = -1; + } + if (mPlayOnReady) { + player.start(); + setState(STATE_PLAYING); + } + } + + @Override + public void onBufferingUpdate(MediaPlayer player, int percent) { + if (!isCurrentPlayer(player)) { + return; + } + pushOnBufferingUpdate(percent); + } + + @Override + public void onCompletion(MediaPlayer player) { + if (!isCurrentPlayer(player)) { + return; + } + if (DEBUG) { + Log.d(TAG, mDebugId + ": Completed item. Have next item? " + (mNextPlayer != null)); + } + if (mNextPlayer != null) { + if (mPlayer != null) { + mPlayer.release(); + } + mPlayer = mNextPlayer; + mContent = mNextContent; + mNextPlayer = null; + mNextContent = null; + pushOnNextStarted(); + return; + } + setState(STATE_ENDED); + } + + @Override + public boolean onError(MediaPlayer player, int what, int extra) { + if (!isCurrentPlayer(player)) { + return false; + } + if (DEBUG) { + Log.d(TAG, mDebugId + ": Entered error state, what: " + what + " extra: " + extra); + } + synchronized (mErrorLock) { + ++mErrorId; + mError = new PlaybackError(); + mError.type = what; + mError.extra = extra; + } + + if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN && extra == MediaPlayer.MEDIA_ERROR_IO + && mContent != null && mContent.source.startsWith("http")) { + HttpGet request = new HttpGet(mContent.source); + if (mContent.headers != null) { + for (String key : mContent.headers.keySet()) { + request.addHeader(key, mContent.headers.get(key)); + } + } + synchronized (mErrorLock) { + if (mErrorRetriever != null) { + mErrorRetriever.cancelRequestLocked(false); + } + mErrorRetriever = new AsyncErrorRetriever(mErrorId); + mErrorRetriever.execute(request); + } + } else { + setError(what, extra, null, null); + } + return true; + } + + @Override + public void onAudioFocusChange(int focusChange) { + // TODO figure out appropriate logic for handling focus loss at the TUQ + // level. + switch (focusChange) { + case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: + case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: + if (mState == STATE_PLAYING) { + onPause(); + mPlayOnReady = true; + } + mHasAudioFocus = false; + break; + case AudioManager.AUDIOFOCUS_LOSS: + if (mState == STATE_PLAYING) { + onPause(); + mPlayOnReady = false; + } + pushOnFocusLost(); + mHasAudioFocus = false; + break; + case AudioManager.AUDIOFOCUS_GAIN: + mHasAudioFocus = true; + if (mPlayOnReady) { + onPlay(); + } + break; + default: + Log.d(TAG, "Unknown focus change event " + focusChange); + break; + } + } + + @Override + public void setContent(Bundle request) { + setContent(request, null); + } + + /** + * Prepares the player for the given playback request. If the holder is null + * it is assumed this is an audio only source. If playOnReady is set to true + * the media will begin playing as soon as it can. + */ + public void setContent(Bundle request, SurfaceHolder holder) { + String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE); + Map<String, String> headers = null; // request.mHeaders; + boolean playOnReady = true; // request.mPlayOnReady; + if (DEBUG) { + Log.d(TAG, mDebugId + ": Settings new content. Have a player? " + (mPlayer != null) + + " have a next player? " + (mNextPlayer != null)); + } + cleanUpPlayer(); + setState(STATE_PREPARING); + mPlayOnReady = playOnReady; + mSeekOnReady = -1; + final MediaPlayer newPlayer = new MediaPlayer(); + + requestAudioFocus(); + + mPlayer = newPlayer; + mContent = new PlayerContent(source, headers); + try { + if (headers != null) { + Uri sourceUri = Uri.parse(source); + newPlayer.setDataSource(mContext, sourceUri, headers); + } else { + newPlayer.setDataSource(source); + } + } catch (Exception e) { + setError(Listener.ERROR_LOAD_FAILED, 0, null, e); + return; + } + if (isHolderReady(holder, newPlayer)) { + preparePlayer(newPlayer, true); + } + } + + @Override + public void setNextContent(Bundle request) { + String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE); + Map<String, String> headers = null; // request.mHeaders; + + // TODO support video + + if (DEBUG) { + Log.d(TAG, mDebugId + ": Setting next content. Have player? " + (mPlayer != null) + + " have next player? " + (mNextPlayer != null)); + } + + if (mPlayer == null) { + // The manager isn't being used to play anything, don't try to + // set a next. + return; + } + if (mNextPlayer != null) { + // Before setting up the new one clear out the old one and release + // it to ensure it doesn't play. + mPlayer.setNextMediaPlayer(null); + mNextPlayer.release(); + mNextPlayer = null; + mNextContent = null; + } + if (source == null) { + // If there's no new content we're done + return; + } + final MediaPlayer newPlayer = new MediaPlayer(); + + try { + if (headers != null) { + Uri sourceUri = Uri.parse(source); + newPlayer.setDataSource(mContext, sourceUri, headers); + } else { + newPlayer.setDataSource(source); + } + } catch (Exception e) { + newPlayer.release(); + // Don't return an error until we get to this item in playback + return; + } + + if (preparePlayer(newPlayer, false)) { + mPlayer.setNextMediaPlayer(newPlayer); + mNextPlayer = newPlayer; + mNextContent = new PlayerContent(source, headers); + } + } + + private void requestAudioFocus() { + int result = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, + AudioManager.AUDIOFOCUS_GAIN); + mHasAudioFocus = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED; + } + + /** + * Start the player if possible or queue it to play when ready. If the + * player is in a state where it will never be ready returns false. + * + * @return true if the content was started or will be started later + */ + @Override + public boolean onPlay() { + MediaPlayer player = mPlayer; + if (player != null && mState == STATE_PLAYING) { + // already playing, just return + return true; + } + if (!mHasAudioFocus) { + requestAudioFocus(); + } + if (player != null && canPlay()) { + player.start(); + setState(STATE_PLAYING); + } else if (canReadyPlay()) { + mPlayOnReady = true; + } else if (!isPlaying()) { + return false; + } + return true; + } + + /** + * Pause the player if possible or set it to not play when ready. If the + * player is in a state where it will never be ready returns false. + * + * @return true if the content was paused or will wait to play when ready + * later + */ + @Override + public boolean onPause() { + MediaPlayer player = mPlayer; + // If the user paused us make sure we won't start playing again until + // asked to + mPlayOnReady = false; + if (player != null && (mState & CAN_PAUSE) != 0) { + player.pause(); + setState(STATE_PAUSED); + } else if (!isPaused()) { + return false; + } + return true; + } + + /** + * Seek to a given position in the media. If the seek succeeded or will be + * performed when loading is complete returns true. If the position is not + * in range or the player will never be ready returns false. + * + * @param position The position to seek to in milliseconds + * @return true if playback was moved or will be moved when ready + */ + @Override + public boolean onSeekTo(int position) { + MediaPlayer player = mPlayer; + if (player != null && (mState & CAN_SEEK) != 0) { + if (position < 0 || position >= getDuration()) { + return false; + } else { + if (mState == STATE_ENDED) { + player.start(); + player.pause(); + setState(STATE_PAUSED); + } + player.seekTo(position); + } + } else if ((mState & CAN_READY_SEEK) != 0) { + mSeekOnReady = position; + } else { + return false; + } + return true; + } + + /** + * Stop the player. It cannot be used again until + * {@link #setContent(String, boolean)} is called. + * + * @return true if stopping the player succeeded + */ + @Override + public boolean onStop() { + cleanUpPlayer(); + setState(STATE_STOPPED); + return true; + } + + public boolean isPlaying() { + return mState == STATE_PLAYING; + } + + public boolean isPaused() { + return mState == STATE_PAUSED; + } + + @Override + public long getSeekPosition() { + return ((mState & CAN_GET_POSITION) == 0) ? -1 : mPlayer.getCurrentPosition(); + } + + @Override + public long getDuration() { + return ((mState & CAN_GET_POSITION) == 0) ? -1 : mPlayer.getDuration(); + } + + private boolean canPlay() { + return ((mState & CAN_PLAY) != 0) && mHasAudioFocus; + } + + private boolean canReadyPlay() { + return (mState & CAN_PLAY) != 0 || (mState & CAN_READY_PLAY) != 0; + } + + /** + * Sends a state update if the listener exists + */ + private void setState(int state) { + if (state == mState) { + return; + } + Log.d(TAG, "Entering state " + state + " from state " + mState); + mState = state; + if (state != STATE_ERROR) { + // Don't notify error here, it'll get sent via onError + pushOnStateChanged(state); + } + } + + private boolean preparePlayer(final MediaPlayer player, boolean current) { + player.setOnPreparedListener(this); + player.setOnBufferingUpdateListener(this); + player.setOnCompletionListener(this); + player.setOnErrorListener(this); + try { + player.prepareAsync(); + if (current) { + setState(STATE_PREPARING); + } + } catch (IllegalStateException e) { + if (current) { + setError(Listener.ERROR_PREPARE_ERROR, 0, null, e); + } + return false; + } + return true; + } + + /** + * @param extra + * @param e + */ + private void setError(int type, int extra, Bundle extras, Exception e) { + setState(STATE_ERROR); + pushOnError(type, extra, extras, e); + cleanUpPlayer(); + return; + } + + /** + * Checks if the holder is ready and either sets up a callback to wait for + * it or sets it directly. If + * + * @param holder + * @param player + * @return + */ + private boolean isHolderReady(final SurfaceHolder holder, final MediaPlayer player) { + mHolder = holder; + if (holder != null) { + if (holder.getSurface() != null && holder.getSurface().isValid()) { + player.setDisplay(holder); + return true; + } else { + Log.w(TAG, "Holder not null, waiting for it to be ready"); + // If the holder isn't ready yet add a callback to set the + // holder when it's ready. + SurfaceHolder.Callback cb = new SurfaceHolder.Callback() { + @Override + public void surfaceDestroyed(SurfaceHolder arg0) { + } + + @Override + public void surfaceCreated(SurfaceHolder arg0) { + if (player.equals(mPlayer)) { + player.setDisplay(arg0); + preparePlayer(player, true); + } + } + + @Override + public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { + } + }; + mHolderCB = cb; + holder.addCallback(cb); + return false; + } + } + return true; + } + + private void cleanUpPlayer() { + if (DEBUG) { + Log.d(TAG, mDebugId + ": Cleaning up current player"); + } + synchronized (mErrorLock) { + mError = null; + if (mErrorRetriever != null) { + mErrorRetriever.cancelRequestLocked(false); + // Don't set to null as we may need to cancel again with true if + // the object gets destroyed. + } + } + mAudioManager.abandonAudioFocus(this); + + SurfaceHolder.Callback cb = mHolderCB; + mHolderCB = null; + SurfaceHolder holder = mHolder; + mHolder = null; + if (holder != null && cb != null) { + holder.removeCallback(cb); + } + + MediaPlayer player = mPlayer; + mPlayer = null; + if (player != null) { + player.reset(); + player.release(); + } + } + + private boolean isCurrentPlayer(MediaPlayer player) { + return player.equals(mPlayer); + } +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java new file mode 100644 index 0000000..f9e6794 --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java @@ -0,0 +1,59 @@ +package com.android.onemedia.playback; + +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v7.media.MediaItemMetadata; + +/** + * TODO: Insert description here. (generated by epastern) + */ +public class MediaItem implements Parcelable { + private Bundle mBundle; + + public MediaItem() { + + } + + private MediaItem(Parcel in) { + mBundle = in.readBundle(); + } + + public String getTitle() { + return mBundle.getString(MediaItemMetadata.KEY_TITLE); + } + + public String getArtist() { + return mBundle.getString(MediaItemMetadata.KEY_ALBUM_ARTIST); + } + + /* (non-Javadoc) + * @see android.os.Parcelable#describeContents() + */ + @Override + public int describeContents() { + // TODO(epastern): Auto-generated method stub + return 0; + } + + /* + * (non-Javadoc) + * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int) + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeBundle(mBundle); + } + + public static final Parcelable.Creator<MediaItem> CREATOR + = new Parcelable.Creator<MediaItem>() { + public MediaItem createFromParcel(Parcel in) { + return new MediaItem(in); + } + + public MediaItem[] newArray(int size) { + return new MediaItem[size]; + } + }; + +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java new file mode 100644 index 0000000..72d936c --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java @@ -0,0 +1,10 @@ +package com.android.onemedia.playback; + +import android.os.Bundle; + +public class PlaybackError { + public int type; + public int extra; + public String errorMessage; + public Bundle errorExtras; +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java new file mode 100644 index 0000000..2451bdf --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java @@ -0,0 +1,199 @@ +package com.android.onemedia.playback; + +import android.content.Context; +import android.media.MediaPlayer; +import android.os.Bundle; + +import java.util.ArrayList; +import java.util.List; + +/** + * TODO: Insert description here. (generated by epastern) + */ +public abstract class Renderer { + public static final String FEATURE_SET_CONTENT = "com.android.media.SET_CONTENT"; + public static final String FEATURE_SET_NEXT_CONTENT = "com.android.media.SET_NEXT_CONTENT"; + public static final String FEATURE_PLAY = "com.android.media.PLAY"; + public static final String FEATURE_PAUSE = "com.android.media.PAUSE"; + public static final String FEATURE_NEXT = "com.android.media.NEXT"; + public static final String FEATURE_PREVIOUS = "com.android.media.PREVIOUS"; + public static final String FEATURE_SEEK_TO = "com.android.media.SEEK_TO"; + public static final String FEATURE_STOP = "com.android.media.STOP"; + // TODO move states somewhere else + public static final int STATE_ERROR = 0; + /** + * The state MediaPlayerManager starts in before any action has been + * performed. + */ + public static final int STATE_INIT = 1 << 0; + /** + * Indicates the source has been set and it is being prepared/buffered + * before starting playback. + */ + public static final int STATE_PREPARING = 1 << 1; + /** + * The media is ready and playback can be started. + */ + public static final int STATE_READY = 1 << 2; + /** + * The media is currently playing. + */ + public static final int STATE_PLAYING = 1 << 3; + /** + * The media is currently paused. + */ + public static final int STATE_PAUSED = 1 << 4; + /** + * The service has been stopped and cannot be started again until a new + * source has been set. + */ + public static final int STATE_STOPPED = 1 << 5; + /** + * The playback has reached the end. It can be restarted by calling play(). + */ + public static final int STATE_ENDED = 1 << 6; + + // TODO decide on proper way of describing features + protected List<String> mFeatures = new ArrayList<String>(); + protected List<Listener> mListeners = new ArrayList<Listener>(); + + public Renderer(Context context, Bundle params) { + onCreate(params); + initFeatures(params); + } + + abstract public void setContent(Bundle request); + + public void onCreate(Bundle params) { + // Do nothing by default + } + + public void setNextContent(Bundle request) { + throw new UnsupportedOperationException("setNextContent() is not supported."); + } + + public List<String> getFeatures() { + return mFeatures; + } + + public boolean onPlay() { + throw new UnsupportedOperationException("play is not supported."); + } + + public boolean onPause() { + throw new UnsupportedOperationException("pause is not supported."); + } + + public boolean onNext() { + throw new UnsupportedOperationException("next is not supported."); + } + + public boolean onPrevious() { + throw new UnsupportedOperationException("previous is not supported."); + } + + public boolean onStop() { + throw new UnsupportedOperationException("stop is not supported."); + } + + public boolean onSeekTo(int time) { + throw new UnsupportedOperationException("seekTo is not supported."); + } + + public long getSeekPosition() { + throw new UnsupportedOperationException("getSeekPosition is not supported."); + } + + public long getDuration() { + throw new UnsupportedOperationException("getDuration is not supported."); + } + + public int getPlayState() { + throw new UnsupportedOperationException("getPlayState is not supported."); + } + + public void onDestroy() { + // Do nothing by default + } + + public void registerListener(Listener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } + } + + public void unregisterListener(Listener listener) { + mListeners.remove(listener); + } + + protected void initFeatures(Bundle params) { + mFeatures.add(FEATURE_SET_CONTENT); + } + + protected void pushOnError(int type, int extra, Bundle extras, Throwable error) { + for (Listener listener : mListeners) { + listener.onError(type, extra, extras, error); + } + } + + protected void pushOnStateChanged(int newState) { + for (Listener listener : mListeners) { + listener.onStateChanged(newState); + } + } + + protected void pushOnBufferingUpdate(int percent) { + for (Listener listener : mListeners) { + listener.onBufferingUpdate(percent); + } + } + + protected void pushOnFocusLost() { + for (Listener listener : mListeners) { + listener.onFocusLost(); + } + } + + protected void pushOnNextStarted() { + for (Listener listener : mListeners) { + listener.onNextStarted(); + } + } + + public interface Listener { + public static final int ERROR_LOAD_FAILED = 1770; + public static final int ERROR_PREPARE_ERROR = 1771; + public static final int ERROR_PLAYBACK_FAILED = 1772; + + /** + * When an error occurs onError will be called but not onStateChanged. + * The Manager will remain in the error state until + * {@link #setContent()} is called again. + */ + public void onError(int type, int extra, Bundle extras, + Throwable error); + + /** + * onStateChanged will be called whenever the state of the manager + * transitions except to an error state. + */ + public void onStateChanged(int newState); + + /** + * This is a passthrough of + * {@link MediaPlayer.OnBufferingUpdateListener}. + */ + public void onBufferingUpdate(int percent); + + /** + * Called when audio focus is lost and it is not transient or ducking. + */ + public void onFocusLost(); + + /** + * Called when the next item was started playing. Only called if a next + * item has been set and the current item has ended. + */ + public void onNextStarted(); + } +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java b/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java new file mode 100644 index 0000000..f333fce --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java @@ -0,0 +1,22 @@ +package com.android.onemedia.playback; + +import android.content.Context; +import android.media.MediaRouter; +import android.os.Bundle; +import android.util.Log; + +/** + * TODO: Insert description here. + */ +public class RendererFactory { + private static final String TAG = "RendererFactory"; + + public Renderer createRenderer(MediaRouter.RouteInfo route, Context context, Bundle params) { + if (route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL) { + return new LocalRenderer(context, params); + } + Log.e(TAG, "Unable to create renderer for route of playback type " + + route.getPlaybackType()); + return null; + } +} diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java new file mode 100644 index 0000000..9b50dad --- /dev/null +++ b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java @@ -0,0 +1,53 @@ +package com.android.onemedia.playback; + +import android.os.Bundle; +import android.support.v7.media.MediaItemMetadata; + +import java.util.HashMap; +import java.util.Map; + +/** + * TODO: Insert description here. (generated by epastern) + */ +public class RequestUtils { + public static final String ACTION_SET_CONTENT = "set_content"; + public static final String ACTION_SET_NEXT_CONTENT = "set_next_content"; + + public static final String EXTRA_KEY_SOURCE = "source"; + public static final String EXTRA_KEY_METADATA = "metadata"; + public static final String EXTRA_KEY_HEADERS = "headers"; + + private RequestUtils() { + } + + public static class ContentBuilder { + private Bundle mBundle; + + public ContentBuilder() { + mBundle = new Bundle(); + } + + public ContentBuilder setSource(String source) { + mBundle.putString(EXTRA_KEY_SOURCE, source); + return this; + } + + /** + * @see MediaItemMetadata + * @param metadata The metadata for this item + */ + public ContentBuilder setMetadata(Bundle metadata) { + mBundle.putBundle(EXTRA_KEY_METADATA, metadata); + return this; + } + + public ContentBuilder setHeaders(HashMap<String, String> headers) { + mBundle.putSerializable(EXTRA_KEY_HEADERS, headers); + return this; + } + + public Bundle build() { + return mBundle; + } + } +} diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk new file mode 100644 index 0000000..bdcba2e --- /dev/null +++ b/tests/RenderThreadTest/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +# Only compile source java files in this apk. +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := RenderThreadTest + +LOCAL_STATIC_JAVA_LIBRARIES += android-common + +LOCAL_PROGUARD_ENABLED := disabled + +include $(BUILD_PACKAGE) + +# Use the following include to make our test apk. +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tests/RenderThreadTest/AndroidManifest.xml b/tests/RenderThreadTest/AndroidManifest.xml new file mode 100644 index 0000000..c76cfce --- /dev/null +++ b/tests/RenderThreadTest/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.renderthread" + android:versionCode="1" + android:versionName="1.0" > + + <uses-sdk + android:minSdkVersion="18" + android:targetSdkVersion="18" /> + + <application + android:allowBackup="true" + android:icon="@drawable/ic_launcher" + android:label="@string/app_name" + android:theme="@style/AppTheme" > + <activity + android:name=".MainActivity" + android:label="@string/app_name" > + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + <activity android:name=".SubActivity" + android:theme="@style/AppTheme.Transparent" /> + </application> + +</manifest> diff --git a/tests/RenderThreadTest/res/drawable-hdpi/ic_launcher.png b/tests/RenderThreadTest/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..96a442e --- /dev/null +++ b/tests/RenderThreadTest/res/drawable-hdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-mdpi/ic_launcher.png b/tests/RenderThreadTest/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..359047d --- /dev/null +++ b/tests/RenderThreadTest/res/drawable-mdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png b/tests/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 0000000..71c6d76 --- /dev/null +++ b/tests/RenderThreadTest/res/drawable-xhdpi/ic_launcher.png diff --git a/tests/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg b/tests/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg Binary files differnew file mode 100644 index 0000000..755232d --- /dev/null +++ b/tests/RenderThreadTest/res/drawable-xhdpi/starry_night_bg.jpg diff --git a/tests/RenderThreadTest/res/layout/activity_main.xml b/tests/RenderThreadTest/res/layout/activity_main.xml new file mode 100644 index 0000000..1fd5459 --- /dev/null +++ b/tests/RenderThreadTest/res/layout/activity_main.xml @@ -0,0 +1,12 @@ +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".MainActivity" > + + <ListView android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:divider="@null" /> + +</FrameLayout> diff --git a/tests/RenderThreadTest/res/layout/activity_sub.xml b/tests/RenderThreadTest/res/layout/activity_sub.xml new file mode 100644 index 0000000..713cee4 --- /dev/null +++ b/tests/RenderThreadTest/res/layout/activity_sub.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" > + + <View + android:id="@+id/bg_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/starry_night_bg" /> + + <LinearLayout + android:id="@+id/my_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <View + android:id="@+id/from_left" + android:layout_width="match_parent" + android:layout_height="48dip" + android:background="#7000FF00" /> + + <View + android:id="@+id/from_right" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_margin="80dip" + android:layout_weight="1" + android:background="#90FF0000" /> + + <View + android:id="@+id/from_left" + android:layout_width="match_parent" + android:layout_height="48dip" + android:background="#7000FF00" /> + </LinearLayout> + +</FrameLayout>
\ No newline at end of file diff --git a/tests/RenderThreadTest/res/layout/item_layout.xml b/tests/RenderThreadTest/res/layout/item_layout.xml new file mode 100644 index 0000000..5bdb1ac --- /dev/null +++ b/tests/RenderThreadTest/res/layout/item_layout.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceListItemSmall" + android:gravity="center_vertical" + android:paddingStart="?android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:background="#33b5e5" +/>
\ No newline at end of file diff --git a/tests/RenderThreadTest/res/values/strings.xml b/tests/RenderThreadTest/res/values/strings.xml new file mode 100644 index 0000000..f782e98 --- /dev/null +++ b/tests/RenderThreadTest/res/values/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name">Render Thread</string> + <string name="action_settings">Settings</string> + <string name="hello_world">Hello world!</string> + +</resources> diff --git a/tests/RenderThreadTest/res/values/styles.xml b/tests/RenderThreadTest/res/values/styles.xml new file mode 100644 index 0000000..f6b5d6a --- /dev/null +++ b/tests/RenderThreadTest/res/values/styles.xml @@ -0,0 +1,11 @@ +<resources> + <!-- Application theme. --> + <style name="AppTheme" parent="android:Theme.Holo.Light"> + </style> + + <style name="AppTheme.Transparent"> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowBackground">@android:color/transparent</item> + </style> + +</resources> diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java new file mode 100644 index 0000000..09531fd --- /dev/null +++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java @@ -0,0 +1,158 @@ + +package com.example.renderthread; + +import android.animation.TimeInterpolator; +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.SystemClock; +import android.view.RenderNode; +import android.view.HardwareRenderer; +import android.view.ThreadedRenderer; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListView; +import android.widget.SimpleAdapter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class MainActivity extends Activity implements OnItemClickListener { + + static final int DURATION = 400; + + static final String KEY_NAME = "name"; + static final String KEY_CLASS = "clazz"; + + static Map<String,?> make(String name) { + Map<String,Object> ret = new HashMap<String,Object>(); + ret.put(KEY_NAME, name); + return ret; + } + + @SuppressWarnings("serial") + static final ArrayList<Map<String,?>> SAMPLES = new ArrayList<Map<String,?>>() {{ + for (int i = 1; i < 25; i++) { + add(make("List Item: " + i)); + } + }}; + + Handler mHandler = new Handler(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + HardwareRenderer.sUseRenderThread = true; + setContentView(R.layout.activity_main); + ListView lv = (ListView) findViewById(android.R.id.list); + lv.setDrawSelectorOnTop(true); + lv.setAdapter(new SimpleAdapter(this, SAMPLES, + R.layout.item_layout, new String[] { KEY_NAME }, + new int[] { android.R.id.text1 })); + lv.setOnItemClickListener(this); + getActionBar().setTitle("MainActivity"); + } + + @Override + protected void onResume() { + super.onResume(); + ListView lv = (ListView) findViewById(android.R.id.list); + for (int i = 0; i < lv.getChildCount(); i++) { + lv.getChildAt(i).animate().translationY(0).setDuration(DURATION); + } + } + + private static class DisplayListAnimator { + private static final TimeInterpolator sDefaultInterpolator = + new AccelerateDecelerateInterpolator(); + + RenderNode mDisplayList; + float mFromValue; + float mDelta; + long mDuration = DURATION * 2; + long mStartTime; + + DisplayListAnimator(View view, float translateXBy) { + mDelta = translateXBy; + mFromValue = view.getTranslationY(); + mDisplayList = view.getDisplayList(); + } + + boolean animate(long currentTime) { + if (mStartTime == 0) mStartTime = currentTime; + + float fraction = (float)(currentTime - mStartTime) / mDuration; + if (fraction > 1) { + return false; + } + fraction = sDefaultInterpolator.getInterpolation(fraction); + float translation = mFromValue + (mDelta * fraction); + mDisplayList.setTranslationY(translation); + return fraction < 1f; + } + } + + private static class AnimationExecutor implements Runnable { + DisplayListAnimator[] mAnimations; + ThreadedRenderer mRenderer; + + AnimationExecutor(ThreadedRenderer renderer, DisplayListAnimator[] animations) { + mRenderer = renderer; + mAnimations = animations; + ThreadedRenderer.postToRenderThread(this); + } + + @Override + public void run() { + boolean hasMore = false; + long now = SystemClock.uptimeMillis(); + for (DisplayListAnimator animator : mAnimations) { + hasMore |= animator.animate(now); + } + mRenderer.repeatLastDraw(); + if (hasMore) { + ThreadedRenderer.postToRenderThread(this); + } + } + + } + + @Override + public void onItemClick(final AdapterView<?> adapterView, View clickedView, + int clickedPosition, long clickedId) { + int topPosition = adapterView.getFirstVisiblePosition(); + int dy = adapterView.getHeight(); + final DisplayListAnimator[] animators = new DisplayListAnimator[adapterView.getChildCount()]; + for (int i = 0; i < adapterView.getChildCount(); i++) { + int pos = topPosition + i; + View child = adapterView.getChildAt(i); + float delta = (pos - clickedPosition) * 1.1f; + if (delta == 0) delta = -1; + animators[i] = new DisplayListAnimator(child, dy * delta); + } + adapterView.invalidate(); + adapterView.post(new Runnable() { + + @Override + public void run() { + new AnimationExecutor((ThreadedRenderer) adapterView.getHardwareRenderer(), animators); + } + }); + //mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4)); + mLaunchActivity.run(); + } + + private Runnable mLaunchActivity = new Runnable() { + + @Override + public void run() { + startActivity(new Intent(MainActivity.this, SubActivity.class)); + overridePendingTransition(0, 0); + } + }; + +} diff --git a/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java new file mode 100644 index 0000000..892cbae --- /dev/null +++ b/tests/RenderThreadTest/src/com/example/renderthread/SubActivity.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 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.example.renderthread; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Process; +import android.os.SystemClock; +import android.view.View; +import android.view.ViewGroup; + +public class SubActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + long before = SystemClock.currentThreadTimeMillis(); + setContentView(R.layout.activity_sub); + getActionBar().setTitle("SubActivity"); + // Simulate being a real app! + while (SystemClock.currentThreadTimeMillis() - before < 100) { + View v = new View(this, null); + } + } + + @Override + protected void onResume() { + super.onResume(); + ViewGroup container = (ViewGroup) findViewById(R.id.my_container); + int dx = getWindowManager().getDefaultDisplay().getWidth(); + for (int i = 0; i < container.getChildCount(); i++) { + View child = container.getChildAt(i); + int dir = child.getId() == R.id.from_left ? 1 : -1; + child.setTranslationX(dx * dir); + child.animate().translationX(0).setDuration(MainActivity.DURATION); + } + View bg = findViewById(R.id.bg_container); + bg.setAlpha(0f); + bg.animate().alpha(1f).setDuration(MainActivity.DURATION); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + overridePendingTransition(0, 0); + } +} diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk index 60ef92a..1d66bb9 100644 --- a/tests/SharedLibrary/client/Android.mk +++ b/tests/SharedLibrary/client/Android.mk @@ -3,7 +3,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_APK_LIBRARIES := SharedLibrary +LOCAL_RES_LIBRARIES := SharedLibrary LOCAL_PACKAGE_NAME := SharedLibraryClient diff --git a/tests/SharedLibrary/client/AndroidManifest.xml b/tests/SharedLibrary/client/AndroidManifest.xml index c6a43c0..a39c754 100644 --- a/tests/SharedLibrary/client/AndroidManifest.xml +++ b/tests/SharedLibrary/client/AndroidManifest.xml @@ -16,7 +16,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.google.android.test.lib_client"> - <application android:label="@string/app_title"> + <application android:label="@string/app_title" android:theme="@style/Theme"> <uses-library android:name="android.test.runner" /> <uses-library android:name="com.google.android.test.shared_library" /> <activity android:name="ActivityMain"> diff --git a/tests/SharedLibrary/client/res/layout/main.xml b/tests/SharedLibrary/client/res/layout/main.xml new file mode 100644 index 0000000..067ef9f --- /dev/null +++ b/tests/SharedLibrary/client/res/layout/main.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView android:id="@+id/label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@com.google.android.test.shared_library:string/shared_string" + style="@com.google.android.test.shared_library:style/CodeFont"/> + + <com.google.android.test.shared_library.AddressView + xmlns:custom="http://schemas.android.com/apk/res/com.google.android.test.shared_library" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + custom:name="Professor Android" + custom:streetNumber="44" + custom:streetName="KitKat Lane" + custom:city="AndroidVille" + custom:state="OS" + custom:country="Mobile" + custom:zip="12345"/> +</LinearLayout> diff --git a/tests/SharedLibrary/client/res/values/strings.xml b/tests/SharedLibrary/client/res/values/strings.xml index 3757a25..d9efdc7 100644 --- a/tests/SharedLibrary/client/res/values/strings.xml +++ b/tests/SharedLibrary/client/res/values/strings.xml @@ -16,4 +16,5 @@ <resources> <string name="app_title">SharedLibrary client</string> + <string name="changes">@com.google.android.test.shared_library:string/shared_string</string> </resources> diff --git a/tests/SharedLibrary/client/res/values/themes.xml b/tests/SharedLibrary/client/res/values/themes.xml new file mode 100644 index 0000000..a14f98a --- /dev/null +++ b/tests/SharedLibrary/client/res/values/themes.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <style name="Theme" parent="com.google.android.test.shared_library:Theme"> + </style> +</resources> diff --git a/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java index d6121a5..7276b3c 100644 --- a/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java +++ b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java @@ -18,18 +18,33 @@ package com.google.android.test.lib_client; import android.app.Activity; import android.os.Bundle; -import android.widget.TextView; import com.google.android.test.shared_library.SharedLibraryMain; public class ActivityMain extends Activity { + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + String[] expectedAnimals = new String[] { + "Racoon", + "Rhino", + "Elephant" + }; + + String[] animals = getResources().getStringArray(com.google.android.test.shared_library.R.array.animals); + if (animals == null || animals.length != expectedAnimals.length) { + throw new AssertionError("Animal list from shared library is null or wrong length."); + } - TextView content = new TextView(this); - content.setText("Library version: " + SharedLibraryMain.getVersion(this) + "!"); + for (int i = 0; i < expectedAnimals.length; i++) { + if (!expectedAnimals[i].equals(animals[i])) { + throw new AssertionError("Expected '" + expectedAnimals[i] + + "' at index " + i + " but got '" + animals[i]); + } + } SharedLibraryMain.ensureVersion(this, SharedLibraryMain.VERSION_BASE); - setContentView(content); } } diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk index c19e23a..b2fc369 100644 --- a/tests/SharedLibrary/lib/Android.mk +++ b/tests/SharedLibrary/lib/Android.mk @@ -3,8 +3,13 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_AAPT_FLAGS := --shared-lib LOCAL_PACKAGE_NAME := SharedLibrary -LOCAL_MODULE_TAGS := tests +LOCAL_EXPORT_PACKAGE_RESOURCES := true +LOCAL_PRIVILEGED_MODULE := true +LOCAL_MODULE_TAGS := optional + +LOCAL_PROGUARD_FLAG_FILES := proguard.proguard include $(BUILD_PACKAGE) diff --git a/tests/SharedLibrary/lib/proguard.proguard b/tests/SharedLibrary/lib/proguard.proguard new file mode 100644 index 0000000..e5dfbe1 --- /dev/null +++ b/tests/SharedLibrary/lib/proguard.proguard @@ -0,0 +1,7 @@ +-keepparameternames +-keepattributes Exceptions,InnerClasses,Signature,Deprecated, + SourceFile,LineNumberTable,*Annotation*,EnclosingMethod + +-keep public class * { + public protected *; +} diff --git a/tests/SharedLibrary/lib/res/layout/address.xml b/tests/SharedLibrary/lib/res/layout/address.xml new file mode 100644 index 0000000..835f43e --- /dev/null +++ b/tests/SharedLibrary/lib/res/layout/address.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <TextView android:id="@+id/name" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/street" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/cityStateZip" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <TextView android:id="@+id/country" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> +</merge> diff --git a/tests/SharedLibrary/lib/res/values/attrs.xml b/tests/SharedLibrary/lib/res/values/attrs.xml new file mode 100644 index 0000000..8cefe92 --- /dev/null +++ b/tests/SharedLibrary/lib/res/values/attrs.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <declare-styleable name="AddressView"> + <attr name="name" format="string" /> + <attr name="streetNumber" format="integer" /> + <attr name="streetName" format="string" /> + <attr name="city" format="string" /> + <attr name="state" format="string" /> + <attr name="zip" format="string" /> + <attr name="country" format="string" /> + </declare-styleable> +</resources> diff --git a/tests/SharedLibrary/lib/res/values/public.xml b/tests/SharedLibrary/lib/res/values/public.xml new file mode 100644 index 0000000..37b1ec9 --- /dev/null +++ b/tests/SharedLibrary/lib/res/values/public.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <public type="string" name="shared_string" id="0x00020003" /> + <public type="style" name="CodeFont" id="0x00040000" /> + <public type="style" name="Theme" id="0x00040001" /> + + <public type="attr" name="name" id="0x00010000" /> + <public type="attr" name="streetNumber" id="0x00010001" /> + <public type="attr" name="streetName" id="0x00010002" /> + <public type="attr" name="city" id="0x00010003" /> + <public type="attr" name="state" id="0x00010004" /> + <public type="attr" name="zip" id="0x00010005" /> + <public type="attr" name="country" id="0x00010006" /> + + <public type="array" name="animals" id="0x02050000" /> +</resources> diff --git a/tests/SharedLibrary/lib/res/values/strings.xml b/tests/SharedLibrary/lib/res/values/strings.xml index bbfb0b4..6827f93 100644 --- a/tests/SharedLibrary/lib/res/values/strings.xml +++ b/tests/SharedLibrary/lib/res/values/strings.xml @@ -19,4 +19,13 @@ <string name="upgrade_body"><xliff:g id="app">%1$s</xliff:g> requires a newer version of <xliff:g id="lib">%2$s</xliff:g> to run.</string> <string name="upgrade_button">Upgrade</string> + <string name="shared_string">Shared string!</string> + + <string-array name="animals"> + <item>@string/racoon</item> + <item>Rhino</item> + <item>Elephant</item> + </string-array> + + <string name="racoon">Racoon</string> </resources> diff --git a/tests/SharedLibrary/lib/res/values/themes.xml b/tests/SharedLibrary/lib/res/values/themes.xml new file mode 100644 index 0000000..f1081ac --- /dev/null +++ b/tests/SharedLibrary/lib/res/values/themes.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <style name="CodeFont" parent="@android:style/TextAppearance.Medium"> + <item name="android:textColor">#00FF00</item> + <item name="android:typeface">monospace</item> + </style> + + <style name="Theme" parent="android:Theme.Holo.Light"> + <item name="android:actionBarStyle">@style/ActionBar</item> + </style> + + <style name="ActionBar" parent="android:Widget.Holo.Light.ActionBar.Solid.Inverse"> + <item name="android:background">@color/orange</item> + </style> + + <color name="orange">#f0ad4e</color> +</resources> diff --git a/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java new file mode 100644 index 0000000..dcaf68c --- /dev/null +++ b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java @@ -0,0 +1,44 @@ +package com.google.android.test.shared_library; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class AddressView extends LinearLayout { + private TextView mNameView; + private TextView mStreetView; + private TextView mCityStateZipView; + private TextView mCountryView; + + public AddressView(Context context, AttributeSet attrs) { + super(context, attrs); + setOrientation(VERTICAL); + + View view = LayoutInflater.from(context).inflate(R.layout.address, this); + mNameView = (TextView) view.findViewById(R.id.name); + mStreetView = (TextView) view.findViewById(R.id.street); + mCityStateZipView = (TextView) view.findViewById(R.id.cityStateZip); + mCountryView = (TextView) view.findViewById(R.id.country); + + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.AddressView, + 0, 0); + try { + mNameView.setText(a.getString(R.styleable.AddressView_name)); + int streetNumber = a.getInteger(R.styleable.AddressView_streetNumber, -1); + mStreetView.setText((streetNumber <= 0 ? "" : Integer.toString(streetNumber)) + + " " + a.getString(R.styleable.AddressView_streetName)); + mCityStateZipView.setText(a.getString(R.styleable.AddressView_city) + ", " + + a.getString(R.styleable.AddressView_state) + " " + + a.getString(R.styleable.AddressView_zip)); + mCountryView.setText(a.getString(R.styleable.AddressView_country)); + } finally { + a.recycle(); + } + } +} diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java index cceed16..3bd35a7 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java @@ -37,7 +37,7 @@ public class ActivityManagerPermissionTests extends TestCase { } @SmallTest - public void testREORDER_TASKS() { + public void testREORDER_TASKS() { try { mAm.moveTaskToFront(0, 0, null); fail("IActivityManager.moveTaskToFront did not throw SecurityException as" @@ -67,7 +67,7 @@ public class ActivityManagerPermissionTests extends TestCase { } catch (RemoteException e) { fail("Unexpected remote exception"); } - } + } @SmallTest public void testCHANGE_CONFIGURATION() { diff --git a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java index b690c45..93aa555 100644 --- a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java @@ -16,7 +16,7 @@ package com.android.framework.permission.tests; -import junit.framework.TestCase; +import android.app.PackageInstallObserver; import android.content.pm.PackageManager; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -68,10 +68,14 @@ public class PmPermissionsTests extends AndroidTestCase { * This test verifies that PackageManger.installPackage enforces permission * android.permission.INSTALL_PACKAGES */ + private class TestInstallObserver extends PackageInstallObserver { + } + @SmallTest public void testInstallPackage() { + TestInstallObserver observer = new TestInstallObserver(); try { - mPm.installPackage(null, null, 0, null); + mPm.installPackage(null, observer, 0, null); fail("PackageManager.installPackage" + "did not throw SecurityException as expected"); } catch (SecurityException e) { diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java index 4dfe0fe..322b853 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java @@ -32,7 +32,7 @@ import junit.framework.TestCase; */ public class ServiceManagerPermissionTests extends TestCase { @SmallTest - public void testAddService() { + public void testAddService() { try { // The security in the service manager is that you can't replace // a service that is already published. @@ -43,7 +43,7 @@ public class ServiceManagerPermissionTests extends TestCase { } catch (SecurityException e) { // expected } - } + } @SmallTest public void testSetPermissionController() { diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java index 90b6abc..b12ed94 100644 --- a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java +++ b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java @@ -18,6 +18,7 @@ package com.android.framework.permission.tests; import junit.framework.TestCase; +import android.media.AudioManager; import android.os.Binder; import android.os.IVibratorService; import android.os.Process; @@ -47,7 +48,8 @@ public class VibratorServicePermissionTest extends TestCase { */ public void testVibrate() throws RemoteException { try { - mVibratorService.vibrate(Process.myUid(), null, 2000, new Binder()); + mVibratorService.vibrate(Process.myUid(), null, 2000, AudioManager.STREAM_ALARM, + new Binder()); fail("vibrate did not throw SecurityException as expected"); } catch (SecurityException e) { // expected @@ -63,7 +65,8 @@ public class VibratorServicePermissionTest extends TestCase { */ public void testVibratePattern() throws RemoteException { try { - mVibratorService.vibratePattern(Process.myUid(), null, new long[] {0}, 0, new Binder()); + mVibratorService.vibratePattern(Process.myUid(), null, new long[] {0}, 0, + AudioManager.STREAM_ALARM, new Binder()); fail("vibratePattern did not throw SecurityException as expected"); } catch (SecurityException e) { // expected diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index df32ee1..6f5788a 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -41,7 +41,7 @@ public class WindowManagerPermissionTests extends TestCase { } @SmallTest - public void testMANAGE_APP_TOKENS() { + public void testMANAGE_APP_TOKENS() { try { mWm.pauseKeyDispatching(null); fail("IWindowManager.pauseKeyDispatching did not throw SecurityException as" |