summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt13
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java11
-rw-r--r--core/java/android/content/pm/Signature.java25
-rw-r--r--core/java/android/provider/CallLog.java10
-rw-r--r--core/java/android/provider/ContactsContract.java26
-rw-r--r--core/java/android/provider/Settings.java10
-rw-r--r--core/java/android/provider/VoicemailContract.java6
-rw-r--r--core/java/android/server/BluetoothAdapterStateMachine.java513
-rw-r--r--core/java/android/server/BluetoothEventLoop.java18
-rwxr-xr-xcore/java/android/server/BluetoothService.java304
-rw-r--r--core/java/android/service/textservice/SpellCheckerService.java3
-rw-r--r--core/java/android/view/Surface.java18
-rw-r--r--core/java/android/view/View.java30
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java44
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java4
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl2
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManagerClient.aidl4
-rw-r--r--core/java/android/view/textservice/SpellCheckerInfo.java20
-rw-r--r--core/java/android/view/textservice/TextServicesManager.java23
-rw-r--r--core/java/android/webkit/JniUtil.java15
-rw-r--r--core/java/android/webkit/WebView.java5
-rw-r--r--core/java/android/widget/PopupWindow.java21
-rw-r--r--core/java/android/widget/SearchView.java47
-rw-r--r--core/java/android/widget/Switch.java8
-rw-r--r--core/java/com/android/internal/textservice/ITextServicesManager.aidl1
-rw-r--r--core/jni/android_view_Surface.cpp36
-rwxr-xr-xcore/res/res/values/attrs.xml2
-rwxr-xr-xcore/res/res/values/config.xml4
-rw-r--r--core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java8
-rw-r--r--include/gui/SurfaceTexture.h5
-rw-r--r--include/surfaceflinger/Surface.h7
-rw-r--r--libs/gui/Surface.cpp56
-rw-r--r--libs/gui/SurfaceTexture.cpp30
-rw-r--r--libs/gui/tests/SurfaceTexture_test.cpp32
-rw-r--r--media/java/android/media/AudioFormat.java28
-rw-r--r--media/java/android/media/MediaPlayer.java29
-rw-r--r--packages/SystemUI/res/values/strings.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java3
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java49
-rw-r--r--services/audioflinger/AudioFlinger.cpp38
-rw-r--r--services/audioflinger/AudioFlinger.h2
-rw-r--r--services/java/com/android/server/TextServicesManagerService.java11
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java95
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java166
-rw-r--r--services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java26
-rw-r--r--services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java16
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java15
48 files changed, 1335 insertions, 515 deletions
diff --git a/api/current.txt b/api/current.txt
index 2514efd..a71c866 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1828,6 +1828,7 @@ package android.accessibilityservice {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DEFAULT = 1; // 0x1
+ field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
field public static final int FEEDBACK_AUDIBLE = 4; // 0x4
field public static final int FEEDBACK_GENERIC = 16; // 0x10
field public static final int FEEDBACK_HAPTIC = 2; // 0x2
@@ -16710,7 +16711,7 @@ package android.provider {
field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
- field public static final java.lang.String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
+ field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
field public static final java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
field public static final java.lang.String TTS_DEFAULT_LANG = "tts_default_lang";
field public static final java.lang.String TTS_DEFAULT_PITCH = "tts_default_pitch";
@@ -17951,7 +17952,7 @@ package android.service.textservice {
method public abstract android.view.textservice.SuggestionsInfo getSuggestions(android.view.textservice.TextInfo, int, java.lang.String);
method public android.view.textservice.SuggestionsInfo[] getSuggestionsMultiple(android.view.textservice.TextInfo[], java.lang.String, int, boolean);
method public final android.os.IBinder onBind(android.content.Intent);
- field public static final java.lang.String SERVICE_INTERFACE;
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.textservice.SpellCheckerService";
}
public class SpellCheckerSession {
@@ -22232,6 +22233,7 @@ package android.view {
method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence);
method protected boolean fitSystemWindows(android.graphics.Rect);
+ method public boolean fitsSystemWindows();
method public android.view.View focusSearch(int);
method public void forceLayout();
method public float getAlpha();
@@ -22473,6 +22475,7 @@ package android.view {
method public void setEnabled(boolean);
method public void setFadingEdgeLength(int);
method public void setFilterTouchesWhenObscured(boolean);
+ method public void setFitsSystemWindows(boolean);
method public void setFocusable(boolean);
method public void setFocusableInTouchMode(boolean);
method public void setHapticFeedbackEnabled(boolean);
@@ -24055,6 +24058,8 @@ package android.view.textservice {
method public android.content.ComponentName getComponent();
method public java.lang.String getId();
method public java.lang.String getPackageName();
+ method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+ method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -26196,7 +26201,7 @@ package android.widget {
method public int timePassed();
}
- public class SearchView extends android.widget.LinearLayout {
+ public class SearchView extends android.widget.LinearLayout implements android.view.CollapsibleActionView {
ctor public SearchView(android.content.Context);
ctor public SearchView(android.content.Context, android.util.AttributeSet);
method public java.lang.CharSequence getQuery();
@@ -26205,6 +26210,8 @@ package android.widget {
method public boolean isIconified();
method public boolean isQueryRefinementEnabled();
method public boolean isSubmitButtonEnabled();
+ method public void onActionViewCollapsed();
+ method public void onActionViewExpanded();
method public void setIconified(boolean);
method public void setIconifiedByDefault(boolean);
method public void setMaxWidth(int);
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index a09607a..41a3eac 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -75,6 +75,17 @@ public class AccessibilityServiceInfo implements Parcelable {
public static final int FEEDBACK_GENERIC = 0x0000010;
/**
+ * Mask for all feedback types.
+ *
+ * @see #FEEDBACK_SPOKEN
+ * @see #FEEDBACK_HAPTIC
+ * @see #FEEDBACK_AUDIBLE
+ * @see #FEEDBACK_VISUAL
+ * @see #FEEDBACK_GENERIC
+ */
+ public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
+
+ /**
* If an {@link AccessibilityService} is the default for a given type.
* Default service is invoked only if no package specific one exists. In case of
* more than one package specific service only the earlier registered is notified.
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index d4e5cc1..b32664e 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -45,16 +45,23 @@ public class Signature implements Parcelable {
* {@link #toChars} or {@link #toCharsString()}.
*/
public Signature(String text) {
- final int N = text.length()/2;
- byte[] sig = new byte[N];
- for (int i=0; i<N; i++) {
- char c = text.charAt(i*2);
- byte b = (byte)(
- (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4);
- c = text.charAt(i*2 + 1);
- b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0'));
- sig[i] = b;
+ final byte[] input = text.getBytes();
+ final int N = input.length;
+ final byte[] sig = new byte[N / 2];
+ int sigIndex = 0;
+
+ for (int i = 0; i < N;) {
+ int b;
+
+ final int hi = input[i++];
+ b = (hi >= 'a' ? (hi - 'a' + 10) : (hi - '0')) << 4;
+
+ final int lo = input[i++];
+ b |= (lo >= 'a' ? (lo - 'a' + 10) : (lo - '0')) & 0x0F;
+
+ sig[sigIndex++] = (byte) (b & 0xFF);
}
+
mSignature = sig;
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 382fcf3..e23d6f3 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -184,6 +184,16 @@ public class CallLog {
public static final String VOICEMAIL_URI = "voicemail_uri";
/**
+ * Whether this item has been read or otherwise consumed by the user.
+ * <p>
+ * Unlike the {@link #NEW} field, which requires the user to have acknowledged the
+ * existence of the entry, this implies the user has interacted with the entry.
+ * <P>Type: INTEGER (boolean)</P>
+ * @hide
+ */
+ public static final String IS_READ = "is_read";
+
+ /**
* Adds a call to the call log.
*
* @param ci the CallerInfo object to get the target contact from. Can be null
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 4a719ec..a0f1eec 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -6514,6 +6514,32 @@ public final class ContactsContract {
public static final String SUMMARY_COUNT = "summ_count";
/**
+ * A boolean query parameter that can be used with {@link Groups#CONTENT_SUMMARY_URI}.
+ * It will additionally return {@link #SUMMARY_GROUP_COUNT_PER_ACCOUNT}.
+ *
+ * @hide
+ */
+ public static final String PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT =
+ "return_group_count_per_account";
+
+ /**
+ * The total number of groups of the account that a group belongs to.
+ * This column is available only when the parameter
+ * {@link #PARAM_RETURN_GROUP_COUNT_PER_ACCOUNT} is specified in
+ * {@link Groups#CONTENT_SUMMARY_URI}.
+ *
+ * For example, when the account "A" has two groups "group1" and "group2", and the account
+ * "B" has a group "group3", the rows for "group1" and "group2" return "2" and the row for
+ * "group3" returns "1" for this column.
+ *
+ * Note: This counts only non-favorites, non-auto-add, and not deleted groups.
+ *
+ * Type: INTEGER
+ * @hide
+ */
+ public static final String SUMMARY_GROUP_COUNT_PER_ACCOUNT = "group_count_per_account";
+
+ /**
* The total number of {@link Contacts} that have both
* {@link CommonDataKinds.GroupMembership} in this group, and also have phone numbers.
* Read-only value that is only present when querying
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1cd46de..cd4e32e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2688,11 +2688,9 @@ public final class Settings {
public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
/**
- * If touch exploration is requested. Touch exploration is enabled if it is
- * requested by this setting, accessibility is enabled and there is at least
- * one enabled accessibility serivce that provides spoken feedback.
+ * If touch exploration is enabled.
*/
- public static final String TOUCH_EXPLORATION_REQUESTED = "touch_exploration_requested";
+ public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
/**
* List of the enabled accessibility providers.
@@ -3935,6 +3933,10 @@ public final class Settings {
/** Timeout in milliseconds to wait for NTP server. {@hide} */
public static final String NTP_TIMEOUT = "ntp_timeout";
+ /** Autofill server address (Used in WebView/browser). {@hide} */
+ public static final String WEB_AUTOFILL_QUERY_URL =
+ "web_autofill_query_url";
+
/**
* @hide
*/
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 2ad7395..2e5a495 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -128,6 +128,12 @@ public class VoicemailContract {
*/
public static final String NEW = Calls.NEW;
/**
+ * Whether this item has been read or otherwise consumed by the user.
+ * <P>Type: INTEGER (boolean)</P>
+ * @hide
+ */
+ public static final String IS_READ = Calls.IS_READ;
+ /**
* The mail box state of the voicemail. This field is currently not used by the system.
* <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED},
* {@link #STATE_UNDELETED}.
diff --git a/core/java/android/server/BluetoothAdapterStateMachine.java b/core/java/android/server/BluetoothAdapterStateMachine.java
new file mode 100644
index 0000000..ae91465
--- /dev/null
+++ b/core/java/android/server/BluetoothAdapterStateMachine.java
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.util.IState;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import java.io.PrintWriter;
+
+/**
+ * Bluetooth Adapter StateMachine
+ * All the states are at the same level, ie, no hierarchy.
+ * (BluetootOn)
+ * | ^
+ * TURN_OFF | | BECOME_PAIRABLE
+ * AIRPLANE_MODE_ON | |
+ * V |
+ * (Switching)
+ * | ^
+ * BECOME_NON_PAIRABLE& | | TURN_ON(_CONTINUE)/TURN_ON_FOR_PRIVILEGED
+ * ALL_DEVICES_DISCONNECTED | |
+ * V |
+ * (HotOff)
+ * / ^
+ * / | SERVICE_RECORD_LOADED
+ * | |
+ * TURN_COLD | (Warmup)
+ * \ ^
+ * \ | TURN_HOT/TURN_ON
+ * | | AIRPLANE_MODE_OFF(when Bluetooth was on before)
+ * V |
+ * (PowerOff) <----- initial state
+ *
+ */
+final class BluetoothAdapterStateMachine extends StateMachine {
+ private static final String TAG = "BluetoothAdapterStateMachine";
+ private static final boolean DBG = false;
+
+ // Message(what) to take an action
+ //
+ // We get this message when user tries to turn on BT
+ public static final int USER_TURN_ON = 1;
+ // We get this message when user tries to turn off BT
+ public static final int USER_TURN_OFF = 2;
+
+ // Message(what) to report a event that the state machine need to respond to
+ //
+ // Event indicates sevice records have been loaded
+ public static final int SERVICE_RECORD_LOADED = 51;
+ // Event indicates all the remote Bluetooth devices has been disconnected
+ public static final int ALL_DEVICES_DISCONNECTED = 52;
+ // Event indicates the Bluetooth is connectable
+ public static final int BECOME_PAIRABLE = 53;
+ // Event indicates the Bluetooth is non-connectable.
+ public static final int BECOME_NON_PAIRABLE = 54;
+ // Event indicates airplane mode is turned on
+ public static final int AIRPLANE_MODE_ON = 55;
+ // Event indicates airplane mode is turned off
+ public static final int AIRPLANE_MODE_OFF = 56;
+
+ // private internal messages
+ //
+ // Turn on Bluetooth Module, Load firmware, and do all the preparation
+ // needed to get the Bluetooth Module ready but keep it not discoverable
+ // and not connectable. This way the Bluetooth Module can be quickly
+ // switched on if needed
+ private static final int TURN_HOT = 101;
+ // USER_TURN_ON is changed to TURN_ON_CONTINUE after we broadcast the
+ // state change intent so that we will not broadcast the intent again in
+ // other state
+ private static final int TURN_ON_CONTINUE = 102;
+ // Unload firmware, turning off Bluetooth module power
+ private static final int TURN_COLD = 103;
+ // For NFC, turn on bluetooth for certain process
+ private static final int TURN_ON_FOR_PRIVILEGED = 104;
+
+ private Context mContext;
+ private BluetoothService mBluetoothService;
+ private BluetoothEventLoop mEventLoop;
+
+ private BluetoothOn mBluetoothOn;
+ private Switching mSwitching;
+ private HotOff mHotOff;
+ private WarmUp mWarmUp;
+ private PowerOff mPowerOff;
+
+ // this is the BluetoothAdapter state that reported externally
+ private int mPublicState;
+
+ BluetoothAdapterStateMachine(Context context, BluetoothService bluetoothService,
+ BluetoothAdapter bluetoothAdapter) {
+ super(TAG);
+ mContext = context;
+ mBluetoothService = bluetoothService;
+ mEventLoop = new BluetoothEventLoop(context, bluetoothAdapter, bluetoothService, this);
+
+ mBluetoothOn = new BluetoothOn();
+ mSwitching = new Switching();
+ mHotOff = new HotOff();
+ mWarmUp = new WarmUp();
+ mPowerOff = new PowerOff();
+
+ addState(mBluetoothOn);
+ addState(mSwitching);
+ addState(mHotOff);
+ addState(mWarmUp);
+ addState(mPowerOff);
+ setInitialState(mPowerOff);
+ mPublicState = BluetoothAdapter.STATE_OFF;
+
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ sendMessage(TURN_HOT);
+ }
+ }
+
+ /**
+ * Bluetooth module's power is off, firmware is not loaded.
+ */
+ private class PowerOff extends State {
+ private boolean mPersistSwitchOn = false;
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter PowerOff: " + mPersistSwitchOn);
+ mPersistSwitchOn = false;
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("PowerOff process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_ON:
+ // starts turning on BT module, broadcast this out
+ transitionTo(mWarmUp);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ if (prepareBluetooth()) {
+ // this is user request, save the setting
+ if ((Boolean) message.obj) {
+ mPersistSwitchOn = true;
+ }
+ // We will continue turn the BT on all the way to the BluetoothOn state
+ deferMessage(obtainMessage(TURN_ON_CONTINUE));
+ } else {
+ Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+ transitionTo(mPowerOff);
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ }
+ break;
+ case TURN_HOT:
+ if (prepareBluetooth()) {
+ transitionTo(mWarmUp);
+ }
+ break;
+ case AIRPLANE_MODE_OFF:
+ if (getBluetoothPersistedSetting()) {
+ // starts turning on BT module, broadcast this out
+ transitionTo(mWarmUp);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ if (prepareBluetooth()) {
+ // We will continue turn the BT on all the way to the BluetoothOn state
+ deferMessage(obtainMessage(TURN_ON_CONTINUE));
+ transitionTo(mWarmUp);
+ } else {
+ Log.e(TAG, "failed to prepare bluetooth, abort turning on");
+ transitionTo(mPowerOff);
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ }
+ }
+ break;
+ case AIRPLANE_MODE_ON: // ignore
+ case USER_TURN_OFF: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ /**
+ * Turn on Bluetooth Module, Load firmware, and do all the preparation
+ * needed to get the Bluetooth Module ready but keep it not discoverable
+ * and not connectable.
+ * The last step of this method sets up the local service record DB.
+ * There will be a event reporting the status of the SDP setup.
+ */
+ private boolean prepareBluetooth() {
+ if (mBluetoothService.enableNative() != 0) {
+ return false;
+ }
+
+ // try to start event loop, give 2 attempts
+ int retryCount = 2;
+ boolean eventLoopStarted = false;
+ while ((retryCount-- > 0) && !eventLoopStarted) {
+ mEventLoop.start();
+ // it may take a moment for the other thread to do its
+ // thing. Check periodically for a while.
+ int pollCount = 5;
+ while ((pollCount-- > 0) && !eventLoopStarted) {
+ if (mEventLoop.isEventLoopRunning()) {
+ eventLoopStarted = true;
+ break;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+ }
+
+ if (!eventLoopStarted) {
+ mBluetoothService.disableNative();
+ return false;
+ }
+
+ // get BluetoothService ready
+ if (!mBluetoothService.prepareBluetooth()) {
+ mEventLoop.stop();
+ mBluetoothService.disableNative();
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Turning on Bluetooth module's power, loading firmware, starting
+ * event loop thread to listen on Bluetooth module event changes.
+ */
+ private class WarmUp extends State {
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter WarmUp");
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("WarmUp process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case SERVICE_RECORD_LOADED:
+ transitionTo(mHotOff);
+ break;
+ case USER_TURN_ON: // handle this at HotOff state
+ case TURN_ON_CONTINUE: // Once in HotOff state, continue turn bluetooth
+ // on to the BluetoothOn state
+ case AIRPLANE_MODE_ON:
+ case AIRPLANE_MODE_OFF:
+ deferMessage(message);
+ break;
+ case USER_TURN_OFF: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+ /**
+ * Bluetooth Module has powered, firmware loaded, event loop started,
+ * SDP loaded, but the modules stays non-discoverable and
+ * non-connectable.
+ */
+ private class HotOff extends State {
+ private boolean mPersistSwitchOn = false;
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter HotOff: " + mPersistSwitchOn);
+ mPersistSwitchOn = false;
+ }
+
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("HotOff process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_ON:
+ if ((Boolean) message.obj) {
+ mPersistSwitchOn = true;
+ }
+ // let it fall to TURN_ON_CONTINUE:
+ case TURN_ON_CONTINUE:
+ mBluetoothService.switchConnectable(true);
+ transitionTo(mSwitching);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ break;
+ case AIRPLANE_MODE_ON:
+ case TURN_COLD:
+ mBluetoothService.shutoffBluetooth();
+ mEventLoop.stop();
+ transitionTo(mPowerOff);
+ // ASSERT no support of config_bluetooth_adapter_quick_switch
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ break;
+ case AIRPLANE_MODE_OFF:
+ if (getBluetoothPersistedSetting()) {
+ mBluetoothService.switchConnectable(true);
+ transitionTo(mSwitching);
+ broadcastState(BluetoothAdapter.STATE_TURNING_ON);
+ }
+ break;
+ case USER_TURN_OFF: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+ private class Switching extends State {
+
+ @Override
+ public void enter() {
+ int what = getCurrentMessage().what;
+ if (DBG) log("Enter Switching: " + what);
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("Switching process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case BECOME_PAIRABLE:
+ if (mPowerOff.mPersistSwitchOn || mHotOff.mPersistSwitchOn) {
+ persistSwitchSetting(true);
+ mPowerOff.mPersistSwitchOn = mHotOff.mPersistSwitchOn = false;
+ }
+ String[] propVal = {"Pairable", mBluetoothService.getProperty("Pairable")};
+ mEventLoop.onPropertyChanged(propVal);
+
+ // run bluetooth now that it's turned on
+ mBluetoothService.runBluetooth();
+ transitionTo(mBluetoothOn);
+ broadcastState(BluetoothAdapter.STATE_ON);
+ break;
+ case BECOME_NON_PAIRABLE:
+ if (mBluetoothService.getAdapterConnectionState() ==
+ BluetoothAdapter.STATE_DISCONNECTED) {
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ }
+ break;
+ case ALL_DEVICES_DISCONNECTED:
+ if (mBluetoothService.getScanMode() == BluetoothAdapter.SCAN_MODE_NONE) {
+ transitionTo(mHotOff);
+ finishSwitchingOff();
+ }
+ break;
+ case USER_TURN_ON:
+ case AIRPLANE_MODE_OFF:
+ case AIRPLANE_MODE_ON:
+ case USER_TURN_OFF:
+ deferMessage(message);
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ private void finishSwitchingOff() {
+ if (mBluetoothOn.mPersistBluetoothOff) {
+ persistSwitchSetting(false);
+ mBluetoothOn.mPersistBluetoothOff = false;
+ }
+ mBluetoothService.finishDisable();
+ if (mContext.getResources().getBoolean
+ (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {
+ broadcastState(BluetoothAdapter.STATE_OFF);
+ } else {
+ deferMessage(obtainMessage(TURN_COLD));
+ }
+ }
+ }
+
+ private class BluetoothOn extends State {
+ private boolean mPersistBluetoothOff = false;
+
+ @Override
+ public void enter() {
+ if (DBG) log("Enter BluetoothOn: " + mPersistBluetoothOff);
+ mPersistBluetoothOff = false;
+ }
+ @Override
+ public boolean processMessage(Message message) {
+ if (DBG) log("BluetoothOn process message: " + message.what);
+
+ boolean retValue = HANDLED;
+ switch(message.what) {
+ case USER_TURN_OFF:
+ if ((Boolean) message.obj) {
+ mPersistBluetoothOff = true;
+ }
+ // let it fall through to AIRPLANE_MODE_ON
+ case AIRPLANE_MODE_ON:
+ transitionTo(mSwitching);
+ broadcastState(BluetoothAdapter.STATE_TURNING_OFF);
+ mBluetoothService.switchConnectable(false);
+ mBluetoothService.disconnectDevices();
+ // we turn all the way to PowerOff with AIRPLANE_MODE_ON
+ if (message.what == AIRPLANE_MODE_ON) {
+ deferMessage(obtainMessage(AIRPLANE_MODE_ON));
+ }
+ break;
+ case AIRPLANE_MODE_OFF: // ignore
+ case USER_TURN_ON: // ignore
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ return retValue;
+ }
+
+ }
+
+ /**
+ * Return the public BluetoothAdapter state
+ */
+ int getBluetoothAdapterState() {
+ return mPublicState;
+ }
+
+ BluetoothEventLoop getBluetoothEventLoop() {
+ return mEventLoop;
+ }
+
+ private void persistSwitchSetting(boolean setOn) {
+ long origCallerIdentityToken = Binder.clearCallingIdentity();
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.BLUETOOTH_ON,
+ setOn ? 1 : 0);
+ Binder.restoreCallingIdentity(origCallerIdentityToken);
+ }
+
+ private boolean getBluetoothPersistedSetting() {
+ ContentResolver contentResolver = mContext.getContentResolver();
+ return (Settings.Secure.getInt(contentResolver,
+ Settings.Secure.BLUETOOTH_ON, 0) > 0);
+ }
+
+ private void broadcastState(int newState) {
+
+ if (DBG) log("Bluetooth state " + mPublicState + " -> " + newState);
+ if (mPublicState == newState) {
+ return;
+ }
+
+ Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
+ intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mPublicState);
+ intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mPublicState = newState;
+
+ mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
+ }
+
+ private void dump(PrintWriter pw) {
+ IState currentState = getCurrentState();
+ if (currentState == mPowerOff) {
+ pw.println("Bluetooth OFF - power down\n");
+ } else if (currentState == mWarmUp) {
+ pw.println("Bluetooth OFF - warm up\n");
+ } else if (currentState == mHotOff) {
+ pw.println("Bluetooth OFF - hot but off\n");
+ } else if (currentState == mSwitching) {
+ pw.println("Bluetooth Switching\n");
+ } else if (currentState == mBluetoothOn) {
+ pw.println("Bluetooth ON\n");
+ } else {
+ pw.println("ERROR: Bluetooth UNKNOWN STATE ");
+ }
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index f345a6a..107a2a9 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -52,6 +52,7 @@ class BluetoothEventLoop {
private final HashMap<String, Integer> mAuthorizationAgentRequestData;
private final BluetoothService mBluetoothService;
private final BluetoothAdapter mAdapter;
+ private final BluetoothAdapterStateMachine mBluetoothState;
private BluetoothA2dp mA2dp;
private BluetoothInputDevice mInputDevice;
private final Context mContext;
@@ -107,9 +108,11 @@ class BluetoothEventLoop {
private static native void classInitNative();
/* package */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
- BluetoothService bluetoothService) {
+ BluetoothService bluetoothService,
+ BluetoothAdapterStateMachine bluetoothState) {
mBluetoothService = bluetoothService;
mContext = context;
+ mBluetoothState = bluetoothState;
mPasskeyAgentRequestData = new HashMap<String, Integer>();
mAuthorizationAgentRequestData = new HashMap<String, Integer>();
mAdapter = adapter;
@@ -299,8 +302,8 @@ class BluetoothEventLoop {
/**
* Called by native code on a PropertyChanged signal from
- * org.bluez.Adapter. This method is also called from Java at
- * {@link BluetoothService.EnableThread#run()} to set the "Pairable"
+ * org.bluez.Adapter. This method is also called from
+ * {@link BluetoothAdapterStateMachine} to set the "Pairable"
* property when Bluetooth is enabled.
*
* @param propValues a string array containing the key and one or more
@@ -334,6 +337,15 @@ class BluetoothEventLoop {
return;
adapterProperties.setProperty(name, propValues[1]);
+
+ if (name.equals("Pairable")) {
+ if (pairable.equals("true")) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECOME_PAIRABLE);
+ } else {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.BECOME_NON_PAIRABLE);
+ }
+ }
+
int mode = BluetoothService.bluezStringToScanMode(
pairable.equals("true"),
discoverable.equals("true"));
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index d68d8ba..34f1971 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -91,7 +91,7 @@ public class BluetoothService extends IBluetooth.Stub {
private BluetoothPan mPan;
private boolean mIsAirplaneSensitive;
private boolean mIsAirplaneToggleable;
- private int mBluetoothState;
+ private BluetoothAdapterStateMachine mBluetoothState;
private boolean mRestart = false; // need to call enable() after disable()
private boolean mIsDiscovering;
private int[] mAdapterSdpHandles;
@@ -111,9 +111,8 @@ public class BluetoothService extends IBluetooth.Stub {
private static final String SHARED_PREFERENCE_DOCK_ADDRESS = "dock_bluetooth_address";
private static final String SHARED_PREFERENCES_NAME = "bluetooth_service_settings";
- private static final int MESSAGE_FINISH_DISABLE = 1;
- private static final int MESSAGE_UUID_INTENT = 2;
- private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3;
+ private static final int MESSAGE_UUID_INTENT = 1;
+ private static final int MESSAGE_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 2;
// The time (in millisecs) to delay the pairing attempt after the first
// auto pairing attempt fails. We use an exponential delay with
@@ -206,7 +205,6 @@ public class BluetoothService extends IBluetooth.Stub {
disableNative();
}
- mBluetoothState = BluetoothAdapter.STATE_OFF;
mIsDiscovering = false;
mBondState = new BluetoothBondState(context, this);
@@ -306,7 +304,9 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized void initAfterRegistration() {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
+ mBluetoothState = new BluetoothAdapterStateMachine(mContext, this, mAdapter);
+ mBluetoothState.start();
+ mEventLoop = mBluetoothState.getBluetoothEventLoop();
}
public synchronized void initAfterA2dpRegistration() {
@@ -329,16 +329,16 @@ public class BluetoothService extends IBluetooth.Stub {
}
private boolean isEnabledInternal() {
- return mBluetoothState == BluetoothAdapter.STATE_ON;
+ return (getBluetoothStateInternal() == BluetoothAdapter.STATE_ON);
}
public int getBluetoothState() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothState;
+ return getBluetoothStateInternal();
}
int getBluetoothStateInternal() {
- return mBluetoothState;
+ return mBluetoothState.getBluetoothAdapterState();
}
/**
@@ -356,7 +356,9 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized boolean disable(boolean saveSetting) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
- switch (mBluetoothState) {
+ int adapterState = getBluetoothStateInternal();
+
+ switch (adapterState) {
case BluetoothAdapter.STATE_OFF:
return true;
case BluetoothAdapter.STATE_ON:
@@ -364,27 +366,12 @@ public class BluetoothService extends IBluetooth.Stub {
default:
return false;
}
- if (mEnableThread != null && mEnableThread.isAlive()) {
- return false;
- }
-
- setBluetoothState(BluetoothAdapter.STATE_TURNING_OFF);
-
- if (mAdapterSdpHandles != null) removeReservedServiceRecordsNative(mAdapterSdpHandles);
- setBluetoothTetheringNative(false, BluetoothPanProfileHandler.NAP_ROLE,
- BluetoothPanProfileHandler.NAP_BRIDGE);
-
- // Allow 3 seconds for profiles to gracefully disconnect
- // TODO: Introduce a callback mechanism so that each profile can notify
- // BluetoothService when it is done shutting down
- disconnectDevices();
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_OFF, saveSetting);
return true;
}
- private synchronized void disconnectDevices() {
+ synchronized void disconnectDevices() {
// Disconnect devices handled by BluetoothService.
for (BluetoothDevice device: getConnectedInputDevices()) {
disconnectInputDevice(device);
@@ -395,14 +382,11 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
- private synchronized void finishDisable(boolean saveSetting) {
- if (mBluetoothState != BluetoothAdapter.STATE_TURNING_OFF) {
- return;
- }
- mEventLoop.stop();
- tearDownNativeDataNative();
- disableNative();
-
+ /**
+ * The Bluetooth has been turned off, but hot. Do bonding, profile,
+ * and internal cleanup
+ */
+ synchronized void finishDisable() {
// mark in progress bondings as cancelled
for (String address : mBondState.listInState(BluetoothDevice.BOND_BONDING)) {
mBondState.setBondState(address, BluetoothDevice.BOND_NONE,
@@ -430,12 +414,6 @@ public class BluetoothService extends IBluetooth.Stub {
mAdapterUuids = null;
mAdapterSdpHandles = null;
- if (saveSetting) {
- persistBluetoothOnSetting(false);
- }
-
- setBluetoothState(BluetoothAdapter.STATE_OFF);
-
// Log bluetooth off to battery stats.
long ident = Binder.clearCallingIdentity();
try {
@@ -451,6 +429,18 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
+ /**
+ * power off Bluetooth
+ */
+ synchronized void shutoffBluetooth() {
+ tearDownNativeDataNative();
+ disableNative();
+ if (mRestart) {
+ mRestart = false;
+ enable();
+ }
+ }
+
/** Bring up BT and persist BT on in settings */
public boolean enable() {
return enable(true);
@@ -471,21 +461,29 @@ public class BluetoothService extends IBluetooth.Stub {
if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
return false;
}
- if (mBluetoothState != BluetoothAdapter.STATE_OFF) {
- return false;
- }
- if (mEnableThread != null && mEnableThread.isAlive()) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.USER_TURN_ON, saveSetting);
+ return true;
+ }
+
+ /**
+ * Turn on Bluetooth Module, Load firmware, and do all the preparation
+ * needed to get the Bluetooth Module ready but keep it not discoverable
+ * and not connectable.
+ */
+ /* package */ synchronized boolean prepareBluetooth() {
+ if (!setupNativeDataNative()) {
return false;
}
- setBluetoothState(BluetoothAdapter.STATE_TURNING_ON);
- mEnableThread = new EnableThread(saveSetting);
- mEnableThread.start();
+ mIsDiscovering = false;
+
+ switchConnectable(false);
+ updateSdpRecords();
return true;
}
/** Forcibly restart Bluetooth if it is on */
/* package */ synchronized void restart() {
- if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+ if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
return;
}
mRestart = true;
@@ -494,30 +492,10 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
- private synchronized void setBluetoothState(int state) {
- if (state == mBluetoothState) {
- return;
- }
-
- if (DBG) Log.d(TAG, "Bluetooth state " + mBluetoothState + " -> " + state);
-
- Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED);
- intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, mBluetoothState);
- intent.putExtra(BluetoothAdapter.EXTRA_STATE, state);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-
- mBluetoothState = state;
-
- mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- }
-
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MESSAGE_FINISH_DISABLE:
- finishDisable(msg.arg1 != 0);
- break;
case MESSAGE_UUID_INTENT:
String address = (String)msg.obj;
if (address != null) {
@@ -545,65 +523,6 @@ public class BluetoothService extends IBluetooth.Stub {
}
};
- private EnableThread mEnableThread;
-
- private class EnableThread extends Thread {
- private final boolean mSaveSetting;
- public EnableThread(boolean saveSetting) {
- mSaveSetting = saveSetting;
- }
- public void run() {
- boolean res = (enableNative() == 0);
- if (res) {
- int retryCount = 2;
- boolean running = false;
- while ((retryCount-- > 0) && !running) {
- mEventLoop.start();
- // it may take a moment for the other thread to do its
- // thing. Check periodically for a while.
- int pollCount = 5;
- while ((pollCount-- > 0) && !running) {
- if (mEventLoop.isEventLoopRunning()) {
- running = true;
- break;
- }
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {}
- }
- }
- if (!running) {
- Log.e(TAG, "bt EnableThread giving up");
- res = false;
- disableNative();
- }
- }
-
- if (res) {
- if (!setupNativeDataNative()) {
- return;
- }
- if (mSaveSetting) {
- persistBluetoothOnSetting(true);
- }
-
- mIsDiscovering = false;
- mBondState.readAutoPairingData();
- mBondState.initBondState();
- initProfileState();
-
- // This should be the last step of the the enable thread.
- // Because this adds SDP records which asynchronously
- // broadcasts the Bluetooth On State in updateBluetoothState.
- // So we want all internal state setup before this.
- updateSdpRecords();
- } else {
- setBluetoothState(BluetoothAdapter.STATE_OFF);
- }
- mEnableThread = null;
- }
- }
-
private synchronized void addReservedSdpRecords(final ArrayList<ParcelUuid> uuids) {
//Register SDP records.
int[] svcIdentifiers = new int[uuids.size()];
@@ -650,38 +569,37 @@ public class BluetoothService extends IBluetooth.Stub {
* for adapter comes in with UUID property.
* @param uuidsThe uuids of adapter as reported by Bluez.
*/
- synchronized void updateBluetoothState(String uuids) {
- if (mBluetoothState == BluetoothAdapter.STATE_TURNING_ON) {
- ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
-
- if (mAdapterUuids != null &&
- BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
- setBluetoothState(BluetoothAdapter.STATE_ON);
- autoConnect();
- String[] propVal = {"Pairable", getProperty("Pairable")};
- mEventLoop.onPropertyChanged(propVal);
-
- // Log bluetooth on to battery stats.
- long ident = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteBluetoothOn();
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ /*package*/ synchronized void updateBluetoothState(String uuids) {
+ ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);
- if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
- disable(false);
- }
- }
+ if (mAdapterUuids != null &&
+ BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);
}
}
- private void persistBluetoothOnSetting(boolean bluetoothOn) {
- long origCallerIdentityToken = Binder.clearCallingIdentity();
- Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
- bluetoothOn ? 1 : 0);
- Binder.restoreCallingIdentity(origCallerIdentityToken);
+ /**
+ * This method is called immediately after Bluetooth module is turned on.
+ * It starts auto-connection and places bluetooth on sign onto the battery
+ * stats
+ */
+ /*package*/ void runBluetooth() {
+ mIsDiscovering = false;
+ mBondState.readAutoPairingData();
+ mBondState.initBondState();
+ initProfileState();
+
+ autoConnect();
+
+ // Log bluetooth on to battery stats.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mBatteryStats.noteBluetoothOn();
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
/*package*/ synchronized boolean attemptAutoPair(String address) {
@@ -818,6 +736,26 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized boolean setScanMode(int mode, int duration) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
"Need WRITE_SECURE_SETTINGS permission");
+ return setScanMode(mode, duration, true);
+ }
+
+ /**
+ * @param on true set the local Bluetooth module to be connectable
+ * but not dicoverable
+ * false set the local Bluetooth module to be not connectable
+ * and not dicoverable
+ */
+ /*package*/ synchronized void switchConnectable(boolean on) {
+ if (on) {
+ // 0 is a dummy value, does not apply for SCAN_MODE_CONNECTABLE
+ setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE, 0, false);
+ } else {
+ // 0 is a dummy value, does not apply for SCAN_MODE_NONE
+ setScanMode(BluetoothAdapter.SCAN_MODE_NONE, 0, false);
+ }
+ }
+
+ private synchronized boolean setScanMode(int mode, int duration, boolean allowOnlyInOnState) {
boolean pairable;
boolean discoverable;
@@ -839,9 +777,15 @@ public class BluetoothService extends IBluetooth.Stub {
Log.w(TAG, "Requested invalid scan mode " + mode);
return false;
}
- setPropertyBoolean("Pairable", pairable);
- setPropertyBoolean("Discoverable", discoverable);
+ if (allowOnlyInOnState) {
+ setPropertyBoolean("Pairable", pairable);
+ setPropertyBoolean("Discoverable", discoverable);
+ } else {
+ // allowed to set the property through native layer directly
+ setAdapterPropertyBooleanNative("Pairable", pairable ? 1 : 0);
+ setAdapterPropertyBooleanNative("Discoverable", discoverable ? 1 : 0);
+ }
return true;
}
@@ -1569,14 +1513,10 @@ public class BluetoothService extends IBluetooth.Stub {
ContentResolver resolver = context.getContentResolver();
// Query the airplane mode from Settings.System just to make sure that
// some random app is not sending this intent and disabling bluetooth
- boolean enabled = !isAirplaneModeOn();
- // If bluetooth is currently expected to be on, then enable or disable bluetooth
- if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
- if (enabled) {
- enable(false);
- } else {
- disable(false);
- }
+ if (isAirplaneModeOn()) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_ON);
+ } else {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.AIRPLANE_MODE_OFF);
}
} else if (Intent.ACTION_DOCK_EVENT.equals(action)) {
int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -1650,8 +1590,7 @@ public class BluetoothService extends IBluetooth.Stub {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- dumpBluetoothState(pw);
- if (mBluetoothState != BluetoothAdapter.STATE_ON) {
+ if (getBluetoothStateInternal() != BluetoothAdapter.STATE_ON) {
return;
}
@@ -1840,25 +1779,6 @@ public class BluetoothService extends IBluetooth.Stub {
}
}
- private void dumpBluetoothState(PrintWriter pw) {
- switch(mBluetoothState) {
- case BluetoothAdapter.STATE_OFF:
- pw.println("Bluetooth OFF\n");
- break;
- case BluetoothAdapter.STATE_TURNING_ON:
- pw.println("Bluetooth TURNING ON\n");
- break;
- case BluetoothAdapter.STATE_TURNING_OFF:
- pw.println("Bluetooth TURNING OFF\n");
- break;
- case BluetoothAdapter.STATE_ON:
- pw.println("Bluetooth ON\n");
- break;
- default:
- pw.println("Bluetooth UNKNOWN STATE " + mBluetoothState);
- }
- }
-
private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -2389,7 +2309,7 @@ public class BluetoothService extends IBluetooth.Stub {
public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
int prevState) {
// Since this is a binder call check if Bluetooth is on still
- if (mBluetoothState == BluetoothAdapter.STATE_OFF) return;
+ if (getBluetoothStateInternal() == BluetoothAdapter.STATE_OFF) return;
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
if (!validateProfileConnectionState(state) ||
@@ -2405,6 +2325,10 @@ public class BluetoothService extends IBluetooth.Stub {
mAdapterConnectionState = state;
+ if (state == BluetoothProfile.STATE_DISCONNECTED) {
+ mBluetoothState.sendMessage(BluetoothAdapterStateMachine.ALL_DEVICES_DISCONNECTED);
+ }
+
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
@@ -2598,8 +2522,8 @@ public class BluetoothService extends IBluetooth.Stub {
/*package*/ native String getAdapterPathNative();
private native int isEnabledNative();
- private native int enableNative();
- private native int disableNative();
+ /*package*/ native int enableNative();
+ /*package*/ native int disableNative();
/*package*/ native Object[] getAdapterPropertiesNative();
private native Object[] getDevicePropertiesNative(String objectPath);
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index 6ac99ca..270f512 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -36,7 +36,8 @@ import java.lang.ref.WeakReference;
*/
public abstract class SpellCheckerService extends Service {
private static final String TAG = SpellCheckerService.class.getSimpleName();
- public static final String SERVICE_INTERFACE = SpellCheckerService.class.getName();
+ public static final String SERVICE_INTERFACE =
+ "android.service.textservice.SpellCheckerService";
private final SpellCheckerServiceBinder mBinder = new SpellCheckerServiceBinder(this);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index c913bb3..836867b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -161,6 +161,9 @@ public class Surface implements Parcelable {
*/
public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001;
+ // The mSurfaceControl will only be present for Surfaces used by the window
+ // server or system processes. When this class is parceled we defer to the
+ // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface.
@SuppressWarnings("unused")
private int mSurfaceControl;
@SuppressWarnings("unused")
@@ -202,6 +205,19 @@ public class Surface implements Parcelable {
native private static void nativeClassInit();
static { nativeClassInit(); }
+ /**
+ * Create Surface from a SurfaceTexture.
+ *
+ * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface.
+ * @hide
+ */
+ public Surface(SurfaceTexture surfaceTexture) {
+ if (DEBUG_RELEASE) {
+ mCreationStack = new Exception();
+ }
+ mCanvas = new CompatibleCanvas();
+ initFromSurfaceTexture(surfaceTexture);
+ }
/**
* create a surface
@@ -505,5 +521,7 @@ public class Surface implements Parcelable {
private native void init(Parcel source);
+ private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
+
private native int getIdentity();
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c68b01c..dbb19e4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4280,6 +4280,36 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
/**
+ * Set whether or not this view should account for system screen decorations
+ * such as the status bar and inset its content. This allows this view to be
+ * positioned in absolute screen coordinates and remain visible to the user.
+ *
+ * <p>This should only be used by top-level window decor views.
+ *
+ * @param fitSystemWindows true to inset content for system screen decorations, false for
+ * default behavior.
+ *
+ * @attr ref android.R.styleable#View_fitsSystemWindows
+ */
+ public void setFitsSystemWindows(boolean fitSystemWindows) {
+ setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
+ }
+
+ /**
+ * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
+ * will account for system screen decorations such as the status bar and inset its
+ * content. This allows the view to be positioned in absolute screen coordinates
+ * and remain visible to the user.
+ *
+ * @return true if this view will adjust its content bounds for system screen decorations.
+ *
+ * @attr ref android.R.styleable#View_fitsSystemWindows
+ */
+ public boolean fitsSystemWindows() {
+ return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
+ }
+
+ /**
* Returns the visibility status for this view.
*
* @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 83c73cb..a80c2a7 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -67,13 +67,17 @@ public final class AccessibilityManager {
private static final String LOG_TAG = "AccessibilityManager";
+ /** @hide */
+ public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
+
+ /** @hide */
+ public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
+
static final Object sInstanceSync = new Object();
private static AccessibilityManager sInstance;
- private static final int DO_SET_ACCESSIBILITY_ENABLED = 10;
-
- private static final int DO_SET_TOUCH_EXPLORATION_ENABLED = 20;
+ private static final int DO_SET_STATE = 10;
final IAccessibilityManager mService;
@@ -100,13 +104,8 @@ public final class AccessibilityManager {
}
final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
- public void setEnabled(boolean enabled) {
- mHandler.obtainMessage(DO_SET_ACCESSIBILITY_ENABLED, enabled ? 1 : 0, 0).sendToTarget();
- }
-
- public void setTouchExplorationEnabled(boolean enabled) {
- mHandler.obtainMessage(DO_SET_TOUCH_EXPLORATION_ENABLED,
- enabled ? 1 : 0, 0).sendToTarget();
+ public void setState(int state) {
+ mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget();
}
};
@@ -119,14 +118,8 @@ public final class AccessibilityManager {
@Override
public void handleMessage(Message message) {
switch (message.what) {
- case DO_SET_ACCESSIBILITY_ENABLED :
- final boolean isAccessibilityEnabled = (message.arg1 == 1);
- setAccessibilityState(isAccessibilityEnabled);
- return;
- case DO_SET_TOUCH_EXPLORATION_ENABLED :
- synchronized (mHandler) {
- mIsTouchExplorationEnabled = (message.arg1 == 1);
- }
+ case DO_SET_STATE :
+ setState(message.arg1);
return;
default :
Log.w(LOG_TAG, "Unknown message type: " + message.what);
@@ -163,8 +156,8 @@ public final class AccessibilityManager {
mService = service;
try {
- final boolean isEnabled = mService.addClient(mClient);
- setAccessibilityState(isEnabled);
+ final int stateFlags = mService.addClient(mClient);
+ setState(stateFlags);
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
}
@@ -341,6 +334,17 @@ public final class AccessibilityManager {
}
/**
+ * Sets the current state.
+ *
+ * @param stateFlags The state flags.
+ */
+ private void setState(int stateFlags) {
+ final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+ setAccessibilityState(accessibilityEnabled);
+ mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
+ }
+
+ /**
* Sets the enabled state.
*
* @param isEnabled The accessibility state.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 0e04471..6469b35 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -294,14 +294,14 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Gets the unique id identifying this node's parent.
+ * Gets the parent.
* <p>
* <strong>Note:</strong> It is a client responsibility to recycle the
* received info by calling {@link AccessibilityNodeInfo#recycle()}
* to avoid creating of multiple instances.
* </p>
*
- * @return The node's patent id.
+ * @return The parent.
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index b14f02a..c621ff6 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -34,7 +34,7 @@ import android.view.IWindow;
*/
interface IAccessibilityManager {
- boolean addClient(IAccessibilityManagerClient client);
+ int addClient(IAccessibilityManagerClient client);
boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index 4e69692..5e7e813 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -24,7 +24,5 @@ package android.view.accessibility;
*/
oneway interface IAccessibilityManagerClient {
- void setEnabled(boolean enabled);
-
- void setTouchExplorationEnabled(boolean enabled);
+ void setState(int stateFlags);
}
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 1205adf..d88a39f 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -18,8 +18,10 @@ package android.view.textservice;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -103,6 +105,24 @@ public final class SpellCheckerInfo implements Parcelable {
};
/**
+ * Load the user-displayed label for this spell checker.
+ *
+ * @param pm Supply a PackageManager used to load the spell checker's resources.
+ */
+ public CharSequence loadLabel(PackageManager pm) {
+ return mService.loadLabel(pm);
+ }
+
+ /**
+ * Load the user-displayed icon for this spell checker.
+ *
+ * @param pm Supply a PackageManager used to load the spell checker's resources.
+ */
+ public Drawable loadIcon(PackageManager pm) {
+ return mService.loadIcon(pm);
+ }
+
+ /**
* Used to make this class parcelable.
*/
@Override
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 9749416..229b414 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -97,4 +97,27 @@ public final class TextServicesManager {
}
return session;
}
+
+ /**
+ * @hide
+ */
+ public SpellCheckerInfo[] getEnabledSpellCheckers() {
+ try {
+ return sService.getEnabledSpellCheckers();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public SpellCheckerInfo getCurrentSpellChecker() {
+ try {
+ // Passing null as a locale for ICS
+ return sService.getCurrentSpellChecker(null);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
}
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index bb4d192..620973e 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -18,6 +18,7 @@ package android.webkit;
import android.content.Context;
import android.net.Uri;
+import android.provider.Settings;
import android.util.Log;
import java.io.InputStream;
@@ -38,7 +39,7 @@ class JniUtil {
private static boolean initialized = false;
- private static void checkIntialized() {
+ private static void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("Call CookieSyncManager::createInstance() or create a webview before using this class");
}
@@ -63,7 +64,7 @@ class JniUtil {
* @return String The application's database directory
*/
private static synchronized String getDatabaseDirectory() {
- checkIntialized();
+ checkInitialized();
if (sDatabaseDirectory == null)
sDatabaseDirectory = sContext.getDatabasePath("dummy").getParent();
@@ -76,7 +77,7 @@ class JniUtil {
* @return String The application's cache directory
*/
private static synchronized String getCacheDirectory() {
- checkIntialized();
+ checkInitialized();
if (sCacheDirectory == null)
sCacheDirectory = sContext.getCacheDir().getAbsolutePath();
@@ -166,5 +167,13 @@ class JniUtil {
return sUseChromiumHttpStack;
}
+ private static synchronized String getAutofillQueryUrl() {
+ checkInitialized();
+ // If the device has not checked in it won't have pulled down the system setting for the
+ // Autofill Url. In that case we will not make autofill server requests.
+ return Settings.Secure.getString(sContext.getContentResolver(),
+ Settings.Secure.WEB_AUTOFILL_QUERY_URL);
+ }
+
private static native boolean nativeUseChromiumHttpStack();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6a3b2ff..e24ab58 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4701,6 +4701,7 @@ public class WebView extends AbsoluteLayout
private Message mUpdateMessage;
private boolean mAutoFillable;
private boolean mAutoComplete;
+ private WebSettings mWebSettings;
public RequestFormData(String name, String url, Message msg,
boolean autoFillable, boolean autoComplete) {
@@ -4709,6 +4710,7 @@ public class WebView extends AbsoluteLayout
mUpdateMessage = msg;
mAutoFillable = autoFillable;
mAutoComplete = autoComplete;
+ mWebSettings = getSettings();
}
public void run() {
@@ -4718,8 +4720,7 @@ public class WebView extends AbsoluteLayout
// Note that code inside the adapter click handler in WebTextView depends
// on the AutoFill item being at the top of the drop down list. If you change
// the order, make sure to do it there too!
- WebSettings settings = getSettings();
- if (settings != null && settings.getAutoFillProfile() != null) {
+ if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) {
pastEntries.add(getResources().getText(
com.android.internal.R.string.autofill_this_form).toString() +
" " +
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 563fc26..36927ca 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -91,6 +91,7 @@ public class PopupWindow {
private boolean mLayoutInScreen;
private boolean mClipToScreen;
private boolean mAllowScrollingAnchorParent = true;
+ private boolean mLayoutInsetDecor = false;
private OnTouchListener mTouchInterceptor;
@@ -658,6 +659,22 @@ public class PopupWindow {
}
/**
+ * Allows the popup window to force the flag
+ * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
+ * This will cause the popup to inset its content to account for system windows overlaying
+ * the screen, such as the status bar.
+ *
+ * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
+ *
+ * @param enabled true if the popup's views should inset content to account for system windows,
+ * the way that decor views behave for full-screen windows.
+ * @hide
+ */
+ public void setLayoutInsetDecor(boolean enabled) {
+ mLayoutInsetDecor = enabled;
+ }
+
+ /**
* Set the layout type for this window. Should be one of the TYPE constants defined in
* {@link WindowManager.LayoutParams}.
*
@@ -942,6 +959,7 @@ public class PopupWindow {
if (mContext != null) {
p.packageName = mContext.getPackageName();
}
+ mPopupView.setFitsSystemWindows(mLayoutInsetDecor);
mWindowManager.addView(mPopupView, p);
}
@@ -1012,6 +1030,9 @@ public class PopupWindow {
if (mLayoutInScreen) {
curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
}
+ if (mLayoutInsetDecor) {
+ curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+ }
return curFlags;
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index b2d1a1e..55b73df 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -45,6 +45,7 @@ import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
+import android.view.CollapsibleActionView;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -58,18 +59,30 @@ import com.android.internal.R;
import java.util.WeakHashMap;
/**
- * A widget that provides a user interface for the user to enter a search query and submit a
- * request to a search provider. Shows a list of query suggestions or results, if
- * available, and allows the user to pick a suggestion or result to launch into.
+ * A widget that provides a user interface for the user to enter a search query and submit a request
+ * to a search provider. Shows a list of query suggestions or results, if available, and allows the
+ * user to pick a suggestion or result to launch into.
*
- * <p>For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
- * documentation.<p>
+ * <p>
+ * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it
+ * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean)
+ * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done.
+ * </p>
+ * <p>
+ * If you want the search field to always be visible, then call setIconifiedByDefault(false).
+ * </p>
*
+ * <p>
+ * For more information, see the <a href="{@docRoot}guide/topics/search/index.html">Search</a>
+ * documentation.
+ * <p>
+ *
+ * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
* @attr ref android.R.styleable#SearchView_iconifiedByDefault
* @attr ref android.R.styleable#SearchView_maxWidth
* @attr ref android.R.styleable#SearchView_queryHint
*/
-public class SearchView extends LinearLayout {
+public class SearchView extends LinearLayout implements CollapsibleActionView {
private static final boolean DBG = false;
private static final String LOG_TAG = "SearchView";
@@ -100,6 +113,7 @@ public class SearchView extends LinearLayout {
private int mMaxWidth;
private boolean mVoiceButtonEnabled;
private CharSequence mUserQuery;
+ private boolean mExpandedInActionView;
private SearchableInfo mSearchable;
private Bundle mAppSearchData;
@@ -623,7 +637,7 @@ public class SearchView extends LinearLayout {
final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
// Should we show the close button? It is not shown if there's no focus,
// field is not iconified by default and there is no text in it.
- final boolean showClose = hasText || mIconifiedByDefault;
+ final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
mCloseButton.setVisibility(showClose ? VISIBLE : INVISIBLE);
mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
}
@@ -1022,6 +1036,25 @@ public class SearchView extends LinearLayout {
super.onAttachedToWindow();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActionViewCollapsed() {
+ mQueryTextView.setText("");
+ setIconified(true);
+ mExpandedInActionView = false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onActionViewExpanded() {
+ mExpandedInActionView = true;
+ setIconified(false);
+ }
+
private void adjustDropDownSizeAndPosition() {
if (mDropDownAnchor.getWidth() > 1) {
Resources res = getContext().getResources();
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index b7565f3..0c80a11 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -34,6 +34,7 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
@@ -360,6 +361,13 @@ public class Switch extends CompoundButton {
}
}
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
+ event.getText().add(switchText.getText());
+ }
+
private Layout makeLayout(CharSequence text) {
return new StaticLayout(text, mTextPaint,
(int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)),
diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
index ad0c1ff..2a045e3 100644
--- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl
+++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl
@@ -32,4 +32,5 @@ interface ITextServicesManager {
in ITextServicesSessionListener tsListener,
in ISpellCheckerSessionListener scListener);
oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener);
+ SpellCheckerInfo[] getEnabledSpellCheckers();
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 0dc9293..4c1ca31 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -22,6 +22,7 @@
#include "android/graphics/GraphicsJNI.h"
#include <binder/IMemory.h>
+#include <gui/SurfaceTexture.h>
#include <surfaceflinger/SurfaceComposerClient.h>
#include <surfaceflinger/Surface.h>
#include <ui/Region.h>
@@ -38,6 +39,7 @@
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <utils/misc.h>
@@ -244,6 +246,19 @@ static void Surface_init(
setSurfaceControl(env, clazz, surface);
}
+static void Surface_initFromSurfaceTexture(
+ JNIEnv* env, jobject clazz, jobject jst)
+{
+ sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
+ sp<Surface> surface(new Surface(st));
+ if (surface == NULL) {
+ jniThrowException(env, OutOfResourcesException, NULL);
+ return;
+ }
+ setSurfaceControl(env, clazz, NULL);
+ setSurface(env, clazz, surface);
+}
+
static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
{
Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
@@ -761,10 +776,26 @@ static void Surface_writeToParcel(
return;
}
+ // The Java instance may have a SurfaceControl (in the case of the
+ // WindowManager or a system app). In that case, we defer to the
+ // SurfaceControl to send its ISurface. Otherwise, if the Surface is
+ // available we let it parcel itself. Finally, if the Surface is also
+ // NULL we fall back to using the SurfaceControl path which sends an
+ // empty surface; this matches legacy behavior.
const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
- SurfaceControl::writeSurfaceToParcel(control, parcel);
+ if (control != NULL) {
+ SurfaceControl::writeSurfaceToParcel(control, parcel);
+ } else {
+ sp<Surface> surface(Surface_getSurface(env, clazz));
+ if (surface != NULL) {
+ Surface::writeToParcel(surface, parcel);
+ } else {
+ SurfaceControl::writeSurfaceToParcel(NULL, parcel);
+ }
+ }
if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
- setSurfaceControl(env, clazz, 0);
+ setSurfaceControl(env, clazz, NULL);
+ setSurface(env, clazz, NULL);
}
}
@@ -784,6 +815,7 @@ static JNINativeMethod gSurfaceMethods[] = {
{"nativeClassInit", "()V", (void*)nativeClassInit },
{"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init },
{"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel },
+ {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
{"getIdentity", "()I", (void*)Surface_getIdentity },
{"destroy", "()V", (void*)Surface_destroy },
{"release", "()V", (void*)Surface_release },
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7d7aea9..b5fc55e 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2278,6 +2278,8 @@
<flag name="feedbackVisual" value="0x00000008" />
<!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_GENERIC} feedback. -->
<flag name="feedbackGeneric" value="0x00000010" />
+ <!-- Provides {@link android.accessibilityservice.AccessibilityServiceInfo#FEEDBACK_ALL_MASK} feedback. -->
+ <flag name="feedbackAllMask" value="0xffffffff" />
</attr>
<!-- The minimal period in milliseconds between two accessibility events of the same type
are sent to this serivce. This setting can be changed at runtime by calling
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2b2f356..65dce49 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -469,6 +469,10 @@
speech -->
<bool name="config_bluetooth_wide_band_speech">true</bool>
+ <!-- Boolean indicating if current platform supports quick switch-on/off of
+ Bluetooth Module -->
+ <bool name="config_bluetooth_adapter_quick_switch">true</bool>
+
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
diff --git a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
index bbf1696..4814c61 100644
--- a/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/RecycleAccessibilityEventTest.java
@@ -65,13 +65,13 @@ public class RecycleAccessibilityEventTest extends TestCase {
assertEquals(0, first.getText().size());
assertFalse(first.isChecked());
assertNull(first.getContentDescription());
- assertEquals(0, first.getItemCount());
+ assertEquals(-1, first.getItemCount());
assertEquals(AccessibilityEvent.INVALID_POSITION, first.getCurrentItemIndex());
assertFalse(first.isEnabled());
assertFalse(first.isPassword());
- assertEquals(0, first.getFromIndex());
- assertEquals(0, first.getAddedCount());
- assertEquals(0, first.getRemovedCount());
+ assertEquals(-1, first.getFromIndex());
+ assertEquals(-1, first.getAddedCount());
+ assertEquals(-1, first.getRemovedCount());
// get another event from the pool (this must be the recycled first)
AccessibilityEvent second = AccessibilityEvent.obtain();
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 134c208..2a8e725 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -211,7 +211,6 @@ protected:
// all slots.
void freeAllBuffers();
static bool isExternalFormat(uint32_t format);
- static GLenum getTextureTarget(uint32_t format);
private:
@@ -348,10 +347,6 @@ private:
// reset mCurrentTexture to INVALID_BUFFER_SLOT.
int mCurrentTexture;
- // mCurrentTextureTarget is the GLES texture target to be used with the
- // current texture.
- GLenum mCurrentTextureTarget;
-
// mCurrentTextureBuf is the graphic buffer of the current texture. It's
// possible that this buffer is not associated with any buffer slot, so we
// must track it separately in order to support the getCurrentBuffer method.
diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h
index 9c352ad..0460bbd 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -122,7 +122,10 @@ public:
uint32_t reserved[2];
};
+ explicit Surface(const sp<ISurfaceTexture>& st);
+
static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
+
static sp<Surface> readFromParcel(const Parcel& data);
static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid();
@@ -147,14 +150,14 @@ private:
Surface& operator = (Surface& rhs);
Surface(const Surface& rhs);
- Surface(const sp<SurfaceControl>& control);
+ explicit Surface(const sp<SurfaceControl>& control);
Surface(const Parcel& data, const sp<IBinder>& ref);
~Surface();
/*
* private stuff...
*/
- void init();
+ void init(const sp<ISurfaceTexture>& surfaceTexture);
static void cleanCachedSurfacesLocked();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index c4f9e53..ccf98e5 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -184,6 +184,7 @@ status_t SurfaceControl::writeSurfaceToParcel(
identity = control->mIdentity;
}
parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+ parcel->writeStrongBinder(NULL); // NULL ISurfaceTexture in this case.
parcel->writeInt32(identity);
return NO_ERROR;
}
@@ -192,7 +193,8 @@ sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
- mSurfaceData = new Surface(const_cast<SurfaceControl*>(this));
+ sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this));
+ mSurfaceData = new Surface(surface_control);
}
return mSurfaceData;
}
@@ -208,31 +210,58 @@ Surface::Surface(const sp<SurfaceControl>& surface)
mSurface(surface->mSurface),
mIdentity(surface->mIdentity)
{
- init();
+ sp<ISurfaceTexture> st;
+ if (mSurface != NULL) {
+ st = mSurface->getSurfaceTexture();
+ }
+ init(st);
}
Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref)
: SurfaceTextureClient()
{
- mSurface = interface_cast<ISurface>(ref);
+ mSurface = interface_cast<ISurface>(ref);
+ sp<IBinder> st_binder(parcel.readStrongBinder());
+ sp<ISurfaceTexture> st;
+ if (st_binder != NULL) {
+ st = interface_cast<ISurfaceTexture>(st_binder);
+ } else if (mSurface != NULL) {
+ st = mSurface->getSurfaceTexture();
+ }
+
mIdentity = parcel.readInt32();
- init();
+ init(st);
+}
+
+Surface::Surface(const sp<ISurfaceTexture>& st)
+ : SurfaceTextureClient(),
+ mSurface(NULL),
+ mIdentity(0)
+{
+ init(st);
}
status_t Surface::writeToParcel(
const sp<Surface>& surface, Parcel* parcel)
{
sp<ISurface> sur;
+ sp<ISurfaceTexture> st;
uint32_t identity = 0;
if (Surface::isValid(surface)) {
sur = surface->mSurface;
+ st = surface->getISurfaceTexture();
identity = surface->mIdentity;
- } else if (surface != 0 && surface->mSurface != 0) {
- LOGW("Parceling invalid surface with non-NULL ISurface as NULL: "
- "mSurface = %p, mIdentity = %d",
- surface->mSurface.get(), surface->mIdentity);
+ } else if (surface != 0 &&
+ (surface->mSurface != NULL ||
+ surface->getISurfaceTexture() != NULL)) {
+ LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: "
+ "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ",
+ surface->mSurface.get(), surface->getISurfaceTexture().get(),
+ surface->mIdentity);
}
- parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL);
+
+ parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL);
+ parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL);
parcel->writeInt32(identity);
return NO_ERROR;
@@ -249,8 +278,8 @@ sp<Surface> Surface::readFromParcel(const Parcel& data) {
surface = new Surface(data, binder);
sCachedSurfaces.add(binder, surface);
}
- if (surface->mSurface == 0) {
- surface = 0;
+ if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) {
+ surface = 0;
}
cleanCachedSurfacesLocked();
return surface;
@@ -267,10 +296,9 @@ void Surface::cleanCachedSurfacesLocked() {
}
}
-void Surface::init()
+void Surface::init(const sp<ISurfaceTexture>& surfaceTexture)
{
- if (mSurface != NULL) {
- sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture());
+ if (mSurface != NULL || surfaceTexture != NULL) {
LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface");
if (surfaceTexture != NULL) {
setISurfaceTexture(surfaceTexture);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index c190195..8d19957 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -86,7 +86,6 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
mClientBufferCount(0),
mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
mCurrentTexture(INVALID_BUFFER_SLOT),
- mCurrentTextureTarget(GL_TEXTURE_EXTERNAL_OES),
mCurrentTransform(0),
mCurrentTimestamp(0),
mNextTransform(0),
@@ -651,12 +650,8 @@ status_t SurfaceTexture::updateTexImage() {
LOGW("updateTexImage: clearing GL error: %#04x", error);
}
- GLenum target = getTextureTarget(mSlots[buf].mGraphicBuffer->format);
- if (target != mCurrentTextureTarget) {
- glDeleteTextures(1, &mTexName);
- }
- glBindTexture(target, mTexName);
- glEGLImageTargetTexture2DOES(target, (GLeglImageOES)image);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
bool failed = false;
while ((error = glGetError()) != GL_NO_ERROR) {
@@ -678,7 +673,6 @@ status_t SurfaceTexture::updateTexImage() {
// Update the SurfaceTexture state.
mCurrentTexture = buf;
- mCurrentTextureTarget = target;
mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
mCurrentCrop = mSlots[buf].mCrop;
mCurrentTransform = mSlots[buf].mTransform;
@@ -692,7 +686,7 @@ status_t SurfaceTexture::updateTexImage() {
mDequeueCondition.signal();
} else {
// We always bind the texture even if we don't update its contents.
- glBindTexture(mCurrentTextureTarget, mTexName);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
}
return OK;
@@ -717,20 +711,8 @@ bool SurfaceTexture::isExternalFormat(uint32_t format)
return false;
}
-GLenum SurfaceTexture::getTextureTarget(uint32_t format)
-{
- GLenum target = GL_TEXTURE_2D;
-#if defined(GL_OES_EGL_image_external)
- if (isExternalFormat(format)) {
- target = GL_TEXTURE_EXTERNAL_OES;
- }
-#endif
- return target;
-}
-
GLenum SurfaceTexture::getCurrentTextureTarget() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureTarget;
+ return GL_TEXTURE_EXTERNAL_OES;
}
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
@@ -959,12 +941,12 @@ void SurfaceTexture::dump(String8& result, const char* prefix,
}
snprintf(buffer, SIZE,
- "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d, target=0x%04x}\n"
+ "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
"%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
,
prefix, mCurrentCrop.left,
mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture, mCurrentTextureTarget,
+ mCurrentTransform, mCurrentTexture,
prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
mCurrentTransform, fifoSize, fifo.string()
);
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 0fac6cd..44babcf 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -832,9 +832,7 @@ TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
pt->requestExitAndWait();
}
-// XXX: This test is disabled because there are currently no drivers that can
-// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
-TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) {
const int texWidth = 64;
const int texHeight = 66;
@@ -871,26 +869,24 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35));
EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(23, 65, 231, 35, 231, 35));
EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35));
EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35));
EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231));
- EXPECT_TRUE(checkPixel(37, 33, 228, 38, 38, 38));
+ EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231));
EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231));
- EXPECT_TRUE(checkPixel(36, 47, 228, 35, 231, 231));
- EXPECT_TRUE(checkPixel(24, 63, 38, 228, 231, 35));
- EXPECT_TRUE(checkPixel(48, 3, 228, 228, 38, 35));
+ EXPECT_TRUE(checkPixel(37, 47, 231, 35, 231, 231));
+ EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35));
+ EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35));
EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231));
- EXPECT_TRUE(checkPixel(24, 25, 41, 41, 231, 231));
- EXPECT_TRUE(checkPixel(10, 9, 38, 38, 231, 231));
+ EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231));
+ EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231));
EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231));
- EXPECT_TRUE(checkPixel(56, 31, 38, 228, 231, 35));
+ EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35));
EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231));
}
-// XXX: This test is disabled because there are currently no drivers that can
-// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
-TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) {
const int texWidth = 64;
const int texHeight = 64;
@@ -944,9 +940,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) {
EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35));
}
-// XXX: This test is disabled because there are currently no drivers that can
-// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
-TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
+TEST_F(SurfaceTextureGLTest, TexturingFromGLFilledRGBABufferPow2) {
const int texWidth = 64;
const int texHeight = 64;
@@ -956,7 +950,7 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
mANW.get(), NULL);
ASSERT_EQ(EGL_SUCCESS, eglGetError());
- ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+ ASSERT_NE(EGL_NO_SURFACE, stcEglSurface);
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
mEglContext));
@@ -980,6 +974,8 @@ TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
eglSwapBuffers(mEglDisplay, stcEglSurface);
+ eglDestroySurface(mEglDisplay, stcEglSurface);
+
// Do the consumer side of things
EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
mEglContext));
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 31e4631..82e8d77 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -54,7 +54,8 @@ public class AudioFormat {
/** Default audio channel mask */
public static final int CHANNEL_OUT_DEFAULT = 1;
- // Channel mask definitions must be kept in sync with native values in include/media/AudioSystem.h
+ // Channel mask definitions must be kept in sync with native values
+ // in /system/core/include/system/audio.h
public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
public static final int CHANNEL_OUT_FRONT_CENTER = 0x10;
@@ -64,6 +65,25 @@ public class AudioFormat {
public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100;
public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200;
public static final int CHANNEL_OUT_BACK_CENTER = 0x400;
+ /** @hide */
+ public static final int CHANNEL_OUT_SIDE_LEFT = 0x800;
+ /** @hide */
+ public static final int CHANNEL_OUT_SIDE_RIGHT = 0x1000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_CENTER = 0x2000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_LEFT = 0x4000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_CENTER = 0x8000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_FRONT_RIGHT = 0x10000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_LEFT = 0x20000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_CENTER = 0x40000;
+ /** @hide */
+ public static final int CHANNEL_OUT_TOP_BACK_RIGHT = 0x80000;
+
public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
@@ -75,6 +95,12 @@ public class AudioFormat {
public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
+ /** @hide */
+ public static final int CHANNEL_OUT_7POINT1_SURROUND = (
+ CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
+ CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
+ CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
+ CHANNEL_OUT_LOW_FREQUENCY);
public static final int CHANNEL_IN_DEFAULT = 1;
public static final int CHANNEL_IN_LEFT = 0x4;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 482b437..95671bc 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -611,7 +611,7 @@ public class MediaPlayer
* needed. Not calling this method when playing back a video will
* result in only the audio track being played.
*
- * Either a surface or surface texture must be set if a display or video sink
+ * Either a surface holder or surface must be set if a display or video sink
* is needed. Not calling this method or {@link #setTexture(SurfaceTexture)}
* when playing back a video will result in only the audio track being played.
*
@@ -630,6 +630,27 @@ public class MediaPlayer
}
/**
+ * Sets the {@link Surface} to be used as the sink for the video portion of
+ * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not
+ * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}.
+ * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set.
+ *
+ * @param surface The {@link Surface} to be used for the video portion of the media.
+ *
+ * @hide Pending review by API council.
+ */
+ public void setSurface(Surface surface) {
+ if (mScreenOnWhilePlaying && surface != null && mSurface != null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
+ }
+ mSurfaceHolder = null;
+ mSurface = surface;
+ mParcelSurfaceTexture = null; // TODO(tedbo): Remove.
+ _setVideoSurfaceOrSurfaceTexture();
+ updateSurfaceScreenOn();
+ }
+
+ /**
* Sets the {@link SurfaceTexture} to be used as the sink for the
* video portion of the media. Either a surface or surface texture
* must be set if a video sink is needed. The same surface texture
@@ -665,7 +686,7 @@ public class MediaPlayer
* @param pst The {@link ParcelSurfaceTexture} to be used as the sink for
* the video portion of the media.
*
- * @hide Pending review by API council.
+ * @hide Pending removal when there are no more callers.
*/
public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) {
if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) {
@@ -1000,8 +1021,8 @@ public class MediaPlayer
*/
public void setScreenOnWhilePlaying(boolean screenOn) {
if (mScreenOnWhilePlaying != screenOn) {
- if (screenOn && mParcelSurfaceTexture != null) {
- Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
+ if (screenOn && mSurfaceHolder == null) {
+ Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
}
mScreenOnWhilePlaying = screenOn;
updateSurfaceScreenOn();
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 082dab3..fc8ab96 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -158,7 +158,7 @@
<!-- Checkbox label for application compatibility mode OFF (normal mode on tablets).
[CHAR LIMIT=25] -->
<string name="compat_mode_off">Stretch to fill screen</string>
-
+
<!-- Compatibility mode help screen: header text. [CHAR LIMIT=50] -->
<string name="compat_mode_help_header">Compatibility Zoom</string>
@@ -168,7 +168,7 @@
<!-- toast message displayed when a screenshot is saved to the Gallery. -->
<string name="screenshot_saving_toast">Screenshot saved to Gallery</string>
<!-- toast message displayed when we fail to take a screenshot. -->
- <string name="screenshot_failed_toast">Could not save screenshot</string>
+ <string name="screenshot_failed_toast">Could not save screenshot. External storage may be in use.</string>
<!-- Title for the USB function chooser in UsbPreferenceActivity. [CHAR LIMIT=30] -->
<string name="usb_preference_title">USB file transfer options</string>
@@ -299,5 +299,4 @@
<!-- Content description of the ringer silent icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_ringer_silent">Ringer silent.</string>
-
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 83a5578..02a955b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -87,7 +87,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
Context context = params[0].context;
Bitmap image = params[0].image;
- try{
+ try {
long currentTime = System.currentTimeMillis();
String date = new SimpleDateFormat("MM-dd-yy-kk-mm-ss").format(new Date(currentTime));
String imageDir = Environment.getExternalStoragePublicDirectory(
@@ -114,7 +114,9 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
out.close();
params[0].result = 0;
- }catch(IOException e){
+ } catch (Exception e) {
+ // IOException/UnsupportedOperationException may be thrown if external storage is not
+ // mounted
params[0].result = 1;
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index e0debf7..bfc3cdd 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2040,13 +2040,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mActionModePopup = new PopupWindow(mContext, null,
com.android.internal.R.attr.actionModePopupWindowStyle);
mActionModePopup.setLayoutInScreenEnabled(true);
+ mActionModePopup.setLayoutInsetDecor(true);
mActionModePopup.setClippingEnabled(false);
mActionModePopup.setContentView(mActionModeView);
mActionModePopup.setWidth(MATCH_PARENT);
TypedValue heightValue = new TypedValue();
mContext.getTheme().resolveAttribute(
- com.android.internal.R.attr.actionBarSize, heightValue, false);
+ com.android.internal.R.attr.actionBarSize, heightValue, true);
final int height = TypedValue.complexToDimensionPixelSize(heightValue.data,
mContext.getResources().getDisplayMetrics());
mActionModePopup.setHeight(height);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ae13ab5..b7f6adf 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2444,20 +2444,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (down) {
- // If the power key down was already triggered, take the screenshot
- if (mPowerDownTriggered) {
- // Dismiss the power-key longpress
- mHandler.removeCallbacks(mPowerLongPress);
- mPowerKeyHandled = true;
-
- // Take the screenshot
- takeScreenshot();
-
- // Prevent the event from being passed through to the current activity
- result &= ~ACTION_PASS_TO_USER;
- break;
+ if (isScreenOn) {
+ // If the power key down was already triggered, take the screenshot
+ if (mPowerDownTriggered) {
+ // Dismiss the power-key longpress
+ mHandler.removeCallbacks(mPowerLongPress);
+ mPowerKeyHandled = true;
+
+ // Take the screenshot
+ takeScreenshot();
+
+ // Prevent the event from being passed through to the current activity
+ result &= ~ACTION_PASS_TO_USER;
+ break;
+ }
+ mVolumeDownTriggered = true;
}
- mVolumeDownTriggered = true;
} else {
mVolumeDownTriggered = false;
}
@@ -2541,17 +2543,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
- // If the volume down key has been triggered, then just take the screenshot
- if (mVolumeDownTriggered) {
- // Take the screenshot
- takeScreenshot();
- mPowerKeyHandled = true;
-
- // Prevent the event from being passed through to the current activity
- break;
+ if (isScreenOn) {
+ // If the volume down key has been triggered, then just take the screenshot
+ if (mVolumeDownTriggered) {
+ // Take the screenshot
+ takeScreenshot();
+ mPowerKeyHandled = true;
+
+ // Prevent the event from being passed through to the current activity
+ break;
+ }
+ mPowerDownTriggered = true;
}
- mPowerDownTriggered = true;
-
ITelephony telephonyService = getTelephonyService();
boolean hungUp = false;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0323fe0..cb1f921 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1043,6 +1043,25 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args
return NO_ERROR;
}
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+ write(fd, buffer, strlen(buffer));
+
+ for (size_t i = 0; i < mEffectChains.size(); ++i) {
+ sp<EffectChain> chain = mEffectChains[i];
+ if (chain != 0) {
+ chain->dump(fd, args);
+ }
+ }
+ return NO_ERROR;
+}
+
+
// ----------------------------------------------------------------------------
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
@@ -1111,24 +1130,6 @@ status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>
return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
- write(fd, buffer, strlen(buffer));
-
- for (size_t i = 0; i < mEffectChains.size(); ++i) {
- sp<EffectChain> chain = mEffectChains[i];
- if (chain != 0) {
- chain->dump(fd, args);
- }
- }
- return NO_ERROR;
-}
-
status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -4178,6 +4179,7 @@ status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
write(fd, result.string(), result.size());
dumpBase(fd, args);
+ dumpEffectChains(fd, args);
return NO_ERROR;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fff4f06..e2cf946 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -285,6 +285,7 @@ private:
};
status_t dumpBase(int fd, const Vector<String16>& args);
+ status_t dumpEffectChains(int fd, const Vector<String16>& args);
// base for record and playback
class TrackBase : public AudioBufferProvider, public RefBase {
@@ -724,7 +725,6 @@ private:
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
status_t dumpTracks(int fd, const Vector<String16>& args);
- status_t dumpEffectChains(int fd, const Vector<String16>& args);
SortedVector< sp<Track> > mTracks;
// mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index 4a0c837..ffdc288 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -156,6 +156,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
final String curSpellCheckerId =
Settings.Secure.getString(mContext.getContentResolver(),
Settings.Secure.SPELL_CHECKER_SERVICE);
+ if (DBG) {
+ Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId);
+ }
if (TextUtils.isEmpty(curSpellCheckerId)) {
return null;
}
@@ -198,6 +201,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
+ public SpellCheckerInfo[] getEnabledSpellCheckers() {
+ return mSpellCheckerList.toArray(new SpellCheckerInfo[mSpellCheckerList.size()]);
+ }
+
+ @Override
public void finishSpellCheckerService(ISpellCheckerSessionListener listener) {
synchronized(mSpellCheckerMap) {
for (SpellCheckerBindGroup group : mSpellCheckerBindGroups.values()) {
@@ -208,6 +216,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
private void setCurrentSpellChecker(SpellCheckerInfo sci) {
+ if (DBG) {
+ Slog.w(TAG, "setCurrentSpellChecker: " + sci.getId());
+ }
if (sci == null || mSpellCheckerMap.containsKey(sci.getId())) return;
Settings.Secure.putString(mContext.getContentResolver(),
Settings.Secure.SPELL_CHECKER_SERVICE, sci == null ? "" : sci.getId());
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index bb9d15b..92647e6 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -49,6 +49,7 @@ import android.util.SparseArray;
import android.view.IWindow;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -129,10 +130,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private boolean mIsAccessibilityEnabled;
- private boolean mIsTouchExplorationRequested;
-
private AccessibilityInputFilter mInputFilter;
+ private boolean mHasInputFilter;
+
private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
private boolean mIsTouchExplorationEnabled;
@@ -189,7 +190,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
manageServicesLocked();
}
}
-
+
@Override
public boolean onHandleForceStop(Intent intent, String[] packages,
int uid, boolean doit) {
@@ -236,17 +237,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mIsAccessibilityEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
- // if accessibility is enabled inform our clients we are on
- if (mIsAccessibilityEnabled) {
- sendAccessibilityEnabledToClientsLocked();
- }
+
manageServicesLocked();
// get touch exploration enabled setting on boot
- mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mIsTouchExplorationEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
- updateTouchExplorationEnabledLocked();
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+ updateInputFilterLocked();
+
+ sendStateToClientsLocked();
}
return;
@@ -288,13 +288,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
} else {
unbindAllServicesLocked();
}
- sendAccessibilityEnabledToClientsLocked();
+ sendStateToClientsLocked();
}
}
});
Uri touchExplorationRequestedUri = Settings.Secure.getUriFor(
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED);
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED);
contentResolver.registerContentObserver(touchExplorationRequestedUri, false,
new ContentObserver(new Handler()) {
@Override
@@ -302,10 +302,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
super.onChange(selfChange);
synchronized (mLock) {
- mIsTouchExplorationRequested = Settings.Secure.getInt(
+ mIsTouchExplorationEnabled = Settings.Secure.getInt(
mContext.getContentResolver(),
- Settings.Secure.TOUCH_EXPLORATION_REQUESTED, 0) == 1;
- updateTouchExplorationEnabledLocked();
+ Settings.Secure.TOUCH_EXPLORATION_ENABLED, 0) == 1;
+ updateInputFilterLocked();
+ sendStateToClientsLocked();
}
}
});
@@ -325,7 +326,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
});
}
- public boolean addClient(IAccessibilityManagerClient client) throws RemoteException {
+ public int addClient(IAccessibilityManagerClient client) throws RemoteException {
synchronized (mLock) {
final IAccessibilityManagerClient addedClient = client;
mClients.add(addedClient);
@@ -338,7 +339,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
}
}, 0);
- return mIsAccessibilityEnabled;
+ return getState();
}
}
@@ -628,7 +629,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
service.linkToOwnDeath();
mServices.add(service);
mComponentNameToServiceMap.put(service.mComponentName, service);
- updateTouchExplorationEnabledLocked();
+ updateInputFilterLocked();
} catch (RemoteException e) {
/* do nothing */
}
@@ -648,7 +649,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mComponentNameToServiceMap.remove(service.mComponentName);
mHandler.removeMessages(service.mId);
service.unlinkToOwnDeath();
- updateTouchExplorationEnabledLocked();
+ updateInputFilterLocked();
return removed;
}
@@ -781,12 +782,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
- * Updates the state of {@link android.view.accessibility.AccessibilityManager} clients.
+ * Sends the state to the clients.
*/
- private void sendAccessibilityEnabledToClientsLocked() {
+ private void sendStateToClientsLocked() {
+ final int state = getState();
for (int i = 0, count = mClients.size(); i < count; i++) {
try {
- mClients.get(i).setEnabled(mIsAccessibilityEnabled);
+ mClients.get(i).setState(state);
} catch (RemoteException re) {
mClients.remove(i);
count--;
@@ -796,48 +798,39 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
/**
- * Sends the touch exploration state to clients.
+ * Gets the current state as a set of flags.
+ *
+ * @return The state.
*/
- private void sendTouchExplorationEnabledToClientsLocked() {
- for (int i = 0, count = mClients.size(); i < count; i++) {
- try {
- mClients.get(i).setTouchExplorationEnabled(mIsTouchExplorationEnabled);
- } catch (RemoteException re) {
- mClients.remove(i);
- count--;
- i--;
- }
+ private int getState() {
+ int state = 0;
+ if (mIsAccessibilityEnabled) {
+ state |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
+ // Touch exploration relies on enabled accessibility.
+ if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ state |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
+ }
+ return state;
}
/**
- * Updates the touch exploration state. Touch exploration is enabled if it
- * is requested, accessibility is on and there is at least one enabled
- * accessibility service providing spoken feedback.
+ * Updates the touch exploration state.
*/
- private void updateTouchExplorationEnabledLocked() {
- if (mIsAccessibilityEnabled && mIsTouchExplorationRequested) {
- final boolean hasSpeakingServicesEnabled = !getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
- if (!mIsTouchExplorationEnabled) {
- if (!hasSpeakingServicesEnabled) {
- return;
- }
+ private void updateInputFilterLocked() {
+ if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ if (!mHasInputFilter) {
+ mHasInputFilter = true;
if (mInputFilter == null) {
mInputFilter = new AccessibilityInputFilter(mContext);
}
mWindowManagerService.setInputFilter(mInputFilter);
- mIsTouchExplorationEnabled = true;
- sendTouchExplorationEnabledToClientsLocked();
- return;
- } else if (hasSpeakingServicesEnabled) {
- return;
}
+ return;
}
- if (mIsTouchExplorationEnabled) {
+ if (mHasInputFilter) {
+ mHasInputFilter = false;
mWindowManagerService.setInputFilter(null);
- mIsTouchExplorationEnabled = false;
- sendTouchExplorationEnabledToClientsLocked();
}
}
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 5a3a55d..0ad58d0 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -19,21 +19,21 @@ package com.android.server.accessibility;
import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END;
import static android.view.accessibility.AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START;
-import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
-import com.android.server.wm.InputFilter;
-
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-import android.view.WindowManagerPolicy;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
+import android.view.ViewConfiguration;
+import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
+import com.android.server.wm.InputFilter;
+
import java.util.Arrays;
/**
@@ -146,6 +146,9 @@ public class TouchExplorer implements Explorer {
// Command for delayed sending of a hover event.
private final SendHoverDelayed mSendHoverDelayed;
+ // Command for delayed sending of a long press.
+ private final PerformLongPressDelayed mPerformLongPressDelayed;
+
/**
* Creates a new instance.
*
@@ -160,6 +163,7 @@ public class TouchExplorer implements Explorer {
mPointerTracker = new PointerTracker(context);
mHandler = new Handler(context.getMainLooper());
mSendHoverDelayed = new SendHoverDelayed();
+ mPerformLongPressDelayed = new PerformLongPressDelayed();
mAccessibilityManager = AccessibilityManager.getInstance(context);
}
@@ -208,15 +212,7 @@ public class TouchExplorer implements Explorer {
final int activePointerCount = pointerTracker.getActivePointerCount();
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- // Send a hover for every finger down so the user gets feedback
- // where she is currently touching.
- mSendHoverDelayed.forceSendAndRemove();
- final int pointerIndex = event.getActionIndex();
- final int pointerIdBits = (1 << event.getPointerId(pointerIndex));
- mSendHoverDelayed.post(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits,
- policyFlags, DELAY_SEND_HOVER_MOVE);
- } break;
+ case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN: {
switch (activePointerCount) {
case 0: {
@@ -224,13 +220,13 @@ public class TouchExplorer implements Explorer {
+ "touch exploring state!");
}
case 1: {
- // Schedule a hover event which will lead to firing an
- // accessibility event from the hovered view.
- mSendHoverDelayed.remove();
+ // Send hover if pending.
+ mSendHoverDelayed.forceSendAndRemove();
+ // Send a hover for every finger down so the user gets feedback.
final int pointerId = pointerTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
final int lastAction = pointerTracker.getLastInjectedHoverAction();
- // If a schedules hover enter for another pointer is delivered we send move.
+ // If a hover enter for another pointer is delivered we send move.
final int action = (lastAction == MotionEvent.ACTION_HOVER_ENTER)
? MotionEvent.ACTION_HOVER_MOVE
: MotionEvent.ACTION_HOVER_ENTER;
@@ -244,7 +240,19 @@ public class TouchExplorer implements Explorer {
// If more pointers down on the screen since the last touch
// exploration we discard the last cached touch explore event.
if (event.getPointerCount() != mLastTouchExploreEvent.getPointerCount()) {
- mLastTouchExploreEvent = null;
+ mLastTouchExploreEvent = null;
+ break;
+ }
+
+ // If the down is in the time slop => schedule a long press.
+ final long pointerDownTime =
+ pointerTracker.getReceivedPointerDownTime(pointerId);
+ final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
+ final long deltaTimeExplore = pointerDownTime - lastExploreTime;
+ if (deltaTimeExplore <= ACTIVATION_TIME_SLOP) {
+ mPerformLongPressDelayed.post(event, policyFlags,
+ ViewConfiguration.getLongPressTimeout());
+ break;
}
} break;
default: {
@@ -275,6 +283,7 @@ public class TouchExplorer implements Explorer {
sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_START);
// Make sure the scheduled down/move event is sent.
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// If we have transitioned to exploring state from another one
// we need to send a hover enter event here.
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
@@ -291,20 +300,11 @@ public class TouchExplorer implements Explorer {
policyFlags);
}
- // Detect long press on the last touch explored position.
- if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null) {
+ // If the exploring pointer moved enough => cancel the long press.
+ if (!mTouchExploreGestureInProgress && mLastTouchExploreEvent != null
+ && mPerformLongPressDelayed.isPenidng()) {
- // If the down was not in the time slop => nothing else to do.
- final long pointerDownTime =
- pointerTracker.getReceivedPointerDownTime(pointerId);
- final long lastExploreTime = mLastTouchExploreEvent.getEventTime();
- final long deltaTimeExplore = pointerDownTime - lastExploreTime;
- if (deltaTimeExplore > ACTIVATION_TIME_SLOP) {
- mLastTouchExploreEvent = null;
- break;
- }
-
- // If the pointer moved more than the tap slop => nothing else to do.
+ // If the pointer moved more than the tap slop => cancel long press.
final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
- event.getX(pointerIndex);
final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
@@ -312,24 +312,14 @@ public class TouchExplorer implements Explorer {
final float moveDelta = (float) Math.hypot(deltaX, deltaY);
if (moveDelta > mTouchExplorationTapSlop) {
mLastTouchExploreEvent = null;
+ mPerformLongPressDelayed.remove();
break;
}
-
- // If down for long enough we get a long press.
- final long deltaTimeMove = event.getEventTime() - pointerDownTime;
- if (deltaTimeMove > ViewConfiguration.getLongPressTimeout()) {
- mCurrentState = STATE_DELEGATING;
- // Make sure the scheduled hover exit is delivered.
- mSendHoverDelayed.forceSendAndRemove();
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
- sendMotionEvent(event, policyFlags);
- mTouchExploreGestureInProgress = false;
- mLastTouchExploreEvent = null;
- }
}
} break;
case 2: {
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -360,6 +350,7 @@ public class TouchExplorer implements Explorer {
} break;
default: {
mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
// We want to no longer hover over the location so subsequent
// touch at the same spot will generate a hover enter.
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits,
@@ -388,22 +379,26 @@ public class TouchExplorer implements Explorer {
break;
}
+ mSendHoverDelayed.forceSendAndRemove();
+ mPerformLongPressDelayed.remove();
+
// If touch exploring announce the end of the gesture.
+ // Also do not click on the last explored location.
if (mTouchExploreGestureInProgress) {
- sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
mTouchExploreGestureInProgress = false;
+ mLastTouchExploreEvent = MotionEvent.obtain(event);
+ sendAccessibilityEvent(TYPE_TOUCH_EXPLORATION_GESTURE_END);
+ break;
}
// Detect whether to activate i.e. click on the last explored location.
if (mLastTouchExploreEvent != null) {
-
// If the down was not in the time slop => nothing else to do.
final long eventTime =
pointerTracker.getLastReceivedUpPointerDownTime();
final long exploreTime = mLastTouchExploreEvent.getEventTime();
final long deltaTime = eventTime - exploreTime;
if (deltaTime > ACTIVATION_TIME_SLOP) {
- mSendHoverDelayed.forceSendAndRemove();
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -413,15 +408,14 @@ public class TouchExplorer implements Explorer {
break;
}
- // If the pointer moved more than the tap slop => nothing else to do.
+ // If a tap is farther than the tap slop => nothing to do.
final int pointerIndex = event.findPointerIndex(pointerId);
- final float deltaX = pointerTracker.getLastReceivedUpPointerDownX()
+ final float deltaX = mLastTouchExploreEvent.getX(pointerIndex)
- event.getX(pointerIndex);
- final float deltaY = pointerTracker.getLastReceivedUpPointerDownY()
+ final float deltaY = mLastTouchExploreEvent.getY(pointerIndex)
- event.getY(pointerIndex);
final float deltaMove = (float) Math.hypot(deltaX, deltaY);
if (deltaMove > mTouchExplorationTapSlop) {
- mSendHoverDelayed.forceSendAndRemove();
final int lastAction = mPointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT,
@@ -432,7 +426,6 @@ public class TouchExplorer implements Explorer {
}
// All preconditions are met, so click the last explored location.
- mSendHoverDelayed.forceSendAndRemove();
sendActionDownAndUp(mLastTouchExploreEvent, policyFlags);
mLastTouchExploreEvent = null;
} else {
@@ -448,6 +441,8 @@ public class TouchExplorer implements Explorer {
}
} break;
case MotionEvent.ACTION_CANCEL: {
+ mSendHoverDelayed.remove();
+ mPerformLongPressDelayed.remove();
final int lastAction = pointerTracker.getLastInjectedHoverAction();
if (lastAction != MotionEvent.ACTION_HOVER_EXIT) {
final int pointerId = pointerTracker.getPrimaryActivePointerId();
@@ -934,8 +929,6 @@ public class TouchExplorer implements Explorer {
private int mInjectedPointersDown;
// Keep track of the last up pointer data.
- private float mLastReceivedUpPointerDownX;
- private float mLastReveivedUpPointerDownY;
private long mLastReceivedUpPointerDownTime;
private int mLastReceivedUpPointerId;
private boolean mLastReceivedUpPointerActive;
@@ -968,8 +961,6 @@ public class TouchExplorer implements Explorer {
mPrimaryActivePointerId = 0;
mHasMovingActivePointer = false;
mInjectedPointersDown = 0;
- mLastReceivedUpPointerDownX = 0;
- mLastReveivedUpPointerDownY = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerId = 0;
mLastReceivedUpPointerActive = false;
@@ -1126,20 +1117,6 @@ public class TouchExplorer implements Explorer {
}
/**
- * @return The X coordinate where the last up received pointer went down.
- */
- public float getLastReceivedUpPointerDownX() {
- return mLastReceivedUpPointerDownX;
- }
-
- /**
- * @return The Y coordinate where the last up received pointer went down.
- */
- public float getLastReceivedUpPointerDownY() {
- return mLastReveivedUpPointerDownY;
- }
-
- /**
* @return The time when the last up received pointer went down.
*/
public long getLastReceivedUpPointerDownTime() {
@@ -1220,8 +1197,6 @@ public class TouchExplorer implements Explorer {
final int pointerFlag = (1 << pointerId);
mLastReceivedUpPointerId = 0;
- mLastReceivedUpPointerDownX = 0;
- mLastReveivedUpPointerDownY = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerActive = false;
@@ -1262,8 +1237,6 @@ public class TouchExplorer implements Explorer {
final int pointerFlag = (1 << pointerId);
mLastReceivedUpPointerId = pointerId;
- mLastReceivedUpPointerDownX = getReceivedPointerDownX(pointerId);
- mLastReveivedUpPointerDownY = getReceivedPointerDownY(pointerId);
mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
mLastReceivedUpPointerActive = isActivePointer(pointerId);
@@ -1400,6 +1373,51 @@ public class TouchExplorer implements Explorer {
}
/**
+ * Class for delayed sending of long press.
+ */
+ private final class PerformLongPressDelayed implements Runnable {
+ private MotionEvent mEvent;
+ private int mPolicyFlags;
+
+ public void post(MotionEvent prototype, int policyFlags, long delay) {
+ mEvent = MotionEvent.obtain(prototype);
+ mPolicyFlags = policyFlags;
+ mHandler.postDelayed(this, delay);
+ }
+
+ public void remove() {
+ if (isPenidng()) {
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
+
+ private boolean isPenidng() {
+ return (mEvent != null);
+ }
+
+ @Override
+ public void run() {
+ mCurrentState = STATE_DELEGATING;
+ // Make sure the scheduled hover exit is delivered.
+ mSendHoverDelayed.forceSendAndRemove();
+ sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+ mTouchExploreGestureInProgress = false;
+ mLastTouchExploreEvent = null;
+ clear();
+ }
+
+ private void clear() {
+ if (!isPenidng()) {
+ return;
+ }
+ mEvent.recycle();
+ mEvent = null;
+ mPolicyFlags = 0;
+ }
+ }
+
+ /**
* Class for delayed sending of hover events.
*/
private final class SendHoverDelayed implements Runnable {
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
index 1234bfd..46bcc4a 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java
@@ -29,12 +29,13 @@ import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
/**
* This test exercises the
- * {@link com.android.server.AccessibilityManagerService} by mocking the
+ * {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the
* {@link android.view.accessibility.AccessibilityManager} which talks to to the
* service. The service itself is interacting with the platform. Note: Testing
* the service in full isolation would require significant amount of work for
@@ -97,7 +98,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+ final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityDisabled =
+ (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertFalse("The client must be disabled since accessibility is disabled.",
@@ -107,7 +110,10 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
ensureAccessibilityEnabled(mContext, true);
// invoke the method under test
- boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+ final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityEnabled =
+ (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
+
// check expected result
assertTrue("The client must be enabled since accessibility is enabled.",
@@ -123,7 +129,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();
// invoke the method under test
- boolean enabledAccessibilityEnabled = mManagerService.addClient(mockClient);
+ final int stateFlagsEnabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityEnabled =
+ (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertTrue("The client must be enabled since accessibility is enabled.",
@@ -133,7 +141,9 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
ensureAccessibilityEnabled(mContext, false);
// invoke the method under test
- boolean enabledAccessibilityDisabled = mManagerService.addClient(mockClient);
+ final int stateFlagsDisabled = mManagerService.addClient(mockClient);
+ boolean enabledAccessibilityDisabled =
+ (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
// check expected result
assertFalse("The client must be disabled since accessibility is disabled.",
@@ -537,10 +547,10 @@ public class AccessibilityManagerServiceTest extends AndroidTestCase {
* This class is a mock {@link IAccessibilityManagerClient}.
*/
public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub {
- boolean mIsEnabled;
+ int mState;
- public void setEnabled(boolean enabled) {
- mIsEnabled = enabled;
+ public void setState(int state) {
+ mState = state;
}
public void setTouchExplorationEnabled(boolean enabled) {
diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
index 1463d30..e083815 100644
--- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java
@@ -70,7 +70,8 @@ public class AccessibilityManagerTest extends AndroidTestCase {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn(
expectedServices);
replay(mockServiceInterface);
@@ -91,7 +92,8 @@ public class AccessibilityManagerTest extends AndroidTestCase {
public void testInterrupt() throws Exception {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
mockServiceInterface.interrupt();
replay(mockServiceInterface);
@@ -107,7 +109,8 @@ public class AccessibilityManagerTest extends AndroidTestCase {
public void testIsEnabled() throws Exception {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
replay(mockServiceInterface);
// invoke the method under test
@@ -118,7 +121,7 @@ public class AccessibilityManagerTest extends AndroidTestCase {
assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled);
// disable accessibility
- manager.getClient().setEnabled(false);
+ manager.getClient().setState(0);
// wait for the asynchronous IBinder call to complete
Thread.sleep(TIMEOUT_BINDER_CALL);
@@ -141,7 +144,8 @@ public class AccessibilityManagerTest extends AndroidTestCase {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(true);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(
+ AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED);
expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
.andReturn(true);
expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent)))
@@ -176,7 +180,7 @@ public class AccessibilityManagerTest extends AndroidTestCase {
// configure the mock service behavior
IAccessibilityManager mockServiceInterface = mMockServiceInterface;
- expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(false);
+ expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0);
replay(mockServiceInterface);
// invoke the method under test (accessibility disabled)
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 54685a6..74c6b49 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1059,7 +1059,7 @@ public class WifiStateMachine extends StateMachine {
}
}
- private void startTethering(ArrayList<String> available) {
+ private boolean startTethering(ArrayList<String> available) {
boolean wifiAvailable = false;
@@ -1085,18 +1085,20 @@ public class WifiStateMachine extends StateMachine {
} catch (Exception e) {
Log.e(TAG, "Error configuring interface " + intf + ", :" + e);
setWifiApEnabled(null, false);
- return;
+ return false;
}
if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Log.e(TAG, "Error tethering on " + intf);
setWifiApEnabled(null, false);
- return;
+ return false;
}
- break;
+ return true;
}
}
}
+ // We found no interfaces to tether
+ return false;
}
private void stopTethering() {
@@ -3098,8 +3100,9 @@ public class WifiStateMachine extends StateMachine {
break;
case CMD_TETHER_INTERFACE:
ArrayList<String> available = (ArrayList<String>) message.obj;
- startTethering(available);
- transitionTo(mTetheredState);
+ if (startTethering(available)) {
+ transitionTo(mTetheredState);
+ }
break;
case WifiP2pService.P2P_ENABLE_PENDING:
// turn of soft Ap and defer to be handled in DriverUnloadedState