From 59091c08f4d0ad8f42013f58ce9bd23ac3306336 Mon Sep 17 00:00:00 2001 From: Jake Hamby Date: Thu, 16 Sep 2010 16:55:43 -0700 Subject: Fix Bluetooth device name max length checking. The Bluetooth device name has a maximum length of 248 bytes in UTF-8 encoding. The settings app previously limited the Bluetooth device name entered by the user based on the number of characters, which is incorrect when the name includes non-ASCII characters. Created a new Utf8ByteLengthFilter class for BluetoothNamePreference which counts UTF-8 bytes instead of Unicode characters, along with unit tests. We can move Utf8ByteLengthFilter into the framework in the future if it would be useful elsewhere in the system or for applications. Change-Id: I9debface09659f09d750f3bfe8ad6ddfd34c75c5 --- tests/AndroidManifest.xml | 5 + .../settings/SettingsLaunchPerformance.java | 53 ---------- .../settings/tests/SettingsLaunchPerformance.java | 53 ++++++++++ .../settings/tests/Utf8ByteLengthFilterTest.java | 113 +++++++++++++++++++++ 4 files changed, 171 insertions(+), 53 deletions(-) delete mode 100644 tests/src/com/android/settings/SettingsLaunchPerformance.java create mode 100644 tests/src/com/android/settings/tests/SettingsLaunchPerformance.java create mode 100644 tests/src/com/android/settings/tests/Utf8ByteLengthFilterTest.java (limited to 'tests') diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 6b9e050..6f0b5ef 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -37,4 +37,9 @@ android:label="Settings Launch Performance"> + + + diff --git a/tests/src/com/android/settings/SettingsLaunchPerformance.java b/tests/src/com/android/settings/SettingsLaunchPerformance.java deleted file mode 100644 index 05154e2..0000000 --- a/tests/src/com/android/settings/SettingsLaunchPerformance.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.tests; - -import android.app.Activity; -import android.test.LaunchPerformanceBase; -import android.os.Bundle; - -import java.util.Map; - -/** - * Instrumentation class for Settings launch performance testing. - */ -public class SettingsLaunchPerformance extends LaunchPerformanceBase { - - public static final String LOG_TAG = "SettingsLaunchPerformance"; - - public SettingsLaunchPerformance() { - super(); - } - - @Override - public void onCreate(Bundle arguments) { - super.onCreate(arguments); - - mIntent.setClassName(getTargetContext(), "com.android.settings.Settings"); - start(); - } - - /** - * Calls LaunchApp and finish. - */ - @Override - public void onStart() { - super.onStart(); - LaunchApp(); - finish(Activity.RESULT_OK, mResults); - } -} diff --git a/tests/src/com/android/settings/tests/SettingsLaunchPerformance.java b/tests/src/com/android/settings/tests/SettingsLaunchPerformance.java new file mode 100644 index 0000000..225a60b --- /dev/null +++ b/tests/src/com/android/settings/tests/SettingsLaunchPerformance.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.tests; + +import android.app.Activity; +import android.test.LaunchPerformanceBase; +import android.os.Bundle; + +import java.util.Map; + +/** + * Instrumentation class for Settings launch performance testing. + */ +public class SettingsLaunchPerformance extends LaunchPerformanceBase { + + public static final String LOG_TAG = "SettingsLaunchPerformance"; + + public SettingsLaunchPerformance() { + super(); + } + + @Override + public void onCreate(Bundle arguments) { + super.onCreate(arguments); + + mIntent.setClassName(getTargetContext(), "com.android.settings.Settings"); + start(); + } + + /** + * Calls LaunchApp and finish. + */ + @Override + public void onStart() { + super.onStart(); + LaunchApp(); + finish(Activity.RESULT_OK, mResults); + } +} diff --git a/tests/src/com/android/settings/tests/Utf8ByteLengthFilterTest.java b/tests/src/com/android/settings/tests/Utf8ByteLengthFilterTest.java new file mode 100644 index 0000000..c03f9c0 --- /dev/null +++ b/tests/src/com/android/settings/tests/Utf8ByteLengthFilterTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.tests; + +import android.test.AndroidTestCase; +import android.text.InputFilter; +import android.text.SpannableStringBuilder; + +import com.android.settings.bluetooth.BluetoothNamePreference; + +import dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +@TestTargetClass(BluetoothNamePreference.Utf8ByteLengthFilter.class) +public class Utf8ByteLengthFilterTest extends AndroidTestCase { + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "filter", + args = {java.lang.CharSequence.class, int.class, int.class, android.text.Spanned.class, + int.class, int.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "BluetoothNamePreference.Utf8ByteLengthFilter", + args = {int.class} + ) + }) + public void testFilter() { + // Define the variables + CharSequence source; + SpannableStringBuilder dest; + // Constructor to create a LengthFilter + BluetoothNamePreference.Utf8ByteLengthFilter lengthFilter = new BluetoothNamePreference.Utf8ByteLengthFilter(10); + InputFilter[] filters = {lengthFilter}; + + // filter() implicitly invoked. If the total length > filter length, the filter will + // cut off the source CharSequence from beginning to fit the filter length. + source = "abc"; + dest = new SpannableStringBuilder("abcdefgh"); + dest.setFilters(filters); + + dest.insert(1, source); + String expectedString1 = "aabbcdefgh"; + assertEquals(expectedString1, dest.toString()); + + dest.replace(5, 8, source); + String expectedString2 = "aabbcabcgh"; + assertEquals(expectedString2, dest.toString()); + + dest.insert(2, source); + assertEquals(expectedString2, dest.toString()); + + dest.delete(1, 3); + String expectedString3 = "abcabcgh"; + assertEquals(expectedString3, dest.toString()); + + dest.append("12345"); + String expectedString4 = "abcabcgh12"; + assertEquals(expectedString4, dest.toString()); + + source = "\u60a8\u597d"; // 2 Chinese chars == 6 bytes in UTF-8 + dest.replace(8, 10, source); + assertEquals(expectedString3, dest.toString()); + + dest.replace(0, 1, source); + String expectedString5 = "\u60a8bcabcgh"; + assertEquals(expectedString5, dest.toString()); + + dest.replace(0, 4, source); + String expectedString6 = "\u60a8\u597dbcgh"; + assertEquals(expectedString6, dest.toString()); + + source = "\u00a3\u00a5"; // 2 Latin-1 chars == 4 bytes in UTF-8 + dest.delete(2, 6); + dest.insert(0, source); + String expectedString7 = "\u00a3\u00a5\u60a8\u597d"; + assertEquals(expectedString7, dest.toString()); + + dest.replace(2, 3, source); + String expectedString8 = "\u00a3\u00a5\u00a3\u597d"; + assertEquals(expectedString8, dest.toString()); + + dest.replace(3, 4, source); + String expectedString9 = "\u00a3\u00a5\u00a3\u00a3\u00a5"; + assertEquals(expectedString9, dest.toString()); + + // filter() explicitly invoked + dest = new SpannableStringBuilder("abcdefgh"); + CharSequence beforeFilterSource = "TestLengthFilter"; + String expectedAfterFilter = "TestLength"; + CharSequence actualAfterFilter = lengthFilter.filter(beforeFilterSource, 0, + beforeFilterSource.length(), dest, 0, dest.length()); + assertEquals(expectedAfterFilter, actualAfterFilter); + } +} -- cgit v1.1