diff options
Diffstat (limited to 'core/tests')
39 files changed, 1351 insertions, 1173 deletions
diff --git a/core/tests/bandwidthtests/Android.mk b/core/tests/bandwidthtests/Android.mk index 6871efd..cb44721 100644 --- a/core/tests/bandwidthtests/Android.mk +++ b/core/tests/bandwidthtests/Android.mk @@ -22,9 +22,9 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := \ $(call all-java-files-under, src) -LOCAL_JAVA_LIBRARIES := android.test.runner +LOCAL_JAVA_LIBRARIES := android.test.runner org.apache.http.legacy LOCAL_PACKAGE_NAME := BandwidthTests include $(BUILD_PACKAGE) -include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/core/tests/bandwidthtests/AndroidManifest.xml b/core/tests/bandwidthtests/AndroidManifest.xml index 24221bc..d0a6198 100644 --- a/core/tests/bandwidthtests/AndroidManifest.xml +++ b/core/tests/bandwidthtests/AndroidManifest.xml @@ -19,6 +19,7 @@ <application > <uses-library android:name="android.test.runner" /> + <uses-library android:name="org.apache.http.legacy" android:required="false" /> </application> <instrumentation diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java new file mode 100644 index 0000000..1a50432 --- /dev/null +++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015 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 android.net; + +import com.google.caliper.Param; +import com.google.caliper.SimpleBenchmark; + +public class NetworkStatsBenchmark extends SimpleBenchmark { + private static final String UNDERLYING_IFACE = "wlan0"; + private static final String TUN_IFACE = "tun0"; + private static final int TUN_UID = 999999999; + + @Param({"100", "1000"}) + private int mSize; + private NetworkStats mNetworkStats; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mNetworkStats = new NetworkStats(0, mSize + 2); + int uid = 0; + NetworkStats.Entry recycle = new NetworkStats.Entry(); + for (int i = 0; i < mSize; i++) { + recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE; + recycle.uid = uid; + recycle.set = i % 2; + recycle.tag = NetworkStats.TAG_NONE; + recycle.rxBytes = 60000; + recycle.rxPackets = 60; + recycle.txBytes = 150000; + recycle.txPackets = 1500; + recycle.operations = 0; + mNetworkStats.addValues(recycle); + if (recycle.set == 1) { + uid++; + } + } + recycle.iface = UNDERLYING_IFACE; + recycle.uid = TUN_UID; + recycle.set = NetworkStats.SET_FOREGROUND; + recycle.tag = NetworkStats.TAG_NONE; + recycle.rxBytes = 90000 * mSize; + recycle.rxPackets = 40 * mSize; + recycle.txBytes = 180000 * mSize; + recycle.txPackets = 1200 * mSize; + recycle.operations = 0; + mNetworkStats.addValues(recycle); + } + + public void timeMigrateTun(int reps) { + for (int i = 0; i < reps; i++) { + NetworkStats stats = mNetworkStats.clone(); + stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE); + } + } + + /** + * Since timeMigrateTun() includes a clone() call on the NetworkStats object, + * we need to measure the cost of the clone() call itself in order to get more + * accurate measurement on the migrateTun() method. + */ + public void timeClone(int reps) { + for (int i = 0; i < reps; i++) { + NetworkStats stats = mNetworkStats.clone(); + } + } +} diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk index 6bdeaf0..79a0b0c 100644 --- a/core/tests/coretests/Android.mk +++ b/core/tests/coretests/Android.mk @@ -24,7 +24,7 @@ LOCAL_SRC_FILES := \ LOCAL_DX_FLAGS := --core-library LOCAL_AAPT_FLAGS = -0 dat -0 gld LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock mockito-target -LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common +LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common org.apache.http.legacy LOCAL_PACKAGE_NAME := FrameworksCoreTests LOCAL_CERTIFICATE := platform diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index 226717e..b07d338 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -112,6 +112,10 @@ <application android:theme="@style/Theme"> <uses-library android:name="android.test.runner" /> + <uses-library android:name="org.apache.http.legacy" android:required="false" /> + <meta-data + android:name="android.content.APP_RESTRICTIONS" + android:resource="@xml/app_restrictions" /> <activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/core/tests/coretests/res/layout/size_adaptive.xml b/core/tests/coretests/res/layout/size_adaptive.xml deleted file mode 100644 index 03d0574..0000000 --- a/core/tests/coretests/res/layout/size_adaptive.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/multi1" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_color.xml b/core/tests/coretests/res/layout/size_adaptive_color.xml deleted file mode 100644 index cdb7a59..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_color.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:background="#ffffff" - android:id="@+id/multi1" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml b/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml deleted file mode 100644 index d24df5b..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_color_statelist.xml +++ /dev/null @@ -1,41 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:background="@drawable/size_adaptive_statelist" - android:id="@+id/multi1" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u.xml b/core/tests/coretests/res/layout/size_adaptive_four_u.xml deleted file mode 100644 index 232b921..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_four_u.xml +++ /dev/null @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/gridLayout4" - android:layout_width="match_parent" - android:layout_height="256dp" - android:background="#000000" - android:columnCount="2" - android:padding="1dp" > - - <ImageView - android:id="@+id/actor" - android:layout_width="62dp" - android:layout_height="62dp" - android:layout_row="0" - android:layout_column="0" - android:layout_rowSpan="2" - android:contentDescription="@string/actor" - android:src="@drawable/abe" /> - - <TextView - android:layout_width="0dp" - android:id="@+id/name" - android:layout_row="0" - android:layout_column="1" - android:layout_gravity="fill_horizontal" - android:padding="3dp" - android:text="@string/actor" - android:textColor="#ffffff" - android:textStyle="bold" /> - - <ImageView - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_row="1" - android:layout_column="1" - android:layout_gravity="fill_horizontal" - android:padding="5dp" - android:adjustViewBounds="true" - android:background="#555555" - android:scaleType="centerCrop" - android:src="@drawable/gettysburg" - android:contentDescription="@string/caption" /> - - <TextView - android:layout_width="0dp" - android:id="@+id/note" - android:layout_row="2" - android:layout_column="1" - android:layout_gravity="fill_horizontal" - android:padding="3dp" - android:singleLine="true" - android:text="@string/first" - android:textColor="#ffffff" /> -</GridLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml deleted file mode 100644 index 93a10de..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_four_u_text.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/gridLayout4" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="#000000" - android:columnCount="2" - android:padding="1dp" - android:orientation="horizontal" > - - <ImageView - android:id="@+id/actor" - android:layout_width="62dp" - android:layout_height="62dp" - android:layout_row="0" - android:layout_column="0" - android:layout_rowSpan="2" - android:contentDescription="@string/actor" - android:src="@drawable/abe" /> - - <TextView - android:layout_width="0dp" - android:id="@+id/name" - android:layout_row="0" - android:layout_column="1" - android:layout_gravity="fill_horizontal" - android:padding="3dp" - android:text="@string/actor" - android:textColor="#ffffff" - android:textStyle="bold" /> - - <TextView - android:id="@+id/note" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_column="1" - android:layout_gravity="fill_horizontal" - android:layout_marginTop="5dp" - android:layout_row="1" - android:padding="3dp" - android:singleLine="false" - android:text="@string/first" - android:textColor="#ffffff" /> - - </GridLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_gappy.xml b/core/tests/coretests/res/layout/size_adaptive_gappy.xml deleted file mode 100644 index d5e3b41..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_gappy.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/multi_with_gap" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="256dp" - internal:layout_minHeight="128dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_large_only.xml b/core/tests/coretests/res/layout/size_adaptive_large_only.xml deleted file mode 100644 index cf58265..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_large_only.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/large_only_multi" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="256dp" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_lies.xml b/core/tests/coretests/res/layout/size_adaptive_lies.xml deleted file mode 100644 index 7de892e..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_lies.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/multi1" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u.xml b/core/tests/coretests/res/layout/size_adaptive_one_u.xml deleted file mode 100644 index b6fe4a0..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_one_u.xml +++ /dev/null @@ -1,66 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/gridLayout1" - android:layout_width="match_parent" - android:layout_height="64dp" - android:background="#000000" - android:columnCount="3" - android:padding="1dp" - android:rowCount="2" > - - <ImageView - android:id="@+id/actor" - android:layout_width="62dp" - android:layout_height="62dp" - android:layout_column="0" - android:layout_row="0" - android:layout_rowSpan="2" - android:contentDescription="@string/actor" - android:src="@drawable/abe" /> - - <TextView - android:id="@+id/name" - android:layout_gravity="fill" - android:padding="3dp" - android:text="@string/actor" - android:textColor="#ffffff" - android:textStyle="bold" /> - - <ImageView - android:layout_width="62dp" - android:layout_height="62dp" - android:layout_gravity="fill_vertical" - android:layout_rowSpan="2" - android:adjustViewBounds="true" - android:background="#555555" - android:padding="2dp" - android:scaleType="fitXY" - android:src="@drawable/gettysburg" - android:contentDescription="@string/caption" /> - - <TextView - android:id="@+id/note" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_gravity="fill" - android:layout_marginTop="5dp" - android:padding="3dp" - android:singleLine="true" - android:text="@string/first" - android:textColor="#ffffff" /> - -</GridLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml b/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml deleted file mode 100644 index df54eb6..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_one_u_text.xml +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/gridLayout1" - android:layout_width="match_parent" - android:layout_height="64dp" - android:background="#000000" - android:columnCount="2" - android:padding="1dp" - android:rowCount="2" > - - <ImageView - android:id="@+id/actor" - android:layout_width="62dp" - android:layout_height="62dp" - android:layout_column="0" - android:layout_row="0" - android:layout_rowSpan="2" - android:contentDescription="@string/actor" - android:src="@drawable/abe" /> - - <TextView - android:id="@+id/name" - android:layout_gravity="fill" - android:padding="3dp" - android:text="@string/actor" - android:textColor="#ffffff" - android:textStyle="bold" /> - - <TextView - android:id="@+id/note" - android:layout_width="0dp" - android:layout_height="0dp" - android:layout_gravity="fill" - android:layout_marginTop="5dp" - android:padding="3dp" - android:singleLine="true" - android:text="@string/first" - android:textColor="#ffffff" /> - -</GridLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml b/core/tests/coretests/res/layout/size_adaptive_overlapping.xml deleted file mode 100644 index 4abe8b0..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_overlapping.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/multi_with_overlap" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="256dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="256dp"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_singleton.xml b/core/tests/coretests/res/layout/size_adaptive_singleton.xml deleted file mode 100644 index eba387f..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_singleton.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u_text" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_text.xml b/core/tests/coretests/res/layout/size_adaptive_text.xml deleted file mode 100644 index a9f0ba9..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_text.xml +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/multi1" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u_text" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u_text" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/layout/size_adaptive_three_way.xml b/core/tests/coretests/res/layout/size_adaptive_three_way.xml deleted file mode 100644 index 1eb5396..0000000 --- a/core/tests/coretests/res/layout/size_adaptive_three_way.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<com.android.internal.widget.SizeAdaptiveLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:internal="http://schemas.android.com/apk/prv/res/android" - android:id="@+id/three_way_multi" - android:layout_width="match_parent" - android:layout_height="64dp" > - - <include - android:id="@+id/one_u" - layout="@layout/size_adaptive_one_u" - android:layout_width="fill_parent" - android:layout_height="64dp" - internal:layout_minHeight="64dp" - internal:layout_maxHeight="64dp" - /> - - <include - android:id="@+id/two_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="128dp" - internal:layout_minHeight="65dp" - internal:layout_maxHeight="128dp"/> - - <include - android:id="@+id/four_u" - layout="@layout/size_adaptive_four_u" - android:layout_width="fill_parent" - android:layout_height="256dp" - internal:layout_minHeight="129dp" - internal:layout_maxHeight="unbounded"/> - -</com.android.internal.widget.SizeAdaptiveLayout> diff --git a/core/tests/coretests/res/values/strings.xml b/core/tests/coretests/res/values/strings.xml index ce0d9a2..04b0478 100644 --- a/core/tests/coretests/res/values/strings.xml +++ b/core/tests/coretests/res/values/strings.xml @@ -135,4 +135,8 @@ <string name="first">Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.</string> <string name="actor">Abe Lincoln</string> <string name="caption">Lincoln adressing the crowd at Gettysburgh</string> + + <!-- RestrictionsManagerTest --> + <string name="restrictionManager_title">Title</string> + <string name="restrictionManager_desc">Description</string> </resources> diff --git a/core/tests/coretests/res/xml/app_restrictions.xml b/core/tests/coretests/res/xml/app_restrictions.xml new file mode 100644 index 0000000..c84cabc --- /dev/null +++ b/core/tests/coretests/res/xml/app_restrictions.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2015 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. +--> + +<restrictions xmlns:android="http://schemas.android.com/apk/res/android"> + <restriction android:key="hidden_key" + android:restrictionType="hidden"/> + <restriction + android:defaultValue="true" + android:description="@string/restrictionManager_desc" + android:key="bool_key" + android:restrictionType="bool" + android:title="@string/restrictionManager_title"/> + <restriction + android:defaultValue="test" + android:key="string_key" + android:restrictionType="string"/> + + <restriction android:key="int_key" + android:restrictionType="integer" + android:defaultValue="15"/> + <restriction android:key="bundle_key" + android:restrictionType="bundle"> + <restriction + android:key="bundle_string_key" + android:restrictionType="string"/> + <restriction + android:defaultValue="true" + android:key="bundle_bool_key" + android:restrictionType="bool"/> + + </restriction> + <restriction android:key="bundle_array_key" + android:restrictionType="bundle_array"> + <restriction android:key="bundle_array_int" + android:restrictionType="integer"/> + <restriction android:key="bundle_array_bundle_key" + android:restrictionType="bundle"> + <restriction android:key="bundle_array_bundle_int_key" + android:restrictionType="integer"/> + </restriction> + </restriction> +</restrictions>
\ No newline at end of file diff --git a/core/tests/coretests/src/android/content/RestrictionsManagerTest.java b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java new file mode 100644 index 0000000..8921924 --- /dev/null +++ b/core/tests/coretests/src/android/content/RestrictionsManagerTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 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 android.content; + +import android.os.Bundle; +import android.os.Parcelable; +import android.test.AndroidTestCase; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class RestrictionsManagerTest extends AndroidTestCase { + private RestrictionsManager mRm; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mRm = (RestrictionsManager) mContext.getSystemService(Context.RESTRICTIONS_SERVICE); + } + + public void testGetManifestRestrictions() { + String packageName = getContext().getPackageName(); + List<RestrictionEntry> manifestRestrictions = mRm.getManifestRestrictions(packageName); + assertEquals(6, manifestRestrictions.size()); + Set<String> verifiedKeys = new HashSet<>(Arrays.asList("bundle_key", "bundle_array_key", + "bundle_array_bundle_key")); + for (RestrictionEntry entry : manifestRestrictions) { + if ("bundle_key".equals(entry.getKey())) { + assertEquals("bundle_key entry should have 2 children entries", + 2, entry.getRestrictions().length); + verifiedKeys.remove(entry.getKey()); + } else if ("bundle_array_key".equals(entry.getKey())) { + assertEquals("bundle_array_key should have 2 children entries", + 2, entry.getRestrictions().length); + assertNotNull(entry.getRestrictions()); + for (RestrictionEntry childEntry : entry.getRestrictions()) { + if ("bundle_array_bundle_key".equals(childEntry.getKey())) { + assertNotNull(childEntry.getRestrictions()); + assertEquals("bundle_array_bundle_key should have 1 child entry", + 1, childEntry.getRestrictions().length); + verifiedKeys.remove(childEntry.getKey()); + } + } + verifiedKeys.remove(entry.getKey()); + } + } + assertTrue("Entries" + verifiedKeys + " were not found", verifiedKeys.isEmpty()); + } + + public void testConvertRestrictionsToBundle() { + String packageName = getContext().getPackageName(); + List<RestrictionEntry> manifestRestrictions = mRm.getManifestRestrictions(packageName); + Bundle bundle = RestrictionsManager.convertRestrictionsToBundle(manifestRestrictions); + assertEquals(6, bundle.size()); + Bundle childBundle = bundle.getBundle("bundle_key"); + assertNotNull(childBundle); + assertEquals(2, childBundle.size()); + Parcelable[] childBundleArray = bundle.getParcelableArray("bundle_array_key"); + assertEquals(2, childBundleArray.length); + } + +} diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index a59581b..279bfbf 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -576,14 +576,6 @@ public class PackageManagerTests extends AndroidTestCase { fail(pkgName + " shouldnt be installed"); } catch (NameNotFoundException e) { } - - UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - List<UserInfo> users = um.getUsers(); - for (UserInfo user : users) { - String dataDir = PackageManager.getDataDirForUser(user.id, pkgName); - assertFalse("Application data directory should not exist: " + dataDir, - new File(dataDir).exists()); - } } class InstallParams { diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java new file mode 100644 index 0000000..32b4557 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java @@ -0,0 +1,377 @@ +/* + * Copyright (C) 2015 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 android.content.pm; + +import android.content.res.Resources; +import android.os.FileUtils; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.UserHandle; +import android.test.AndroidTestCase; +import android.util.AttributeSet; +import android.util.SparseArray; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Tests for {@link android.content.pm.RegisteredServicesCache} + */ +public class RegisteredServicesCacheTest extends AndroidTestCase { + private static final int U0 = 0; + private static final int U1 = 1; + private static final int UID1 = 1; + private static final int UID2 = 2; + // Represents UID of a system image process + private static final int SYSTEM_IMAGE_UID = 20; + + private final ResolveInfo r1 = new ResolveInfo(); + private final ResolveInfo r2 = new ResolveInfo(); + private final TestServiceType t1 = new TestServiceType("t1", "value1"); + private final TestServiceType t2 = new TestServiceType("t2", "value2"); + private File mDataDir; + private File mSyncDir; + private List<UserInfo> mUsers; + + @Override + protected void setUp() throws Exception { + super.setUp(); + File cacheDir = mContext.getCacheDir(); + mDataDir = new File(cacheDir, "testServicesCache"); + FileUtils.deleteContents(mDataDir); + mSyncDir = new File(mDataDir, "system/"+RegisteredServicesCache.REGISTERED_SERVICES_DIR); + mSyncDir.mkdirs(); + mUsers = new ArrayList<>(); + mUsers.add(new UserInfo(0, "Owner", UserInfo.FLAG_ADMIN)); + mUsers.add(new UserInfo(1, "User1", 0)); + } + + public void testGetAllServicesHappyPath() { + TestServicesCache cache = new TestServicesCache(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2)); + assertEquals(2, cache.getAllServicesSize(U0)); + assertEquals(2, cache.getPersistentServicesSize(U0)); + assertNotEmptyFileCreated(cache, U0); + // Make sure all services can be loaded from xml + cache = new TestServicesCache(); + assertEquals(2, cache.getPersistentServicesSize(U0)); + } + + public void testGetAllServicesReplaceUid() { + TestServicesCache cache = new TestServicesCache(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2)); + cache.getAllServices(U0); + // Invalidate cache and clear update query results + cache.invalidateCache(U0); + cache.clearServicesForQuerying(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, SYSTEM_IMAGE_UID)); + Collection<RegisteredServicesCache.ServiceInfo<TestServiceType>> allServices = cache + .getAllServices(U0); + assertEquals(2, allServices.size()); + Set<Integer> uids = new HashSet<>(); + for (RegisteredServicesCache.ServiceInfo<TestServiceType> srv : allServices) { + uids.add(srv.uid); + } + assertTrue("UID must be updated to the new value", + uids.contains(SYSTEM_IMAGE_UID)); + assertFalse("UID must be updated to the new value", uids.contains(UID2)); + } + + public void testGetAllServicesServiceRemoved() { + TestServicesCache cache = new TestServicesCache(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2)); + assertEquals(2, cache.getAllServicesSize(U0)); + assertEquals(2, cache.getPersistentServicesSize(U0)); + // Re-read data from disk and verify services were saved + cache = new TestServicesCache(); + assertEquals(2, cache.getPersistentServicesSize(U0)); + // Now register only one service and verify that another one is removed + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + assertEquals(1, cache.getAllServicesSize(U0)); + assertEquals(1, cache.getPersistentServicesSize(U0)); + } + + public void testGetAllServicesMultiUser() { + TestServicesCache cache = new TestServicesCache(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + int u1uid = UserHandle.getUid(U1, 0); + cache.addServiceForQuerying(U1, r2, newServiceInfo(t2, u1uid)); + assertEquals(1, cache.getAllServicesSize(U0)); + assertEquals(1, cache.getPersistentServicesSize(U0)); + assertEquals(1, cache.getAllServicesSize(U1)); + assertEquals(1, cache.getPersistentServicesSize(U1)); + assertEquals("No services should be available for user 3", 0, cache.getAllServicesSize(3)); + // Re-read data from disk and verify services were saved + cache = new TestServicesCache(); + assertEquals(1, cache.getPersistentServicesSize(U0)); + assertEquals(1, cache.getPersistentServicesSize(U1)); + assertNotEmptyFileCreated(cache, U0); + assertNotEmptyFileCreated(cache, U1); + } + + public void testOnRemove() { + TestServicesCache cache = new TestServicesCache(); + cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1)); + int u1uid = UserHandle.getUid(U1, 0); + cache.addServiceForQuerying(U1, r2, newServiceInfo(t2, u1uid)); + assertEquals(1, cache.getAllServicesSize(U0)); + assertEquals(1, cache.getAllServicesSize(U1)); + // Simulate ACTION_USER_REMOVED + cache.onUserRemoved(U1); + // Make queryIntentServices(u1) return no results for U1 + cache.clearServicesForQuerying(); + assertEquals(1, cache.getAllServicesSize(U0)); + assertEquals(0, cache.getAllServicesSize(U1)); + } + + public void testMigration() { + // Prepare "old" file for testing + String oldFile = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + + "<services>\n" + + " <service uid=\"1\" type=\"type1\" value=\"value1\" />\n" + + " <service uid=\"100002\" type=\"type2\" value=\"value2\" />\n" + + "<services>\n"; + + File file = new File(mSyncDir, TestServicesCache.SERVICE_INTERFACE + ".xml"); + FileUtils.copyToFile(new ByteArrayInputStream(oldFile.getBytes()), file); + + int u0 = 0; + int u1 = 1; + TestServicesCache cache = new TestServicesCache(); + assertEquals(1, cache.getPersistentServicesSize(u0)); + assertEquals(1, cache.getPersistentServicesSize(u1)); + assertNotEmptyFileCreated(cache, u0); + assertNotEmptyFileCreated(cache, u1); + // Check that marker was created + File markerFile = new File(mSyncDir, TestServicesCache.SERVICE_INTERFACE + ".xml.migrated"); + assertTrue("Marker file should be created at " + markerFile, markerFile.exists()); + // Now introduce 2 service types for u0: t1, t2. type1 will be removed + cache.addServiceForQuerying(0, r1, newServiceInfo(t1, 1)); + cache.addServiceForQuerying(0, r2, newServiceInfo(t2, 2)); + assertEquals(2, cache.getAllServicesSize(u0)); + assertEquals(0, cache.getAllServicesSize(u1)); + // Re-read data from disk. Verify that services were saved and old file was ignored + cache = new TestServicesCache(); + assertEquals(2, cache.getPersistentServicesSize(u0)); + assertEquals(0, cache.getPersistentServicesSize(u1)); + } + + private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo( + TestServiceType type, int uid) { + return new RegisteredServicesCache.ServiceInfo<>(type, null, uid); + } + + private void assertNotEmptyFileCreated(TestServicesCache cache, int userId) { + File dir = new File(cache.getUserSystemDirectory(userId), + RegisteredServicesCache.REGISTERED_SERVICES_DIR); + File file = new File(dir, TestServicesCache.SERVICE_INTERFACE+".xml"); + assertTrue("File should be created at " + file, file.length() > 0); + } + + /** + * Mock implementation of {@link android.content.pm.RegisteredServicesCache} for testing + */ + private class TestServicesCache extends RegisteredServicesCache<TestServiceType> { + static final String SERVICE_INTERFACE = "RegisteredServicesCacheTest"; + static final String SERVICE_META_DATA = "RegisteredServicesCacheTest"; + static final String ATTRIBUTES_NAME = "test"; + private SparseArray<Map<ResolveInfo, ServiceInfo<TestServiceType>>> mServices + = new SparseArray<>(); + + public TestServicesCache() { + super(RegisteredServicesCacheTest.this.mContext, + SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, new TestSerializer()); + } + + @Override + public TestServiceType parseServiceAttributes(Resources res, String packageName, + AttributeSet attrs) { + return null; + } + + @Override + protected List<ResolveInfo> queryIntentServices(int userId) { + Map<ResolveInfo, ServiceInfo<TestServiceType>> map = mServices + .get(userId, new HashMap<ResolveInfo, ServiceInfo<TestServiceType>>()); + return new ArrayList<>(map.keySet()); + } + + @Override + protected File getUserSystemDirectory(int userId) { + File dir = new File(mDataDir, "users/" + userId); + dir.mkdirs(); + return dir; + } + + @Override + protected List<UserInfo> getUsers() { + return mUsers; + } + + @Override + protected UserInfo getUser(int userId) { + for (UserInfo user : getUsers()) { + if (user.id == userId) { + return user; + } + } + return null; + } + + @Override + protected File getDataDirectory() { + return mDataDir; + } + + void addServiceForQuerying(int userId, ResolveInfo resolveInfo, + ServiceInfo<TestServiceType> serviceInfo) { + Map<ResolveInfo, ServiceInfo<TestServiceType>> map = mServices.get(userId); + if (map == null) { + map = new HashMap<>(); + mServices.put(userId, map); + } + map.put(resolveInfo, serviceInfo); + } + + void clearServicesForQuerying() { + mServices.clear(); + } + + int getPersistentServicesSize(int user) { + return getPersistentServices(user).size(); + } + + int getAllServicesSize(int user) { + return getAllServices(user).size(); + } + + @Override + protected boolean inSystemImage(int callerUid) { + return callerUid == SYSTEM_IMAGE_UID; + } + + @Override + protected ServiceInfo<TestServiceType> parseServiceInfo( + ResolveInfo resolveInfo) throws XmlPullParserException, IOException { + int size = mServices.size(); + for (int i = 0; i < size; i++) { + Map<ResolveInfo, ServiceInfo<TestServiceType>> map = mServices.valueAt(i); + ServiceInfo<TestServiceType> serviceInfo = map.get(resolveInfo); + if (serviceInfo != null) { + return serviceInfo; + } + } + throw new IllegalArgumentException("Unexpected service " + resolveInfo); + } + + @Override + public void onUserRemoved(int userId) { + super.onUserRemoved(userId); + } + } + + static class TestSerializer implements XmlSerializerAndParser<TestServiceType> { + + public void writeAsXml(TestServiceType item, XmlSerializer out) throws IOException { + out.attribute(null, "type", item.type); + out.attribute(null, "value", item.value); + } + + public TestServiceType createFromXml(XmlPullParser parser) + throws IOException, XmlPullParserException { + final String type = parser.getAttributeValue(null, "type"); + final String value = parser.getAttributeValue(null, "value"); + return new TestServiceType(type, value); + } + } + + static class TestServiceType implements Parcelable { + final String type; + final String value; + + public TestServiceType(String type, String value) { + this.type = type; + this.value = value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TestServiceType that = (TestServiceType) o; + + return type.equals(that.type) && value.equals(that.value); + } + + @Override + public int hashCode() { + return 31 * type.hashCode() + value.hashCode(); + } + + @Override + public String toString() { + return "TestServiceType{" + + "type='" + type + '\'' + + ", value='" + value + '\'' + + '}'; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(type); + dest.writeString(value); + } + + public TestServiceType(Parcel source) { + this(source.readString(), source.readString()); + } + + public static final Creator<TestServiceType> CREATOR = new Creator<TestServiceType>() { + public TestServiceType createFromParcel(Parcel source) { + return new TestServiceType(source); + } + + public TestServiceType[] newArray(int size) { + return new TestServiceType[size]; + } + }; + } +} diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index 9ee4e20..a470de1 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -18,6 +18,8 @@ package android.net; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.SET_DBG_VPN_IN; +import static android.net.NetworkStats.SET_DBG_VPN_OUT; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.TAG_NONE; @@ -320,6 +322,92 @@ public class NetworkStatsTest extends TestCase { red.combineAllValues(blue); } + public void testMigrateTun() throws Exception { + final int tunUid = 10030; + final String tunIface = "tun0"; + final String underlyingIface = "wlan0"; + final int testTag1 = 8888; + NetworkStats delta = new NetworkStats(TEST_START, 17) + .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, 39605L, 46L, 12259L, 55L, 0L) + .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, 72667L, 197L, 43909L, 241L, 0L) + .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, 9297L, 17L, 4128L, 21L, 0L) + // VPN package also uses some traffic through unprotected network. + .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, 4983L, 10L, 1801L, 12L, 0L) + .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + // Tag entries + .addValues(tunIface, 10120, SET_DEFAULT, testTag1, 21691L, 41L, 13820L, 51L, 0L) + .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L) + // Irrelevant entries + .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L) + // Underlying Iface entries + .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, 5178L, 8L, 2139L, 11L, 0L) + .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L) + .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, 149873L, 287L, + 59217L /* smaller than sum(tun0) */, 299L /* smaller than sum(tun0) */, 0L) + .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); + + assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface)); + assertEquals(21, delta.size()); + + // tunIface and TEST_IFACE entries are not changed. + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, + 39605L, 46L, 12259L, 55L, 0L); + assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); + assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, + 72667L, 197L, 43909L, 241L, 0L); + assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, + 9297L, 17L, 4128L, 21L, 0L); + assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, + 4983L, 10L, 1801L, 12L, 0L); + assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); + assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, + 21691L, 41L, 13820L, 51L, 0L); + assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L); + assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L); + + // Existing underlying Iface entries are updated + assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, + 44783L, 54L, 13829L, 60L, 0L); + assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, + 0L, 0L, 0L, 0L, 0L); + + // VPN underlying Iface entries are updated + assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, + 28304L, 27L, 1719L, 12L, 0L); + assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, + 0L, 0L, 0L, 0L, 0L); + + // New entries are added for new application's underlying Iface traffic + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, + 72667L, 197L, 41872l, 219L, 0L); + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, + 9297L, 17L, 3936, 19L, 0L); + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, + 21691L, 41L, 13179L, 46L, 0L); + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, + 1281L, 2L, 634L, 1L, 0L); + + // New entries are added for debug purpose + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, + 39605L, 46L, 11690, 49, 0); + assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, + 81964, 214, 45808, 238, 0); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, + 4983, 10, 1717, 10, 0); + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, + 126552, 270, 59215, 297, 0); + + } + + private static void assertContains(NetworkStats stats, String iface, int uid, int set, + int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int index = stats.findIndex(iface, uid, set, tag); + assertTrue(index != -1); + assertValues(stats, index, iface, uid, set, tag, + rxBytes, rxPackets, txBytes, txPackets, operations); + } + private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { final NetworkStats.Entry entry = stats.getValues(index, null); diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/core/tests/coretests/src/android/net/NetworkUtilsTest.java new file mode 100644 index 0000000..8d51c3b --- /dev/null +++ b/core/tests/coretests/src/android/net/NetworkUtilsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 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 android.net; + +import android.net.NetworkUtils; +import android.test.suitebuilder.annotation.SmallTest; + +import java.net.Inet4Address; +import java.net.InetAddress; + +import junit.framework.TestCase; + +public class NetworkUtilsTest extends TestCase { + + private InetAddress Address(String addr) { + return InetAddress.parseNumericAddress(addr); + } + + private Inet4Address IPv4Address(String addr) { + return (Inet4Address) Address(addr); + } + + @SmallTest + public void testGetImplicitNetmask() { + assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2"))); + assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7"))); + assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105"))); + assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145"))); + assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1"))); + assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1"))); + assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1"))); + assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8"))); + } + + private void assertInvalidNetworkMask(Inet4Address addr) { + try { + NetworkUtils.netmaskToPrefixLength(addr); + fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception"); + } catch (IllegalArgumentException expected) { + } + } + + @SmallTest + public void testNetmaskToPrefixLength() { + assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0"))); + assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0"))); + assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0"))); + assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0"))); + assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254"))); + assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255"))); + + assertInvalidNetworkMask(IPv4Address("0.0.0.1")); + assertInvalidNetworkMask(IPv4Address("255.255.255.253")); + assertInvalidNetworkMask(IPv4Address("255.255.0.255")); + } +} diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java deleted file mode 100644 index 18411b0..0000000 --- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.widget; - -import com.android.frameworks.coretests.R; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; -import android.view.LayoutInflater; -import android.view.View; - -import com.android.internal.widget.SizeAdaptiveLayout; - - -public class SizeAdaptiveLayoutTest extends AndroidTestCase { - - private LayoutInflater mInflater; - private int mOneU; - private int mFourU; - private SizeAdaptiveLayout mSizeAdaptiveLayout; - private View mSmallView; - private View mMediumView; - private View mLargeView; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - // inflate the layout - final Context context = getContext(); - mInflater = LayoutInflater.from(context); - mOneU = 64; - mFourU = 4 * mOneU; - } - - private void inflate(int resource){ - mSizeAdaptiveLayout = (SizeAdaptiveLayout) mInflater.inflate(resource, null); - mSizeAdaptiveLayout.onAttachedToWindow(); - - mSmallView = mSizeAdaptiveLayout.findViewById(R.id.one_u); - mMediumView = mSizeAdaptiveLayout.findViewById(R.id.two_u); - mLargeView = mSizeAdaptiveLayout.findViewById(R.id.four_u); - } - - /** - * The name 'test preconditions' is a convention to signal that if this - * test doesn't pass, the test case was not set up properly and it might - * explain any and all failures in other tests. This is not guaranteed - * to run before other tests, as junit uses reflection to find the tests. - */ - @SmallTest - public void testPreconditions() { - assertNotNull(mInflater); - - inflate(R.layout.size_adaptive); - assertNotNull(mSizeAdaptiveLayout); - assertNotNull(mSmallView); - assertNotNull(mLargeView); - } - - @SmallTest - public void testOpenLarge() { - inflate(R.layout.size_adaptive); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight + 10; - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertEquals("1U should be gone", - View.GONE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenSmall() { - inflate(R.layout.size_adaptive); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - assertEquals("4U should be gone", - View.GONE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenTooSmall() { - inflate(R.layout.size_adaptive); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight - 10; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - assertEquals("4U should be gone", - View.GONE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenTooBig() { - inflate(R.layout.size_adaptive); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - lp.maxHeight = 500; - mLargeView.setLayoutParams(lp); - int height = (int) (lp.minHeight + 10); - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertEquals("1U should be gone", - View.GONE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenWrapContent() { - inflate(R.layout.size_adaptive_text); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight + 10; - - // manually measure it, and lay it out - int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST); - mSizeAdaptiveLayout.measure(500, measureSpec); - assertTrue("should not be forced to 4U", - mSizeAdaptiveLayout.getMeasuredHeight() < mFourU); - } - - @SmallTest - public void testOpenOneUOnlySmall() { - inflate(R.layout.size_adaptive_singleton); - assertNull("largeView should be NULL in the singleton layout", mLargeView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight - 10; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenOneUOnlyLarge() { - inflate(R.layout.size_adaptive_singleton); - assertNull("largeView should be NULL in the singleton layout", mLargeView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.maxHeight + 10; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenOneUOnlyJustRight() { - inflate(R.layout.size_adaptive_singleton); - assertNull("largeView should be NULL in the singleton layout", mLargeView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenFourUOnlySmall() { - inflate(R.layout.size_adaptive_large_only); - assertNull("smallView should be NULL in the singleton layout", mSmallView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight - 10; - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenFourUOnlyLarge() { - inflate(R.layout.size_adaptive_large_only); - assertNull("smallView should be NULL in the singleton layout", mSmallView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.maxHeight + 10; - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenFourUOnlyJustRight() { - inflate(R.layout.size_adaptive_large_only); - assertNull("smallView should be NULL in the singleton layout", mSmallView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenIntoAGap() { - inflate(R.layout.size_adaptive_gappy); - - SizeAdaptiveLayout.LayoutParams smallParams = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - SizeAdaptiveLayout.LayoutParams largeParams = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - assertTrue("gappy layout should have a gap", - smallParams.maxHeight + 10 < largeParams.minHeight); - int height = (int) smallParams.maxHeight + 10; - - measureAndLayout(height); - - assertTrue("one and only one view should be visible", - mLargeView.getVisibility() != mSmallView.getVisibility()); - // behavior is undefined in this case. - } - - @SmallTest - public void testOpenIntoAnOverlap() { - inflate(R.layout.size_adaptive_overlapping); - - SizeAdaptiveLayout.LayoutParams smallParams = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - SizeAdaptiveLayout.LayoutParams largeParams = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - assertEquals("overlapping layout should overlap", - smallParams.minHeight, - largeParams.minHeight); - int height = (int) smallParams.maxHeight; - - measureAndLayout(height); - - assertTrue("one and only one view should be visible", - mLargeView.getVisibility() != mSmallView.getVisibility()); - assertEquals("1U should get priority in an overlap because it is first", - View.VISIBLE, - mSmallView.getVisibility()); - } - - @SmallTest - public void testOpenThreeWayViewSmall() { - inflate(R.layout.size_adaptive_three_way); - assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - assertEquals("2U should be gone", - View.GONE, - mMediumView.getVisibility()); - assertEquals("4U should be gone", - View.GONE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenThreeWayViewMedium() { - inflate(R.layout.size_adaptive_three_way); - assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mMediumView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be gone", - View.GONE, - mSmallView.getVisibility()); - assertEquals("2U should be visible", - View.VISIBLE, - mMediumView.getVisibility()); - assertEquals("4U should be gone", - View.GONE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testOpenThreeWayViewLarge() { - inflate(R.layout.size_adaptive_three_way); - assertNotNull("mMediumView should not be NULL in the three view layout", mMediumView); - - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be gone", - View.GONE, - mSmallView.getVisibility()); - assertEquals("2U should be gone", - View.GONE, - mMediumView.getVisibility()); - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - } - - @SmallTest - public void testResizeWithoutAnimation() { - inflate(R.layout.size_adaptive); - - SizeAdaptiveLayout.LayoutParams largeParams = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int startHeight = (int) largeParams.minHeight + 10; - int endHeight = (int) largeParams.minHeight + 10; - - measureAndLayout(startHeight); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertFalse("There should be no animation on initial rendering.", - mSizeAdaptiveLayout.getTransitionAnimation().isRunning()); - - measureAndLayout(endHeight); - - assertEquals("4U should still be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertFalse("There should be no animation on scale within a view.", - mSizeAdaptiveLayout.getTransitionAnimation().isRunning()); - } - - @SmallTest - public void testResizeWithAnimation() { - inflate(R.layout.size_adaptive); - - SizeAdaptiveLayout.LayoutParams smallParams = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - SizeAdaptiveLayout.LayoutParams largeParams = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int startHeight = (int) largeParams.minHeight + 10; - int endHeight = (int) smallParams.maxHeight; - - measureAndLayout(startHeight); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertFalse("There should be no animation on initial rendering.", - mSizeAdaptiveLayout.getTransitionAnimation().isRunning()); - - measureAndLayout(endHeight); - - assertEquals("1U should now be visible", - View.VISIBLE, - mSmallView.getVisibility()); - assertTrue("There should be an animation on scale between views.", - mSizeAdaptiveLayout.getTransitionAnimation().isRunning()); - } - - @SmallTest - public void testModestyPanelChangesColorWhite() { - inflate(R.layout.size_adaptive_color); - View panel = mSizeAdaptiveLayout.getModestyPanel(); - assertTrue("ModestyPanel should have a ColorDrawable background", - panel.getBackground() instanceof ColorDrawable); - ColorDrawable panelColor = (ColorDrawable) panel.getBackground(); - ColorDrawable salColor = (ColorDrawable) mSizeAdaptiveLayout.getBackground(); - assertEquals("ModestyPanel color should match the SizeAdaptiveLayout", - panelColor.getColor(), salColor.getColor()); - } - - @SmallTest - public void testModestyPanelTracksStateListColor() { - inflate(R.layout.size_adaptive_color_statelist); - View panel = mSizeAdaptiveLayout.getModestyPanel(); - assertEquals("ModestyPanel should have a ColorDrawable background" , - panel.getBackground().getClass(), ColorDrawable.class); - ColorDrawable panelColor = (ColorDrawable) panel.getBackground(); - assertEquals("ModestyPanel color should match the SizeAdaptiveLayout", - panelColor.getColor(), Color.RED); - } - @SmallTest - public void testOpenSmallEvenWhenLargeIsActuallySmall() { - inflate(R.layout.size_adaptive_lies); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mSmallView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("1U should be visible", - View.VISIBLE, - mSmallView.getVisibility()); - assertTrue("1U should also have been measured", - mSmallView.getMeasuredHeight() > 0); - } - - @SmallTest - public void testOpenLargeEvenWhenLargeIsActuallySmall() { - inflate(R.layout.size_adaptive_lies); - SizeAdaptiveLayout.LayoutParams lp = - (SizeAdaptiveLayout.LayoutParams) mLargeView.getLayoutParams(); - int height = (int) lp.minHeight; - - measureAndLayout(height); - - assertEquals("4U should be visible", - View.VISIBLE, - mLargeView.getVisibility()); - assertTrue("4U should also have been measured", - mLargeView.getMeasuredHeight() > 0); - } - - private void measureAndLayout(int height) { - // manually measure it, and lay it out - int measureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST); - mSizeAdaptiveLayout.measure(500, measureSpec); - mSizeAdaptiveLayout.layout(0, 0, 500, mSizeAdaptiveLayout.getMeasuredHeight()); - } -} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk index 7839d26..78e718f 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk @@ -27,18 +27,30 @@ LOCAL_SDK_VERSION := current LOCAL_PACKAGE_NAME := MultiDexLegacyAndException +LOCAL_DEX_PREOPT := false + mainDexList:= \ - $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list + $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/multidexlegacyandexception/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList) - +endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp new file mode 100644 index 0000000..0d027ed --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp @@ -0,0 +1,3 @@ +test: + @@com.android.jack.annotations.ForceInMainDex + class com.android.multidexlegacyandexception.Test diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk index e2ab1a8..7c699b6 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk @@ -27,21 +27,33 @@ LOCAL_SDK_VERSION := current LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp +LOCAL_DEX_PREOPT := false + mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/multidexlegacytestapp/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList) - +endif ## The application with a full main dex include $(CLEAR_VARS) @@ -56,17 +68,30 @@ LOCAL_SDK_VERSION := current LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2 +LOCAL_DEX_PREOPT := false + mainDexList2:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2) +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList2): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/multidexlegacytestapp/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList2) +endif
\ No newline at end of file diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp new file mode 100644 index 0000000..a1f5656 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/test.jpp @@ -0,0 +1,3 @@ +test: + @@com.android.jack.annotations.ForceInMainDex + class com.android.multidexlegacytestapp.Test diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk index 329f544..b85c02c 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk @@ -30,13 +30,16 @@ mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true LOCAL_DEX_PREOPT := false include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ $(built_dex_intermediate): $(mainDexList) - +endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk index e79fd71..0f1d9c0 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk @@ -26,18 +26,30 @@ LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v1 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex +LOCAL_DEX_PREOPT := false + mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) - +endif
\ No newline at end of file diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp new file mode 100644 index 0000000..6d384e3 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/test.jpp @@ -0,0 +1,3 @@ +test: + @@com.android.jack.annotations.ForceInMainDex + class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk index 3742004..67ca483 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk @@ -26,18 +26,30 @@ LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v2 LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex +LOCAL_DEX_PREOPT := false + mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) - +endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp new file mode 100644 index 0000000..6d384e3 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/test.jpp @@ -0,0 +1,3 @@ +test: + @@com.android.jack.annotations.ForceInMainDex + class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk index 7f400bc..bf2efb1 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk @@ -29,15 +29,28 @@ LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list +LOCAL_DEX_PREOPT := false + LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex +LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\ + -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true -LOCAL_DEX_PREOPT := false +################################# +include $(BUILD_SYSTEM)/configure_local_jack.mk +################################# + +ifdef LOCAL_JACK_ENABLED +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp +endif include $(BUILD_PACKAGE) +ifndef LOCAL_JACK_ENABLED $(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses + $(hide) mkdir -p $(dir $@) $(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) +endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp new file mode 100644 index 0000000..6d384e3 --- /dev/null +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/test.jpp @@ -0,0 +1,3 @@ +test: + @@com.android.jack.annotations.ForceInMainDex + class com.android.framework.multidexlegacyversionedtestapp.MultiDexUpdateTest diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java index 1557918..a50fb54 100644 --- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java +++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java @@ -29,8 +29,6 @@ import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import com.android.internal.inputmethod.InputMethodUtils; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -38,19 +36,33 @@ import java.util.Objects; public class InputMethodTest extends InstrumentationTestCase { private static final boolean IS_AUX = true; private static final boolean IS_DEFAULT = true; - private static final boolean IS_AUTO = true; + private static final boolean IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE = true; private static final boolean IS_ASCII_CAPABLE = true; + private static final boolean IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = true; private static final boolean IS_SYSTEM_READY = true; - private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null; + private static final Locale LOCALE_EN = new Locale("en"); private static final Locale LOCALE_EN_US = new Locale("en", "US"); private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); private static final Locale LOCALE_EN_IN = new Locale("en", "IN"); + private static final Locale LOCALE_FI = new Locale("fi"); + private static final Locale LOCALE_FI_FI = new Locale("fi", "FI"); + private static final Locale LOCALE_FIL = new Locale("fil"); + private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH"); + private static final Locale LOCALE_FR = new Locale("fr"); + private static final Locale LOCALE_FR_CA = new Locale("fr", "CA"); private static final Locale LOCALE_HI = new Locale("hi"); private static final Locale LOCALE_JA_JP = new Locale("ja", "JP"); private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN"); private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW"); + private static final Locale LOCALE_IN = new Locale("in"); + private static final Locale LOCALE_ID = new Locale("id"); private static final String SUBTYPE_MODE_KEYBOARD = "keyboard"; private static final String SUBTYPE_MODE_VOICE = "voice"; + private static final String SUBTYPE_MODE_ANY = null; + private static final String EXTRA_VALUE_PAIR_SEPARATOR = ","; + private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; + private static final String EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE = + "EnabledWhenDefaultIsNotAsciiCapable"; @SmallTest public void testVoiceImes() throws Exception { @@ -159,10 +171,415 @@ public class InputMethodTest extends InstrumentationTestCase { } } + @SmallTest + public void testGetImplicitlyApplicableSubtypesLocked() throws Exception { + final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype = + createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 = + createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX, + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + + // Make sure that an automatic subtype (overridesImplicitlyEnabledSubtype:true) is + // selected no matter what locale is specified. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); + subtypes.add(nonAutoEnGB); + subtypes.add(nonAutoJa); + subtypes.add(nonAutoFil); + subtypes.add(autoSubtype); // overridesImplicitlyEnabledSubtype == true + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi); + assertEquals(1, result.size()); + verifyEquality(autoSubtype, result.get(0)); + } + + // Make sure that a subtype whose locale is exactly equal to the specified locale is + // selected as long as there is no no automatic subtype + // (overridesImplicitlyEnabledSubtype:true) in the given list. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); // locale == "en_US" + subtypes.add(nonAutoEnGB); + subtypes.add(nonAutoJa); + subtypes.add(nonAutoFil); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_US, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoEnUS, result.get(0)); + } + + // Make sure that a subtype whose locale is exactly equal to the specified locale is + // selected as long as there is no automatic subtype + // (overridesImplicitlyEnabledSubtype:true) in the given list. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); + subtypes.add(nonAutoEnGB); // locale == "en_GB" + subtypes.add(nonAutoJa); + subtypes.add(nonAutoFil); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_EN_GB, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoEnGB, result.get(0)); + } + + // If there is no automatic subtype (overridesImplicitlyEnabledSubtype:true) and + // any subtype whose locale is exactly equal to the specified locale in the given list, + // try to find a subtype whose language is equal to the language part of the given locale. + // Here make sure that a subtype (locale: "fr_CA") can be found with locale: "fr". + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoFrCA); // locale == "fr_CA" + subtypes.add(nonAutoJa); + subtypes.add(nonAutoFil); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoFrCA, result.get(0)); + } + // Then make sure that a subtype (locale: "fr") can be found with locale: "fr_CA". + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoFr); // locale == "fr" + subtypes.add(nonAutoJa); + subtypes.add(nonAutoFil); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FR_CA, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoFrCA, result.get(0)); + } + + // Make sure that subtypes which have "EnabledWhenDefaultIsNotAsciiCapable" in its + // extra value is selected if and only if all other selected IMEs are not AsciiCapable. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); + subtypes.add(nonAutoJa); // not ASCII capable + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype); + subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_JA_JP, imi); + assertEquals(3, result.size()); + verifyEquality(nonAutoJa, result.get(0)); + verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype, result.get(1)); + verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2)); + } + + // Make sure that 3-letter language code can be handled. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); + subtypes.add(nonAutoFil); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FIL_PH, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoFil, result.get(0)); + } + + // Make sure that we never end up matching "fi" (finnish) with "fil" (filipino). + // Also make sure that the first subtype will be used as the last-resort candidate. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoJa); + subtypes.add(nonAutoEnUS); + subtypes.add(nonAutoFil); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_FI, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoJa, result.get(0)); + } + + // Make sure that "in" and "id" conversion is taken into account. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoIn); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoIn, result.get(0)); + } + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoIn); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoIn, result.get(0)); + } + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoId); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_IN, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoId, result.get(0)); + } + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoId); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + final ArrayList<InputMethodSubtype> result = + callGetImplicitlyApplicableSubtypesLockedWithLocale(LOCALE_ID, imi); + assertEquals(1, result.size()); + verifyEquality(nonAutoId, result.get(0)); + } + } + + @SmallTest + public void testContainsSubtypeOf() throws Exception { + final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id", + SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, + IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + + final boolean CHECK_COUNTRY = true; + + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, + SUBTYPE_MODE_VOICE)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, + SUBTYPE_MODE_VOICE)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, !CHECK_COUNTRY, + SUBTYPE_MODE_ANY)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_US, CHECK_COUNTRY, + SUBTYPE_MODE_ANY)); + + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN_GB, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + } + + // Make sure that 3-letter language code ("fil") can be handled. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoFil); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + } + + // Make sure that 3-letter language code ("fil_PH") can be handled. + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoFilPH); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL_PH, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertFalse(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FI_FI, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + } + + // Make sure that a subtype whose locale is "in" can be queried with "id". + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoIn); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + } + + // Make sure that a subtype whose locale is "id" can be queried with "in". + { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(nonAutoId); + subtypes.add(nonAutoEnUS); + final InputMethodInfo imi = createDummyInputMethodInfo( + "com.android.apps.inputmethod.latin", + "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT, + subtypes); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, !CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_ID, CHECK_COUNTRY, + SUBTYPE_MODE_KEYBOARD)); + } + } + + private ArrayList<InputMethodSubtype> callGetImplicitlyApplicableSubtypesLockedWithLocale( + final Locale locale, final InputMethodInfo imi) { + final Context context = getInstrumentation().getTargetContext(); + final Locale initialLocale = context.getResources().getConfiguration().locale; + try { + context.getResources().getConfiguration().setLocale(locale); + return InputMethodUtils.getImplicitlyApplicableSubtypesLocked(context.getResources(), + imi); + } finally { + context.getResources().getConfiguration().setLocale(initialLocale); + } + } + private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes, final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) { final Context context = getInstrumentation().getTargetContext(); - final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesUnderWithLocale( + final String[] actualImeNames = getPackageNames(callGetDefaultEnabledImesWithLocale( context, isSystemReady, preinstalledImes, systemLocale)); assertEquals(expectedImeNames.length, actualImeNames.length); for (int i = 0; i < expectedImeNames.length; ++i) { @@ -184,7 +601,7 @@ public class InputMethodTest extends InstrumentationTestCase { } } - private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesUnderWithLocale( + private static ArrayList<InputMethodInfo> callGetDefaultEnabledImesWithLocale( final Context context, final boolean isSystemReady, final ArrayList<InputMethodInfo> imis, final Locale locale) { final Locale initialLocale = context.getResources().getConfiguration().locale; @@ -210,11 +627,15 @@ public class InputMethodTest extends InstrumentationTestCase { for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) { final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex); final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex); - assertEquals(expectedSubtype, actualSubtype); - assertEquals(expectedSubtype.hashCode(), actualSubtype.hashCode()); + verifyEquality(expectedSubtype, actualSubtype); } } + private static void verifyEquality(InputMethodSubtype expected, InputMethodSubtype actual) { + assertEquals(expected, actual); + assertEquals(expected.hashCode(), actual.hashCode()); + } + private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name, CharSequence label, boolean isAuxIme, boolean isDefault, List<InputMethodSubtype> subtypes) { @@ -236,13 +657,27 @@ public class InputMethodTest extends InstrumentationTestCase { private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, - boolean isAsciiCapable) { + boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) { + + final StringBuilder subtypeExtraValue = new StringBuilder(); + if (isEnabledWhenDefaultIsNotAsciiCapable) { + subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR); + subtypeExtraValue.append(EXTRA_VALUE_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE); + } + + // TODO: Remove following code. InputMethodSubtype#isAsciiCapable() has been publicly + // available since API level 19 (KitKat). We no longer need to rely on extra value. + if (isAsciiCapable) { + subtypeExtraValue.append(EXTRA_VALUE_PAIR_SEPARATOR); + subtypeExtraValue.append(EXTRA_VALUE_ASCII_CAPABLE); + } + return new InputMethodSubtypeBuilder() .setSubtypeNameResId(0) .setSubtypeIconResId(0) .setSubtypeLocale(locale) .setSubtypeMode(mode) - .setSubtypeExtraValue("") + .setSubtypeExtraValue(subtypeExtraValue.toString()) .setIsAuxiliary(isAuxiliary) .setOverridesImplicitlyEnabledSubtype(overridesImplicitlyEnabledSubtype) .setIsAsciiCapable(isAsciiCapable) @@ -253,10 +688,12 @@ public class InputMethodTest extends InstrumentationTestCase { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO, - !IS_ASCII_CAPABLE)); + subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme", "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes)); } @@ -268,33 +705,39 @@ public class InputMethodTest extends InstrumentationTestCase { ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>(); { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO, - !IS_ASCII_CAPABLE)); + subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0", "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); - subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, IS_AUTO, - !IS_ASCII_CAPABLE)); + subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX, + IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1", "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2", "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes)); } { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme", "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes)); } @@ -321,7 +764,8 @@ public class InputMethodTest extends InstrumentationTestCase { final boolean isDefaultIme = false; final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX, - IS_AUTO, !IS_ASCII_CAPABLE)); + IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice", "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme, subtypes)); @@ -332,9 +776,11 @@ public class InputMethodTest extends InstrumentationTestCase { final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); // TODO: This subtype should be marked as IS_ASCII_CAPABLE subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi", "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme, subtypes)); @@ -345,7 +791,8 @@ public class InputMethodTest extends InstrumentationTestCase { final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin", "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme, subtypes)); @@ -356,7 +803,8 @@ public class InputMethodTest extends InstrumentationTestCase { final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean", "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme, subtypes)); @@ -368,13 +816,17 @@ public class InputMethodTest extends InstrumentationTestCase { new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme, subtypes)); @@ -385,9 +837,11 @@ public class InputMethodTest extends InstrumentationTestCase { final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString); final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX, - !IS_AUTO, !IS_ASCII_CAPABLE)); + !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE, + !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)); preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese", "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX, isDefaultIme, subtypes)); |