diff options
Diffstat (limited to 'core')
19 files changed, 295 insertions, 84 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 4761f98..bf9e07d 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -66,10 +66,10 @@ public class AccessibilityServiceInfo implements Parcelable { * The event types an {@link AccessibilityService} is interested in. * * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED + * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED - * @see android.view.accessibility.AccessibilityEvent#TYPE_ACTIVITY_STARTED * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED */ @@ -115,7 +115,7 @@ public class AccessibilityServiceInfo implements Parcelable { return 0; } - public void writeToParcel(Parcel parcel, int flags) { + public void writeToParcel(Parcel parcel, int flagz) { parcel.writeInt(eventTypes); parcel.writeStringArray(packageNames); parcel.writeInt(feedbackType); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index d31b25b..1b0437c 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1815,11 +1815,18 @@ public class Intent implements Parcelable, Cloneable { /** * Broadcast Action: A sticky broadcast indicating the phone was docked - * or undocked. Includes the extra - * field {@link #EXTRA_DOCK_STATE}, containing the current dock state. It also - * includes the boolean extra field {@link #EXTRA_CAR_MODE_ENABLED}, indicating - * the state of the car mode. - * This is intended for monitoring the current dock state. + * or undocked. + * + * <p>The intent will have the following extra values: + * <ul> + * <li><em>{@link #EXTRA_DOCK_STATE}</em> - the current dock + * state, which depends on the state of the car mode.</li> + * <li><em>{@link #EXTRA_PHYSICAL_DOCK_STATE}</em> - the physical dock + * state.</li> + * <li><em>{@link #EXTRA_CAR_MODE_ENABLED}</em> - a boolean indicating the + * state of the car mode.</li> + * </ul> + * <p>This is intended for monitoring the current dock state. * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK} * or {@link #CATEGORY_DESK_DOCK} instead. */ @@ -2154,6 +2161,16 @@ public class Intent implements Parcelable, Cloneable { public static final int EXTRA_DOCK_STATE_CAR = 2; /** + * Used as an int extra field in {@link android.content.Intent#ACTION_DOCK_EVENT} + * intents to request the physical dock state. Possible values are + * {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED}, + * {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or + * {@link android.content.Intent#EXTRA_DOCK_STATE_CAR}. + */ + public static final String EXTRA_PHYSICAL_DOCK_STATE = + "android.intent.extra.PHYSICAL_DOCK_STATE"; + + /** * Used as an boolean extra field in {@link android.content.Intent#ACTION_DOCK_EVENT} * intents to indicate that the car mode is enabled or not. */ diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 9ff2e25..4ddb819 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -447,17 +447,6 @@ public class SyncManager implements OnAccountsUpdateListener { } /** - * Returns whether or not sync is enabled. Sync can be enabled by - * setting the system property "ro.config.sync" to the value "yes". - * This is normally done at boot time on builds that support sync. - * @return true if sync is enabled - */ - private boolean isSyncEnabled() { - // Require the precise value "yes" to discourage accidental activation. - return "yes".equals(SystemProperties.get("ro.config.sync")); - } - - /** * Initiate a sync. This can start a sync for all providers * (pass null to url, set onlyTicklable to false), only those * providers that are marked as ticklable (pass null to url, @@ -488,13 +477,6 @@ public class SyncManager implements OnAccountsUpdateListener { Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) { boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - if (!isSyncEnabled()) { - if (isLoggable) { - Log.v(TAG, "not syncing because sync is disabled"); - } - return; - } - final boolean backgroundDataUsageAllowed = !mBootCompleted || getConnectivityManager().getBackgroundDataSetting(); @@ -922,9 +904,7 @@ public class SyncManager implements OnAccountsUpdateListener { protected void dump(FileDescriptor fd, PrintWriter pw) { StringBuilder sb = new StringBuilder(); dumpSyncState(pw, sb); - if (isSyncEnabled()) { - dumpSyncHistory(pw, sb); - } + dumpSyncHistory(pw, sb); pw.println(); pw.println("SyncAdapters:"); @@ -940,7 +920,6 @@ public class SyncManager implements OnAccountsUpdateListener { } protected void dumpSyncState(PrintWriter pw, StringBuilder sb) { - pw.print("sync enabled: "); pw.println(isSyncEnabled()); pw.print("data connected: "); pw.println(mDataConnectionIsConnected); pw.print("memory low: "); pw.println(mStorageIsLow); @@ -1456,11 +1435,6 @@ public class SyncManager implements OnAccountsUpdateListener { boolean backgroundDataUsageAllowed) { Account[] accounts = mAccounts; - // Sync is disabled, drop this operation. - if (!isSyncEnabled()) { - return false; - } - // skip the sync if the account of this operation no longer exists if (!ArrayUtils.contains(accounts, account)) { return false; diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl index 816baf3..79a6cfe 100644 --- a/core/java/android/os/storage/IMountService.aidl +++ b/core/java/android/os/storage/IMountService.aidl @@ -63,7 +63,7 @@ interface IMountService * Safely unmount external storage at given mount point. * Returns an int consistent with MountServiceResultCode */ - int unmountVolume(String mountPoint); + int unmountVolume(String mountPoint, boolean force); /** * Format external storage given a mount point. @@ -100,7 +100,7 @@ interface IMountService * NOTE: Ensure all references are released prior to deleting. * Returns an int consistent with MountServiceResultCode */ - int destroySecureContainer(String id); + int destroySecureContainer(String id, boolean force); /* * Mount a secure container with the specified key and owner UID. @@ -112,7 +112,7 @@ interface IMountService * Unount a secure container. * Returns an int consistent with MountServiceResultCode */ - int unmountSecureContainer(String id); + int unmountSecureContainer(String id, boolean force); /* * Returns true if the specified container is mounted diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java index 249bacf..07d95df 100644 --- a/core/java/android/os/storage/StorageResultCode.java +++ b/core/java/android/os/storage/StorageResultCode.java @@ -64,4 +64,10 @@ public class StorageResultCode */ public static final int OperationFailedStorageMounted = -6; + /** + * Operation failed: Storage is busy. + * @see android.os.storage.StorageManager + */ + public static final int OperationFailedStorageBusy = -7; + } diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java index bd7924a..5d09fb5 100644 --- a/core/java/android/pim/RecurrenceSet.java +++ b/core/java/android/pim/RecurrenceSet.java @@ -48,7 +48,8 @@ public class RecurrenceSet { * events table in the CalendarProvider. * @param values The values retrieved from the Events table. */ - public RecurrenceSet(ContentValues values) { + public RecurrenceSet(ContentValues values) + throws EventRecurrence.InvalidFormatException { String rruleStr = values.getAsString(Calendar.Events.RRULE); String rdateStr = values.getAsString(Calendar.Events.RDATE); String exruleStr = values.getAsString(Calendar.Events.EXRULE); @@ -65,7 +66,8 @@ public class RecurrenceSet { * @param cursor The cursor containing the RRULE, RDATE, EXRULE, and EXDATE * columns. */ - public RecurrenceSet(Cursor cursor) { + public RecurrenceSet(Cursor cursor) + throws EventRecurrence.InvalidFormatException { int rruleColumn = cursor.getColumnIndex(Calendar.Events.RRULE); int rdateColumn = cursor.getColumnIndex(Calendar.Events.RDATE); int exruleColumn = cursor.getColumnIndex(Calendar.Events.EXRULE); @@ -78,12 +80,14 @@ public class RecurrenceSet { } public RecurrenceSet(String rruleStr, String rdateStr, - String exruleStr, String exdateStr) { + String exruleStr, String exdateStr) + throws EventRecurrence.InvalidFormatException { init(rruleStr, rdateStr, exruleStr, exdateStr); } private void init(String rruleStr, String rdateStr, - String exruleStr, String exdateStr) { + String exruleStr, String exdateStr) + throws EventRecurrence.InvalidFormatException { if (!TextUtils.isEmpty(rruleStr) || !TextUtils.isEmpty(rdateStr)) { if (!TextUtils.isEmpty(rruleStr)) { diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 39e5275..662be95 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -916,9 +916,12 @@ public class WebSettings { } /** - * Tell the WebView to block network image. This is only checked when - * getLoadsImagesAutomatically() is true. - * @param flag True if the WebView should block network image + * Tell the WebView to block network images. This is only checked when + * {@link #getLoadsImagesAutomatically} is true. If you set the value to + * false, images will automatically be loaded. Use this api to reduce + * bandwidth only. Use {@link #setBlockNetworkLoads} if possible. + * @param flag True if the WebView should block network images. + * @see #setBlockNetworkLoads */ public synchronized void setBlockNetworkImage(boolean flag) { if (mBlockNetworkImage != flag) { @@ -928,17 +931,21 @@ public class WebSettings { } /** - * Return true if the WebView will block network image. The default is false. - * @return True if the WebView blocks network image. + * Return true if the WebView will block network images. The default is + * false. + * @return True if the WebView blocks network images. */ public synchronized boolean getBlockNetworkImage() { return mBlockNetworkImage; } /** - * @hide - * Tell the WebView to block all network load requests. - * @param flag True if the WebView should block all network loads + * Tell the WebView to block all network load requests. If you set the + * value to false, you must call {@link android.webkit.WebView#reload} to + * fetch remote resources. This flag supercedes the value passed to + * {@link #setBlockNetworkImage}. + * @param flag True if the WebView should block all network loads. + * @see android.webkit.WebView#reload */ public synchronized void setBlockNetworkLoads(boolean flag) { if (mBlockNetworkLoads != flag) { @@ -948,9 +955,8 @@ public class WebSettings { } /** - * @hide - * Return true if the WebView will block all network loads. - * The default is false. + * Return true if the WebView will block all network loads. The default is + * false. * @return True if the WebView blocks all network loads. */ public synchronized boolean getBlockNetworkLoads() { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9672892..5f5df56 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -3088,14 +3088,11 @@ public class WebView extends AbsoluteLayout Rect vBox = contentToViewRect(contentBounds); Rect visibleRect = new Rect(); calcOurVisibleRect(visibleRect); - // The IME may have shown, resulting in the textfield being offscreen. - // If so, the textfield will be scrolled on screen, so treat it as - // though it is on screen. If it is on screen, place the WebTextView in - // its new place, accounting for our new scroll/zoom values. - InputMethodManager imm = InputMethodManager.peekInstance(); - if ((imm != null && imm.isActive(mWebTextView)) - || (allowIntersect ? Rect.intersects(visibleRect, vBox) - : visibleRect.contains(vBox))) { + // If the textfield is on screen, place the WebTextView in + // its new place, accounting for our new scroll/zoom values, + // and adjust its textsize. + if (allowIntersect ? Rect.intersects(visibleRect, vBox) + : visibleRect.contains(vBox)) { mWebTextView.setRect(vBox.left, vBox.top, vBox.width(), vBox.height()); mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index c428dc0..5308725 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -16,14 +16,17 @@ package android.widget; +import com.android.internal.R; +import com.google.android.collect.Lists; + import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.PixelFormat; import android.graphics.Paint; -import android.graphics.drawable.Drawable; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; @@ -31,16 +34,13 @@ import android.util.SparseBooleanArray; import android.view.FocusFinder; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewParent; -import android.view.SoundEffectConstants; import android.view.accessibility.AccessibilityEvent; -import com.google.android.collect.Lists; -import com.android.internal.R; - import java.util.ArrayList; /* @@ -2722,7 +2722,8 @@ public class ListView extends AbsListView { /** * Determine the distance to the nearest edge of a view in a particular - * direciton. + * direction. + * * @param descendant A descendant of this list. * @return The distance, or 0 if the nearest edge is already on screen. */ @@ -3307,9 +3308,9 @@ public class ListView extends AbsListView { * Sets the checked state of the specified position. The is only valid if * the choice mode has been set to {@link #CHOICE_MODE_SINGLE} or * {@link #CHOICE_MODE_MULTIPLE}. - * + * * @param position The item whose checked state is to be checked - * @param value The new checked sate for the item + * @param value The new checked state for the item */ public void setItemChecked(int position, boolean value) { if (mChoiceMode == CHOICE_MODE_NONE) { @@ -3392,10 +3393,11 @@ public class ListView extends AbsListView { } /** - * Returns the set of checked items ids. The result is only valid if - * the choice mode has not been set to {@link #CHOICE_MODE_SINGLE}. - * - * @return A new array which contains the id of each checked item in the list. + * Returns the set of checked items ids. The result is only valid if the + * choice mode has not been set to {@link #CHOICE_MODE_SINGLE}. + * + * @return A new array which contains the id of each checked item in the + * list. */ public long[] getCheckItemIds() { if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) { @@ -3404,11 +3406,23 @@ public class ListView extends AbsListView { final long[] ids = new long[count]; final ListAdapter adapter = mAdapter; + int checkedCount = 0; for (int i = 0; i < count; i++) { - ids[i]= adapter.getItemId(states.keyAt(i)); + if (states.valueAt(i)) { + ids[checkedCount++] = adapter.getItemId(states.keyAt(i)); + } } - return ids; + // Trim array if needed. mCheckStates may contain false values + // resulting in checkedCount being smaller than count. + if (checkedCount == count) { + return ids; + } else { + final long[] result = new long[checkedCount]; + System.arraycopy(ids, 0, result, 0, checkedCount); + + return result; + } } return new long[0]; diff --git a/core/java/com/android/internal/app/DisableCarModeActivity.java b/core/java/com/android/internal/app/DisableCarModeActivity.java new file mode 100644 index 0000000..95dc1f9 --- /dev/null +++ b/core/java/com/android/internal/app/DisableCarModeActivity.java @@ -0,0 +1,42 @@ +/* + * 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.internal.app; + +import android.app.Activity; +import android.app.IUiModeManager; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +public class DisableCarModeActivity extends Activity { + private static final String TAG = "DisableCarModeActivity"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + try { + IUiModeManager uiModeManager = IUiModeManager.Stub.asInterface( + ServiceManager.getService("uimode")); + uiModeManager.disableCarMode(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to disable car mode", e); + } + finish(); + } + +} diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java index c5b869b..bc7dbf4 100644 --- a/core/java/com/android/internal/content/PackageHelper.java +++ b/core/java/com/android/internal/content/PackageHelper.java @@ -93,7 +93,7 @@ public class PackageHelper { public static boolean unMountSdDir(String cid) { try { - int rc = getMountService().unmountSecureContainer(cid); + int rc = getMountService().unmountSecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.e(TAG, "Failed to unmount " + cid + " with rc " + rc); return false; @@ -148,7 +148,7 @@ public class PackageHelper { public static boolean destroySdDir(String cid) { try { - int rc = getMountService().destroySecureContainer(cid); + int rc = getMountService().destroySecureContainer(cid, false); if (rc != StorageResultCode.OperationSucceeded) { Log.i(TAG, "Failed to destroy container " + cid); return false; diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp index c197010..26d0e86 100644 --- a/core/jni/android_database_SQLiteDatabase.cpp +++ b/core/jni/android_database_SQLiteDatabase.cpp @@ -470,7 +470,7 @@ void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* messa if (errcode == SQLITE_DONE) { throw_sqlite3_exception(env, errcode, NULL, message); } else { - char temp[20]; + char temp[21]; sprintf(temp, "error code %d", errcode); throw_sqlite3_exception(env, errcode, temp, message); } diff --git a/core/jni/android_database_SQLiteProgram.cpp b/core/jni/android_database_SQLiteProgram.cpp index 32018eb..c247bbd 100644 --- a/core/jni/android_database_SQLiteProgram.cpp +++ b/core/jni/android_database_SQLiteProgram.cpp @@ -45,8 +45,8 @@ static jfieldID gStatementField; static void native_compile(JNIEnv* env, jobject object, jstring sqlString) { - char buf[32]; - sprintf(buf, "android_database_SQLiteProgram->native_compile() not implemented"); + char buf[65]; + strcpy(buf, "android_database_SQLiteProgram->native_compile() not implemented"); throw_sqlite3_exception(env, GET_HANDLE(env, object), buf); return; } @@ -152,8 +152,8 @@ static void native_clear_bindings(JNIEnv* env, jobject object) static void native_finalize(JNIEnv* env, jobject object) { - char buf[32]; - sprintf(buf, "android_database_SQLiteProgram->native_finalize() not implemented"); + char buf[66]; + strcpy(buf, "android_database_SQLiteProgram->native_finalize() not implemented"); throw_sqlite3_exception(env, GET_HANDLE(env, object), buf); return; } diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp index 4e1ae62..5432efb 100644 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -1122,9 +1122,10 @@ void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) { if (dbus_set_error_from_message(&err, msg)) { if (dbus_error_has_name(&err, "org.bluez.Error.AlreadyExists")) { result = CREATE_DEVICE_ALREADY_EXISTS; + } else { + result = CREATE_DEVICE_FAILED; } LOG_AND_FREE_DBUS_ERROR(&err); - result = CREATE_DEVICE_FAILED; } env->CallVoidMethod(nat->me, method_onCreateDeviceResult, diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index a27d28f..333db05 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1252,6 +1252,10 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> + <activity android:name="com.android.internal.app.DisableCarModeActivity" + android:theme="@style/Theme.NoDisplay" + android:excludeFromRecents="true"> + </activity> <activity android:name="com.android.internal.app.RingtonePickerActivity" android:theme="@style/Theme.Dialog.Alert" android:excludeFromRecents="true" diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png Binary files differnew file mode 100644 index 0000000..6c51b32 --- /dev/null +++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png diff --git a/core/res/res/drawable-mdpi/stat_notify_car_mode.png b/core/res/res/drawable-mdpi/stat_notify_car_mode.png Binary files differnew file mode 100644 index 0000000..c664244 --- /dev/null +++ b/core/res/res/drawable-mdpi/stat_notify_car_mode.png diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6f34b4f..cdf38b9 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2261,4 +2261,9 @@ <!-- See TETHER_STOP_DIALOG. If there was an error disconnect, this is the text. --> <string name="tether_stop_error_message">We\'ve encountered a problem turning off Tethering. Please try again.</string> + <!-- Strings for car mode notification --> + <!-- Shown when car mode is enabled --> + <string name="car_mode_disable_notification_title">Car mode enabled</string> + <string name="car_mode_disable_notification_message">Select to disable car mode.</string> + </resources> diff --git a/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java new file mode 100644 index 0000000..33d61a0 --- /dev/null +++ b/core/tests/coretests/src/android/widget/listview/ListGetCheckItemIdsTest.java @@ -0,0 +1,141 @@ +/* + * 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 android.widget.listview; + +import android.test.ActivityInstrumentationTestCase2; +import android.test.UiThreadTest; +import android.test.suitebuilder.annotation.MediumTest; +import android.widget.ListView; + +import java.util.Arrays; + +/** + * Testing the ListView getCheckItemIds() method in different situations. + */ +public class ListGetCheckItemIdsTest extends ActivityInstrumentationTestCase2<ListSimple> { + private ListView mListView; + + public ListGetCheckItemIdsTest() { + super(ListSimple.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mListView = getActivity().getListView(); + } + + private void assertChecked(String message, long... expectedIds) { + // Sort the two arrays since we are actually doing a set equality. + long[] checkItemIds = mListView.getCheckItemIds(); + long[] sortedCheckItemsIds = new long[checkItemIds.length]; + System.arraycopy(checkItemIds, 0, sortedCheckItemsIds, 0, checkItemIds.length); + Arrays.sort(sortedCheckItemsIds); + + long[] sortedExpectedIds = new long[expectedIds.length]; + System.arraycopy(expectedIds, 0, sortedExpectedIds, 0, expectedIds.length); + Arrays.sort(sortedExpectedIds); + + assertTrue(message, Arrays.equals(sortedExpectedIds, sortedCheckItemsIds)); + } + + @MediumTest + @UiThreadTest + public void testNoneCheck() { + mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); + + mListView.setItemChecked(0, true); + assertChecked("None check choice has item checked"); + } + + @MediumTest + @UiThreadTest + public void testSimpleCheck() { + mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + assertChecked("Item checked when setting Single mode"); + + // Test a check at each position + int childCount = mListView.getChildCount(); + for (int i=0; i<childCount; i++) { + mListView.setItemChecked(i, true); + assertChecked("Only element " + i + " should be checked", i); + } + + // Check an element and uncheck some others + for (int i = 0; i < childCount; i++) { + mListView.setItemChecked(i, true); + mListView.setItemChecked((i - 3 + childCount) % childCount, false); + mListView.setItemChecked((i + 1) % childCount, false); + assertChecked("Only element " + i + " should be checked", i); + } + } + + @MediumTest + @UiThreadTest + public void testMultipleCheck() { + mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + assertChecked("Item checked when setting Multiple mode"); + + int childCount = mListView.getChildCount(); + assertTrue("Tests requires at least 4 items", childCount >= 4); + + mListView.setItemChecked(1, true); + assertChecked("First element non checked", 1); + + mListView.setItemChecked(3, true); + assertChecked("Second element not checked", 1, 3); + + mListView.setItemChecked(0, true); + assertChecked("Third element not checked", 0, 1, 3); + + mListView.setItemChecked(2, false); + assertChecked("Unchecked element appears checked", 0, 1, 3); + + mListView.setItemChecked(1, false); + assertChecked("Unchecked element remains", 0, 3); + + mListView.setItemChecked(2, false); + assertChecked("Already unchecked element appears", 0, 3); + + mListView.setItemChecked(3, false); + assertChecked("Unchecked 3 remains", 0); + + mListView.setItemChecked(3, false); + assertChecked("Twice unchecked 3 remains", 0); + + mListView.setItemChecked(0, false); + assertChecked("Checked items after last element unchecked"); + } + + @MediumTest + @UiThreadTest + public void testClearChoices() { + mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); + mListView.setItemChecked(0, true); + mListView.clearChoices(); + assertChecked("Item checked after SINGLE clear choice"); + + mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); + int childCount = mListView.getChildCount(); + for (int i = 0; i < childCount; i++) { + mListView.setItemChecked(0, i % 3 == 0); + } + mListView.clearChoices(); + assertChecked("Item checked after MULTIPLE clear choice"); + } +} |