summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java5
-rw-r--r--core/java/android/bluetooth/BluetoothA2dpSink.java432
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java23
-rw-r--r--core/java/android/bluetooth/BluetoothAudioConfig.aidl19
-rw-r--r--core/java/android/bluetooth/BluetoothAudioConfig.java111
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcp.java93
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpController.java260
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClient.java1167
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl18
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClientCall.java218
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java14
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dpSink.aidl34
-rw-r--r--core/java/android/bluetooth/IBluetoothAvrcpController.aidl31
-rw-r--r--core/java/android/bluetooth/IBluetoothHeadsetClient.aidl67
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/android/webkit/ClientCertRequest.java21
-rw-r--r--core/java/android/webkit/WebView.java8
-rw-r--r--core/res/AndroidManifest.xml20
-rw-r--r--core/res/assets/images/android-logo-mask.pngbin11068 -> 14395 bytes
-rw-r--r--core/res/assets/images/android-logo-shine.pngbin559 -> 97831 bytes
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java1
-rw-r--r--graphics/java/android/graphics/drawable/AnimationDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java40
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.pngbin1453 -> 2980 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.pngbin1932 -> 2046 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.pngbin1362 -> 2963 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.pngbin2285 -> 3653 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.pngbin2257 -> 3583 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.pngbin928 -> 945 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.pngbin928 -> 938 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.pngbin1489 -> 1396 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.pngbin1485 -> 1289 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.pngbin984 -> 3026 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.pngbin936 -> 2992 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.pngbin783 -> 1803 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.pngbin767 -> 1797 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.pngbin1489 -> 4822 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.pngbin1445 -> 4835 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.pngbin1044 -> 2850 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.pngbin1027 -> 2893 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.pngbin1998 -> 7042 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.pngbin1970 -> 6846 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.pngbin3745 -> 6377 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.pngbin3721 -> 6480 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.pngbin1291 -> 4375 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.pngbin1226 -> 4364 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.pngbin1557 -> 2062 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.pngbin1561 -> 2022 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.pngbin1137 -> 1845 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.pngbin1376 -> 1500 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.pngbin1109 -> 1843 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.pngbin1696 -> 2372 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.pngbin1674 -> 2342 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.pngbin708 -> 705 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.pngbin708 -> 714 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.pngbin1300 -> 1148 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.pngbin1286 -> 1113 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.pngbin2297 -> 4229 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.pngbin2724 -> 2955 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.pngbin2195 -> 4332 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.pngbin3174 -> 5240 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.pngbin3127 -> 5299 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.pngbin1982 -> 2122 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.pngbin1982 -> 2163 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.pngbin1891 -> 1828 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.pngbin1780 -> 1744 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.pngbin1542 -> 2486 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.pngbin1785 -> 1943 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.pngbin1580 -> 2463 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.pngbin2079 -> 3198 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.pngbin2041 -> 3154 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.pngbin1366 -> 1482 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.pngbin1366 -> 1496 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.pngbin1368 -> 1339 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.pngbin1227 -> 1135 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.pngbin2878 -> 6190 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.pngbin4086 -> 4509 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.pngbin3073 -> 6118 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.pngbin4583 -> 7524 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.pngbin4480 -> 7655 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.pngbin2418 -> 2614 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.pngbin2418 -> 2645 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.pngbin2450 -> 2250 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.pngbin2412 -> 2192 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.pngbin5945 -> 4766 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.pngbin7758 -> 3585 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.pngbin5988 -> 4782 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.pngbin8718 -> 5895 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.pngbin8739 -> 5764 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.pngbin4375 -> 2229 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.pngbin4375 -> 2231 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.pngbin3949 -> 1778 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.pngbin3945 -> 1713 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.pngbin2037 -> 4218 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.pngbin2791 -> 2849 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.pngbin1941 -> 4216 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.pngbin3426 -> 5365 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.pngbin3399 -> 5312 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.pngbin1141 -> 1103 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.pngbin1141 -> 1119 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.pngbin1945 -> 1754 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.pngbin1917 -> 1685 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.pngbin16953 -> 7195 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.pngbin16779 -> 5288 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.pngbin16821 -> 7186 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.pngbin17012 -> 8635 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.pngbin17087 -> 8519 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.pngbin16209 -> 1545 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.pngbin16209 -> 1576 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.pngbin16827 -> 2369 bytes
-rw-r--r--[-rwxr-xr-x]packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.pngbin16904 -> 2282 bytes
-rw-r--r--packages/SystemUI/res/values/config.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java4
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java2
119 files changed, 2580 insertions, 35 deletions
diff --git a/Android.mk b/Android.mk
index 7a46a1fa0424..58bc2c7f9a0e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -98,6 +98,8 @@ LOCAL_SRC_FILES += \
core/java/android/app/maintenance/IIdleService.aidl \
core/java/android/bluetooth/IBluetooth.aidl \
core/java/android/bluetooth/IBluetoothA2dp.aidl \
+ core/java/android/bluetooth/IBluetoothA2dpSink.aidl \
+ core/java/android/bluetooth/IBluetoothAvrcpController.aidl \
core/java/android/bluetooth/IBluetoothCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
@@ -110,6 +112,7 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothPbap.aidl \
core/java/android/bluetooth/IBluetoothMap.aidl \
core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
+ core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \
core/java/android/bluetooth/IBluetoothGatt.aidl \
core/java/android/bluetooth/IBluetoothGattCallback.aidl \
core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index a2d62b0bef6b..941eb5b2b9df 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35001,7 +35001,8 @@ package android.view.textservice {
package android.webkit {
- public abstract interface ClientCertRequest {
+ public abstract class ClientCertRequest {
+ ctor public ClientCertRequest();
method public abstract void cancel();
method public abstract java.lang.String getHost();
method public abstract java.lang.String[] getKeyTypes();
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 7b709acd911c..51754901163d 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -90,6 +90,11 @@ public final class BluetoothA2dp implements BluetoothProfile {
public static final String ACTION_PLAYING_STATE_CHANGED =
"android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
+ /** @hide */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_AVRCP_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.a2dp.profile.action.AVRCP_CONNECTION_STATE_CHANGED";
+
/**
* A2DP sink device is streaming music. This state can be one of
* {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
new file mode 100644
index 000000000000..2e273459add8
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the Bluetooth A2DP Sink
+ * profile.
+ *
+ *<p>BluetoothA2dpSink is a proxy object for controlling the Bluetooth A2DP Sink
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothA2dpSink proxy object.
+ *
+ * @hide
+ */
+public final class BluetoothA2dpSink implements BluetoothProfile {
+ private static final String TAG = "BluetoothA2dpSink";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /**
+ * Intent used to broadcast the change in connection state of the A2DP Sink
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
+
+ /**
+ * Intent used to broadcast the change in the Playing state of the A2DP Sink
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile. </li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING},
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ public static final String ACTION_PLAYING_STATE_CHANGED =
+ "android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED";
+
+ /**
+ * A2DP sink device is streaming music. This state can be one of
+ * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
+ * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
+ */
+ public static final int STATE_PLAYING = 10;
+
+ /**
+ * A2DP sink device is NOT streaming music. This state can be one of
+ * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
+ * {@link #ACTION_PLAYING_STATE_CHANGED} intent.
+ */
+ public static final int STATE_NOT_PLAYING = 11;
+
+ /**
+ * Intent used to broadcast the change in the Playing state of the A2DP Sink
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_AUDIO_CONFIG} - The audio configuration for the remote device. </li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ public static final String ACTION_AUDIO_CONFIG_CHANGED =
+ "android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED";
+
+ /**
+ * Extra for the {@link #ACTION_AUDIO_CONFIG_CHANGED} intent.
+ *
+ * This extra represents the current audio configuration of the A2DP source device.
+ * {@see BluetoothAudioConfig}
+ */
+ public static final String EXTRA_AUDIO_CONFIG
+ = "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private IBluetoothA2dpSink mService;
+ private BluetoothAdapter mAdapter;
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ if (VDBG) Log.d(TAG,"Unbinding service...");
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ } else {
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG,"Binding service...");
+ doBind();
+ }
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+ };
+ /**
+ * Create a BluetoothA2dp proxy object for interacting with the local
+ * Bluetooth A2DP service.
+ *
+ */
+ /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
+ return false;
+ }
+ return true;
+ }
+
+ /*package*/ void close() {
+ mServiceListener = null;
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (Exception e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+
+ public void finalize() {
+ close();
+ }
+ /**
+ * Initiate connection to a profile of the remote bluetooth device.
+ *
+ * <p> Currently, the system supports only 1 connection to the
+ * A2DP profile. The API will automatically disconnect connected
+ * devices before connecting.
+ *
+ * <p> This API returns false in scenarios like the profile on the
+ * device is already connected or Bluetooth is not turned on.
+ * When this API returns true, it is guaranteed that
+ * connection state intent for the profile will be broadcasted with
+ * the state. Users can get the connection state of the profile
+ * from this intent.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean connect(BluetoothDevice device) {
+ if (DBG) log("connect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.connect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Initiate disconnection from a profile
+ *
+ * <p> This API will return false in scenarios like the profile on the
+ * Bluetooth device is not in connected state etc. When this API returns,
+ * true, it is guaranteed that the connection state change
+ * intent will be broadcasted with the state. Users can get the
+ * disconnection state of the profile from this intent.
+ *
+ * <p> If the disconnection is initiated by a remote device, the state
+ * will transition from {@link #STATE_CONNECTED} to
+ * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
+ * host (local) device the state will transition from
+ * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
+ * state {@link #STATE_DISCONNECTED}. The transition to
+ * {@link #STATE_DISCONNECTING} can be used to distinguish between the
+ * two scenarios.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+ * permission.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on immediate error,
+ * true otherwise
+ * @hide
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.disconnect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (VDBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (VDBG) log("getState(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Get the current audio configuration for the A2DP source device,
+ * or null if the device has no audio configuration
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device Remote bluetooth device.
+ * @return audio configuration for the device, or null
+ *
+ * {@see BluetoothAudioConfig}
+ */
+ public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
+ if (VDBG) log("getAudioConfig(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getAudioConfig(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return null;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ }
+
+ /**
+ * Helper for converting a state to a string.
+ *
+ * For debug use only - strings are not internationalized.
+ * @hide
+ */
+ public static String stateToString(int state) {
+ switch (state) {
+ case STATE_DISCONNECTED:
+ return "disconnected";
+ case STATE_CONNECTING:
+ return "connecting";
+ case STATE_CONNECTED:
+ return "connected";
+ case STATE_DISCONNECTING:
+ return "disconnecting";
+ case STATE_PLAYING:
+ return "playing";
+ case STATE_NOT_PLAYING:
+ return "not playing";
+ default:
+ return "<unknown state " + state + ">";
+ }
+ }
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) Log.d(TAG, "Proxy object connected");
+ mService = IBluetoothA2dpSink.Stub.asInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
+ BluetoothA2dpSink.this);
+ }
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.d(TAG, "Proxy object disconnected");
+ mService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
+ }
+ }
+ };
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 42c2aebead52..ba42f51b6245 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1390,6 +1390,12 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.A2DP) {
BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
return true;
+ } else if (profile == BluetoothProfile.A2DP_SINK) {
+ BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
+ return true;
+ } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
+ BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
+ return true;
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
return true;
@@ -1402,6 +1408,9 @@ public final class BluetoothAdapter {
} else if (profile == BluetoothProfile.MAP) {
BluetoothMap map = new BluetoothMap(context, listener);
return true;
+ } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
+ BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
+ return true;
} else {
return false;
}
@@ -1430,6 +1439,14 @@ public final class BluetoothAdapter {
BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
a2dp.close();
break;
+ case BluetoothProfile.A2DP_SINK:
+ BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy;
+ a2dpSink.close();
+ break;
+ case BluetoothProfile.AVRCP_CONTROLLER:
+ BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy;
+ avrcp.close();
+ break;
case BluetoothProfile.INPUT_DEVICE:
BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
iDev.close();
@@ -1454,6 +1471,10 @@ public final class BluetoothAdapter {
BluetoothMap map = (BluetoothMap)proxy;
map.close();
break;
+ case BluetoothProfile.HEADSET_CLIENT:
+ BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy;
+ headsetClient.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.aidl b/core/java/android/bluetooth/BluetoothAudioConfig.aidl
new file mode 100644
index 000000000000..63be5cff87da
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAudioConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2009 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.bluetooth;
+
+parcelable BluetoothAudioConfig;
diff --git a/core/java/android/bluetooth/BluetoothAudioConfig.java b/core/java/android/bluetooth/BluetoothAudioConfig.java
new file mode 100644
index 000000000000..03176b9e0739
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAudioConfig.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 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.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the audio configuration for a Bluetooth A2DP source device.
+ *
+ * {@see BluetoothA2dpSink}
+ *
+ * {@hide}
+ */
+public final class BluetoothAudioConfig implements Parcelable {
+
+ private final int mSampleRate;
+ private final int mChannelConfig;
+ private final int mAudioFormat;
+
+ public BluetoothAudioConfig(int sampleRate, int channelConfig, int audioFormat) {
+ mSampleRate = sampleRate;
+ mChannelConfig = channelConfig;
+ mAudioFormat = audioFormat;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothAudioConfig) {
+ BluetoothAudioConfig bac = (BluetoothAudioConfig)o;
+ return (bac.mSampleRate == mSampleRate &&
+ bac.mChannelConfig == mChannelConfig &&
+ bac.mAudioFormat == mAudioFormat);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return mSampleRate | (mChannelConfig << 24) | (mAudioFormat << 28);
+ }
+
+ @Override
+ public String toString() {
+ return "{mSampleRate:" + mSampleRate + ",mChannelConfig:" + mChannelConfig
+ + ",mAudioFormat:" + mAudioFormat + "}";
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothAudioConfig> CREATOR =
+ new Parcelable.Creator<BluetoothAudioConfig>() {
+ public BluetoothAudioConfig createFromParcel(Parcel in) {
+ int sampleRate = in.readInt();
+ int channelConfig = in.readInt();
+ int audioFormat = in.readInt();
+ return new BluetoothAudioConfig(sampleRate, channelConfig, audioFormat);
+ }
+ public BluetoothAudioConfig[] newArray(int size) {
+ return new BluetoothAudioConfig[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSampleRate);
+ out.writeInt(mChannelConfig);
+ out.writeInt(mAudioFormat);
+ }
+
+ /**
+ * Returns the sample rate in samples per second
+ * @return sample rate
+ */
+ public int getSampleRate() {
+ return mSampleRate;
+ }
+
+ /**
+ * Returns the channel configuration (either {@link android.media.AudioFormat#CHANNEL_IN_MONO}
+ * or {@link android.media.AudioFormat#CHANNEL_IN_STEREO})
+ * @return channel configuration
+ */
+ public int getChannelConfig() {
+ return mChannelConfig;
+ }
+
+ /**
+ * Returns the channel audio format (either {@link android.media.AudioFormat#ENCODING_PCM_16BIT}
+ * or {@link android.media.AudioFormat#ENCODING_PCM_8BIT}
+ * @return audio format
+ */
+ public int getAudioFormat() {
+ return mAudioFormat;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothAvrcp.java b/core/java/android/bluetooth/BluetoothAvrcp.java
new file mode 100644
index 000000000000..44fe1b737129
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAvrcp.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+/**
+ * This class contains constants for Bluetooth AVRCP profile.
+ *
+ * {@hide}
+ */
+public final class BluetoothAvrcp {
+
+ /*
+ * State flags for Passthrough commands
+ */
+ public static final int PASSTHROUGH_STATE_PRESS = 0;
+ public static final int PASSTHROUGH_STATE_RELEASE = 1;
+
+ /*
+ * Operation IDs for Passthrough commands
+ */
+ public static final int PASSTHROUGH_ID_SELECT = 0x00; /* select */
+ public static final int PASSTHROUGH_ID_UP = 0x01; /* up */
+ public static final int PASSTHROUGH_ID_DOWN = 0x02; /* down */
+ public static final int PASSTHROUGH_ID_LEFT = 0x03; /* left */
+ public static final int PASSTHROUGH_ID_RIGHT = 0x04; /* right */
+ public static final int PASSTHROUGH_ID_RIGHT_UP = 0x05; /* right-up */
+ public static final int PASSTHROUGH_ID_RIGHT_DOWN = 0x06; /* right-down */
+ public static final int PASSTHROUGH_ID_LEFT_UP = 0x07; /* left-up */
+ public static final int PASSTHROUGH_ID_LEFT_DOWN = 0x08; /* left-down */
+ public static final int PASSTHROUGH_ID_ROOT_MENU = 0x09; /* root menu */
+ public static final int PASSTHROUGH_ID_SETUP_MENU = 0x0A; /* setup menu */
+ public static final int PASSTHROUGH_ID_CONT_MENU = 0x0B; /* contents menu */
+ public static final int PASSTHROUGH_ID_FAV_MENU = 0x0C; /* favorite menu */
+ public static final int PASSTHROUGH_ID_EXIT = 0x0D; /* exit */
+ public static final int PASSTHROUGH_ID_0 = 0x20; /* 0 */
+ public static final int PASSTHROUGH_ID_1 = 0x21; /* 1 */
+ public static final int PASSTHROUGH_ID_2 = 0x22; /* 2 */
+ public static final int PASSTHROUGH_ID_3 = 0x23; /* 3 */
+ public static final int PASSTHROUGH_ID_4 = 0x24; /* 4 */
+ public static final int PASSTHROUGH_ID_5 = 0x25; /* 5 */
+ public static final int PASSTHROUGH_ID_6 = 0x26; /* 6 */
+ public static final int PASSTHROUGH_ID_7 = 0x27; /* 7 */
+ public static final int PASSTHROUGH_ID_8 = 0x28; /* 8 */
+ public static final int PASSTHROUGH_ID_9 = 0x29; /* 9 */
+ public static final int PASSTHROUGH_ID_DOT = 0x2A; /* dot */
+ public static final int PASSTHROUGH_ID_ENTER = 0x2B; /* enter */
+ public static final int PASSTHROUGH_ID_CLEAR = 0x2C; /* clear */
+ public static final int PASSTHROUGH_ID_CHAN_UP = 0x30; /* channel up */
+ public static final int PASSTHROUGH_ID_CHAN_DOWN = 0x31; /* channel down */
+ public static final int PASSTHROUGH_ID_PREV_CHAN = 0x32; /* previous channel */
+ public static final int PASSTHROUGH_ID_SOUND_SEL = 0x33; /* sound select */
+ public static final int PASSTHROUGH_ID_INPUT_SEL = 0x34; /* input select */
+ public static final int PASSTHROUGH_ID_DISP_INFO = 0x35; /* display information */
+ public static final int PASSTHROUGH_ID_HELP = 0x36; /* help */
+ public static final int PASSTHROUGH_ID_PAGE_UP = 0x37; /* page up */
+ public static final int PASSTHROUGH_ID_PAGE_DOWN = 0x38; /* page down */
+ public static final int PASSTHROUGH_ID_POWER = 0x40; /* power */
+ public static final int PASSTHROUGH_ID_VOL_UP = 0x41; /* volume up */
+ public static final int PASSTHROUGH_ID_VOL_DOWN = 0x42; /* volume down */
+ public static final int PASSTHROUGH_ID_MUTE = 0x43; /* mute */
+ public static final int PASSTHROUGH_ID_PLAY = 0x44; /* play */
+ public static final int PASSTHROUGH_ID_STOP = 0x45; /* stop */
+ public static final int PASSTHROUGH_ID_PAUSE = 0x46; /* pause */
+ public static final int PASSTHROUGH_ID_RECORD = 0x47; /* record */
+ public static final int PASSTHROUGH_ID_REWIND = 0x48; /* rewind */
+ public static final int PASSTHROUGH_ID_FAST_FOR = 0x49; /* fast forward */
+ public static final int PASSTHROUGH_ID_EJECT = 0x4A; /* eject */
+ public static final int PASSTHROUGH_ID_FORWARD = 0x4B; /* forward */
+ public static final int PASSTHROUGH_ID_BACKWARD = 0x4C; /* backward */
+ public static final int PASSTHROUGH_ID_ANGLE = 0x50; /* angle */
+ public static final int PASSTHROUGH_ID_SUBPICT = 0x51; /* subpicture */
+ public static final int PASSTHROUGH_ID_F1 = 0x71; /* F1 */
+ public static final int PASSTHROUGH_ID_F2 = 0x72; /* F2 */
+ public static final int PASSTHROUGH_ID_F3 = 0x73; /* F3 */
+ public static final int PASSTHROUGH_ID_F4 = 0x74; /* F4 */
+ public static final int PASSTHROUGH_ID_F5 = 0x75; /* F5 */
+ public static final int PASSTHROUGH_ID_VENDOR = 0x7E; /* vendor unique */
+ public static final int PASSTHROUGH_KEYPRESSED_RELEASE = 0x80;
+}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
new file mode 100644
index 000000000000..b53a8fc0f6fc
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the Bluetooth AVRCP Controller
+ * profile.
+ *
+ *<p>BluetoothAvrcpController is a proxy object for controlling the Bluetooth AVRCP
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothAvrcpController proxy object.
+ *
+ * {@hide}
+ */
+public final class BluetoothAvrcpController implements BluetoothProfile {
+ private static final String TAG = "BluetoothAvrcpController";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /**
+ * Intent used to broadcast the change in connection state of the AVRCP Controller
+ * profile.
+ *
+ * <p>This intent will have 3 extras:
+ * <ul>
+ * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+ * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+ * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+ * </ul>
+ *
+ * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+ * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+ * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+ * receive.
+ */
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.acrcp-controller.profile.action.CONNECTION_STATE_CHANGED";
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private IBluetoothAvrcpController mService;
+ private BluetoothAdapter mAdapter;
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ if (VDBG) Log.d(TAG,"Unbinding service...");
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ } else {
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG,"Binding service...");
+ doBind();
+ }
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Create a BluetoothAvrcpController proxy object for interacting with the local
+ * Bluetooth AVRCP service.
+ *
+ */
+ /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) {
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothAvrcpController.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);
+ return false;
+ }
+ return true;
+ }
+
+ /*package*/ void close() {
+ mServiceListener = null;
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (Exception e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+
+ public void finalize() {
+ close();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (VDBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getConnectionState(BluetoothDevice device) {
+ if (VDBG) log("getState(" + device + ")");
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public void sendPassThroughCmd(BluetoothDevice device, int keyCode, int keyState) {
+ if (DBG) Log.d(TAG, "sendPassThroughCmd");
+ if (mService != null && isEnabled()) {
+ try {
+ mService.sendPassThroughCmd(device, keyCode, keyState);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in sendPassThroughCmd()", e);
+ return;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ }
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) Log.d(TAG, "Proxy object connected");
+ mService = IBluetoothAvrcpController.Stub.asInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
+ BluetoothAvrcpController.this);
+ }
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.d(TAG, "Proxy object disconnected");
+ mService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER);
+ }
+ }
+ };
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
new file mode 100644
index 000000000000..ff4ebee221e9
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -0,0 +1,1167 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Public API to control Hands Free Profile (HFP role only).
+ * <p>
+ * This class defines methods that shall be used by application to manage profile
+ * connection, calls states and calls actions.
+ * <p>
+ *
+ * @hide
+ * */
+public final class BluetoothHeadsetClient implements BluetoothProfile {
+ private static final String TAG = "BluetoothHeadsetClient";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /**
+ * Intent sent whenever connection to remote changes.
+ *
+ * <p>It includes two extras:
+ * <code>BluetoothProfile.EXTRA_PREVIOUS_STATE</code>
+ * and <code>BluetoothProfile.EXTRA_STATE</code>, which
+ * are mandatory.
+ * <p>There are also non mandatory feature extras:
+ * {@link #EXTRA_AG_FEATURE_3WAY_CALLING},
+ * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION},
+ * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT},
+ * {@link #EXTRA_AG_FEATURE_REJECT_CALL},
+ * {@link #EXTRA_AG_FEATURE_ECC},
+ * {@link #EXTRA_AG_FEATURE_RESPONSE_AND_HOLD},
+ * {@link #EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL},
+ * {@link #EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL},
+ * {@link #EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT},
+ * {@link #EXTRA_AG_FEATURE_MERGE},
+ * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH},
+ * sent as boolean values only when <code>EXTRA_STATE</code>
+ * is set to <code>STATE_CONNECTED</code>.</p>
+ *
+ * <p>Note that features supported by AG are being sent as
+ * booleans with value <code>true</code>,
+ * and not supported ones are <strong>not</strong> being sent at all.</p>
+ */
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED";
+
+ /**
+ * Intent sent whenever audio state changes.
+ *
+ * <p>It includes two mandatory extras:
+ * {@link BluetoothProfile.EXTRA_STATE},
+ * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE},
+ * with possible values:
+ * {@link #STATE_AUDIO_CONNECTING},
+ * {@link #STATE_AUDIO_CONNECTED},
+ * {@link #STATE_AUDIO_DISCONNECTED}</p>
+ * <p>When <code>EXTRA_STATE</code> is set
+ * to </code>STATE_AUDIO_CONNECTED</code>,
+ * it also includes {@link #EXTRA_AUDIO_WBS}
+ * indicating wide band speech support.</p>
+ */
+ public static final String ACTION_AUDIO_STATE_CHANGED =
+ "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED";
+
+ /**
+ * Intent sending updates of the Audio Gateway state.
+ * Each extra is being sent only when value it
+ * represents has been changed recently on AG.
+ * <p>It can contain one or more of the following extras:
+ * {@link #EXTRA_NETWORK_STATUS},
+ * {@link #EXTRA_NETWORK_SIGNAL_STRENGTH},
+ * {@link #EXTRA_NETWORK_ROAMING},
+ * {@link #EXTRA_BATTERY_LEVEL},
+ * {@link #EXTRA_OPERATOR_NAME},
+ * {@link #EXTRA_VOICE_RECOGNITION},
+ * {@link #EXTRA_IN_BAND_RING}</p>
+ */
+ public static final String ACTION_AG_EVENT =
+ "android.bluetooth.headsetclient.profile.action.AG_EVENT";
+
+ /**
+ * Intent sent whenever state of a call changes.
+ *
+ * <p>It includes:
+ * {@link #EXTRA_CALL},
+ * with value of {@link BluetoothHeadsetClientCall} instance,
+ * representing actual call state.</p>
+ */
+ public static final String ACTION_CALL_CHANGED =
+ "android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED";
+
+ /**
+ * Intent that notifies about the result of the last issued action.
+ * Please note that not every action results in explicit action result code being sent.
+ * Instead other notifications about new Audio Gateway state might be sent,
+ * like <code>ACTION_AG_EVENT</code> with <code>EXTRA_VOICE_RECOGNITION</code> value
+ * when for example user started voice recognition from HF unit.
+ */
+ public static final String ACTION_RESULT =
+ "android.bluetooth.headsetclient.profile.action.RESULT";
+
+ /**
+ * Intent that notifies about the number attached to the last voice tag
+ * recorded on AG.
+ *
+ * <p>It contains:
+ * {@link #EXTRA_NUMBER},
+ * with a <code>String</code> value representing phone number.</p>
+ */
+ public static final String ACTION_LAST_VTAG =
+ "android.bluetooth.headsetclient.profile.action.LAST_VTAG";
+
+ public static final int STATE_AUDIO_DISCONNECTED = 0;
+ public static final int STATE_AUDIO_CONNECTING = 1;
+ public static final int STATE_AUDIO_CONNECTED = 2;
+
+ /**
+ * Extra with information if connected audio is WBS.
+ * <p>Possible values: <code>true</code>,
+ * <code>false</code>.</p>
+ */
+ public static final String EXTRA_AUDIO_WBS =
+ "android.bluetooth.headsetclient.extra.AUDIO_WBS";
+
+ /**
+ * Extra for AG_EVENT indicates network status.
+ * <p>Value: 0 - network unavailable,
+ * 1 - network available </p>
+ */
+ public static final String EXTRA_NETWORK_STATUS =
+ "android.bluetooth.headsetclient.extra.NETWORK_STATUS";
+ /**
+ * Extra for AG_EVENT intent indicates network signal strength.
+ * <p>Value: <code>Integer</code> representing signal strength.</p>
+ */
+ public static final String EXTRA_NETWORK_SIGNAL_STRENGTH =
+ "android.bluetooth.headsetclient.extra.NETWORK_SIGNAL_STRENGTH";
+ /**
+ * Extra for AG_EVENT intent indicates roaming state.
+ * <p>Value: 0 - no roaming
+ * 1 - active roaming</p>
+ */
+ public static final String EXTRA_NETWORK_ROAMING =
+ "android.bluetooth.headsetclient.extra.NETWORK_ROAMING";
+ /**
+ * Extra for AG_EVENT intent indicates the battery level.
+ * <p>Value: <code>Integer</code> representing signal strength.</p>
+ */
+ public static final String EXTRA_BATTERY_LEVEL =
+ "android.bluetooth.headsetclient.extra.BATTERY_LEVEL";
+ /**
+ * Extra for AG_EVENT intent indicates operator name.
+ * <p>Value: <code>String</code> representing operator name.</p>
+ */
+ public static final String EXTRA_OPERATOR_NAME =
+ "android.bluetooth.headsetclient.extra.OPERATOR_NAME";
+ /**
+ * Extra for AG_EVENT intent indicates voice recognition state.
+ * <p>Value:
+ * 0 - voice recognition stopped,
+ * 1 - voice recognition started.</p>
+ */
+ public static final String EXTRA_VOICE_RECOGNITION =
+ "android.bluetooth.headsetclient.extra.VOICE_RECOGNITION";
+ /**
+ * Extra for AG_EVENT intent indicates in band ring state.
+ * <p>Value:
+ * 0 - in band ring tone not supported, or
+ * 1 - in band ring tone supported.</p>
+ */
+ public static final String EXTRA_IN_BAND_RING =
+ "android.bluetooth.headsetclient.extra.IN_BAND_RING";
+
+ /**
+ * Extra for AG_EVENT intent indicates subscriber info.
+ * <p>Value: <code>String</code> containing subscriber information.</p>
+ */
+ public static final String EXTRA_SUBSCRIBER_INFO =
+ "android.bluetooth.headsetclient.extra.SUBSCRIBER_INFO";
+
+ /**
+ * Extra for AG_CALL_CHANGED intent indicates the
+ * {@link BluetoothHeadsetClientCall} object that has changed.
+ */
+ public static final String EXTRA_CALL =
+ "android.bluetooth.headsetclient.extra.CALL";
+
+ /**
+ * Extra for ACTION_LAST_VTAG intent.
+ * <p>Value: <code>String</code> representing phone number
+ * corresponding to last voice tag recorded on AG</p>
+ */
+ public static final String EXTRA_NUMBER =
+ "android.bluetooth.headsetclient.extra.NUMBER";
+
+ /**
+ * Extra for ACTION_RESULT intent that shows the result code of
+ * last issued action.
+ * <p>Possible results:
+ * {@link #ACTION_RESULT_OK},
+ * {@link #ACTION_RESULT_ERROR},
+ * {@link #ACTION_RESULT_ERROR_NO_CARRIER},
+ * {@link #ACTION_RESULT_ERROR_BUSY},
+ * {@link #ACTION_RESULT_ERROR_NO_ANSWER},
+ * {@link #ACTION_RESULT_ERROR_DELAYED},
+ * {@link #ACTION_RESULT_ERROR_BLACKLISTED},
+ * {@link #ACTION_RESULT_ERROR_CME}</p>
+ */
+ public static final String EXTRA_RESULT_CODE =
+ "android.bluetooth.headsetclient.extra.RESULT_CODE";
+
+ /**
+ * Extra for ACTION_RESULT intent that shows the extended result code of
+ * last issued action.
+ * <p>Value: <code>Integer</code> - error code.</p>
+ */
+ public static final String EXTRA_CME_CODE =
+ "android.bluetooth.headsetclient.extra.CME_CODE";
+
+ /* Extras for AG_FEATURES, extras type is boolean */
+ // TODO verify if all of those are actually useful
+ /**
+ * AG feature: three way calling.
+ */
+ public final static String EXTRA_AG_FEATURE_3WAY_CALLING =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING";
+ /**
+ * AG feature: voice recognition.
+ */
+ public final static String EXTRA_AG_FEATURE_VOICE_RECOGNITION =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION";
+ /**
+ * AG feature: fetching phone number for voice tagging procedure.
+ */
+ public final static String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT";
+ /**
+ * AG feature: ability to reject incoming call.
+ */
+ public final static String EXTRA_AG_FEATURE_REJECT_CALL =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_REJECT_CALL";
+ /**
+ * AG feature: enhanced call handling (terminate specific call, private consultation).
+ */
+ public final static String EXTRA_AG_FEATURE_ECC =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ECC";
+ /**
+ * AG feature: response and hold.
+ */
+ public final static String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD";
+ /**
+ * AG call handling feature: accept held or waiting call in three way calling scenarios.
+ */
+ public final static String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL";
+ /**
+ * AG call handling feature: release held or waiting call in three way calling scenarios.
+ */
+ public final static String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL";
+ /**
+ * AG call handling feature: release active call and accept held or waiting call in three way
+ * calling scenarios.
+ */
+ public final static String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT";
+ /**
+ * AG call handling feature: merge two calls, held and active - multi party conference mode.
+ */
+ public final static String EXTRA_AG_FEATURE_MERGE =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE";
+ /**
+ * AG call handling feature: merge calls and disconnect from multi party
+ * conversation leaving peers connected to each other.
+ * Note that this feature needs to be supported by mobile network operator
+ * as it requires connection and billing transfer.
+ */
+ public final static String EXTRA_AG_FEATURE_MERGE_AND_DETACH =
+ "android.bluetooth.headsetclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH";
+
+ /* Action result codes */
+ public final static int ACTION_RESULT_OK = 0;
+ public final static int ACTION_RESULT_ERROR = 1;
+ public final static int ACTION_RESULT_ERROR_NO_CARRIER = 2;
+ public final static int ACTION_RESULT_ERROR_BUSY = 3;
+ public final static int ACTION_RESULT_ERROR_NO_ANSWER = 4;
+ public final static int ACTION_RESULT_ERROR_DELAYED = 5;
+ public final static int ACTION_RESULT_ERROR_BLACKLISTED = 6;
+ public final static int ACTION_RESULT_ERROR_CME = 7;
+
+ /* Detailed CME error codes */
+ public final static int CME_PHONE_FAILURE = 0;
+ public final static int CME_NO_CONNECTION_TO_PHONE = 1;
+ public final static int CME_OPERATION_NOT_ALLOWED = 3;
+ public final static int CME_OPERATION_NOT_SUPPORTED = 4;
+ public final static int CME_PHSIM_PIN_REQUIRED = 5;
+ public final static int CME_PHFSIM_PIN_REQUIRED = 6;
+ public final static int CME_PHFSIM_PUK_REQUIRED = 7;
+ public final static int CME_SIM_NOT_INSERTED = 10;
+ public final static int CME_SIM_PIN_REQUIRED = 11;
+ public final static int CME_SIM_PUK_REQUIRED = 12;
+ public final static int CME_SIM_FAILURE = 13;
+ public final static int CME_SIM_BUSY = 14;
+ public final static int CME_SIM_WRONG = 15;
+ public final static int CME_INCORRECT_PASSWORD = 16;
+ public final static int CME_SIM_PIN2_REQUIRED = 17;
+ public final static int CME_SIM_PUK2_REQUIRED = 18;
+ public final static int CME_MEMORY_FULL = 20;
+ public final static int CME_INVALID_INDEX = 21;
+ public final static int CME_NOT_FOUND = 22;
+ public final static int CME_MEMORY_FAILURE = 23;
+ public final static int CME_TEXT_STRING_TOO_LONG = 24;
+ public final static int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25;
+ public final static int CME_DIAL_STRING_TOO_LONG = 26;
+ public final static int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27;
+ public final static int CME_NO_NETWORK_SERVICE = 30;
+ public final static int CME_NETWORK_TIMEOUT = 31;
+ public final static int CME_EMERGENCY_SERVICE_ONLY = 32;
+ public final static int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33;
+ public final static int CME_NOT_SUPPORTED_FOR_VOIP = 34;
+ public final static int CME_SIP_RESPONSE_CODE = 35;
+ public final static int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40;
+ public final static int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41;
+ public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42;
+ public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43;
+ public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44;
+ public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45;
+ public final static int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46;
+ public final static int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47;
+ public final static int CME_HIDDEN_KEY_REQUIRED = 48;
+ public final static int CME_EAP_NOT_SUPPORTED = 49;
+ public final static int CME_INCORRECT_PARAMETERS = 50;
+
+ /* Action policy for other calls when accepting call */
+ public static final int CALL_ACCEPT_NONE = 0;
+ public static final int CALL_ACCEPT_HOLD = 1;
+ public static final int CALL_ACCEPT_TERMINATE = 2;
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private IBluetoothHeadsetClient mService;
+ private BluetoothAdapter mAdapter;
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ @Override
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ if (VDBG) Log.d(TAG,"Unbinding service...");
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ } else {
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG,"Binding service...");
+ Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
+ doBind();
+ }
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Create a BluetoothHeadsetClient proxy object.
+ */
+ /*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) {
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Close the connection to the backing service.
+ * Other public functions of BluetoothHeadsetClient will return default error
+ * results once close() has been called. Multiple invocations of close()
+ * are ok.
+ */
+ /*package*/ void close() {
+ if (VDBG) log("close()");
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (Exception e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ mServiceListener = null;
+ }
+
+ /**
+ * Connects to remote device.
+ *
+ * Currently, the system supports only 1 connection. So, in case of the
+ * second connection, this implementation will disconnect already connected
+ * device automatically and will process the new one.
+ *
+ * @param device a remote device we want connect to
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED}
+ * intent.
+ */
+ public boolean connect(BluetoothDevice device) {
+ if (DBG) log("connect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.connect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Disconnects remote device
+ *
+ * @param device a remote device we want disconnect
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED}
+ * intent.
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) log("disconnect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.disconnect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Return the list of connected remote devices
+ *
+ * @return list of connected devices; empty list if nothing is connected.
+ */
+ @Override
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (VDBG) log("getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * Returns list of remote devices in a particular state
+ *
+ * @param states collection of states
+ * @return list of devices that state matches the states listed in
+ * <code>states</code>; empty list if nothing matches the
+ * <code>states</code>
+ */
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (VDBG) log("getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ }
+
+ /**
+ * Returns state of the <code>device</code>
+ *
+ * @param device a remote device
+ * @return the state of connection of the device
+ */
+ @Override
+ public int getConnectionState(BluetoothDevice device) {
+ if (VDBG) log("getConnectionState(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Set priority of the profile
+ *
+ * The device should already be paired.
+ */
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON) {
+ return false;
+ }
+ try {
+ return mService.setPriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get the priority of the profile.
+ */
+ public int getPriority(BluetoothDevice device) {
+ if (VDBG) log("getPriority(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getPriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return PRIORITY_OFF;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return PRIORITY_OFF;
+ }
+
+ /**
+ * Starts voice recognition.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_AG_EVENT}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean startVoiceRecognition(BluetoothDevice device) {
+ if (DBG) log("startVoiceRecognition()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.startVoiceRecognition(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Stops voice recognition.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_AG_EVENT}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean stopVoiceRecognition(BluetoothDevice device) {
+ if (DBG) log("stopVoiceRecognition()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.stopVoiceRecognition(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Returns list of all calls in any state.
+ *
+ * @param device remote device
+ * @return list of calls; empty list if none call exists
+ */
+ public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
+ if (DBG) log("getCurrentCalls()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getCurrentCalls(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ }
+
+ /**
+ * Returns list of current values of AG indicators.
+ *
+ * @param device remote device
+ * @return bundle of AG indicators; null if device is not in
+ * CONNECTED state
+ */
+ public Bundle getCurrentAgEvents(BluetoothDevice device) {
+ if (DBG) log("getCurrentCalls()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getCurrentAgEvents(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return null;
+ }
+
+ /**
+ * Accepts a call
+ *
+ * @param device remote device
+ * @param flag action policy while accepting a call. Possible values
+ * {@link #CALL_ACCEPT_NONE}, {@link #CALL_ACCEPT_HOLD},
+ * {@link #CALL_ACCEPT_TERMINATE}
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ */
+ public boolean acceptCall(BluetoothDevice device, int flag) {
+ if (DBG) log("acceptCall()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.acceptCall(device, flag);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Holds a call.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ */
+ public boolean holdCall(BluetoothDevice device) {
+ if (DBG) log("holdCall()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.holdCall(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Rejects a call.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_REJECT_CALL}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean rejectCall(BluetoothDevice device) {
+ if (DBG) log("rejectCall()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.rejectCall(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Terminates a specified call.
+ *
+ * Works only when Extended Call Control is supported by Audio Gateway.
+ *
+ * @param device remote device
+ * @param index index of the call to be terminated
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_ECC}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean terminateCall(BluetoothDevice device, int index) {
+ if (DBG) log("terminateCall()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.terminateCall(device, index);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Enters private mode with a specified call.
+ *
+ * Works only when Extended Call Control is supported by Audio Gateway.
+ *
+ * @param device remote device
+ * @param index index of the call to connect in private mode
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_ECC}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean enterPrivateMode(BluetoothDevice device, int index) {
+ if (DBG) log("enterPrivateMode()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.enterPrivateMode(device, index);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Performs explicit call transfer.
+ *
+ * That means connect other calls and disconnect.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent.
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean explicitCallTransfer(BluetoothDevice device) {
+ if (DBG) log("explicitCallTransfer()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.explicitCallTransfer(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Redials last number from Audio Gateway.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent in case of success; {@link #ACTION_RESULT} is sent
+ * otherwise;
+ */
+ public boolean redial(BluetoothDevice device) {
+ if (DBG) log("redial()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.redial(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Places a call with specified number.
+ *
+ * @param device remote device
+ * @param number valid phone number
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent in case of success; {@link #ACTION_RESULT} is sent
+ * otherwise;
+ */
+ public boolean dial(BluetoothDevice device, String number) {
+ if (DBG) log("dial()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.dial(device, number);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Places a call to the number under specified memory location.
+ *
+ * @param device remote device
+ * @param location valid memory location
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_CALL_CHANGED}
+ * intent in case of success; {@link #ACTION_RESULT} is sent
+ * otherwise;
+ */
+ public boolean dialMemory(BluetoothDevice device, int location) {
+ if (DBG) log("dialMemory()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.dialMemory(device, location);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Sends DTMF code.
+ *
+ * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,#
+ *
+ * @param device remote device
+ * @param code ASCII code
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_RESULT} intent;
+ */
+ public boolean sendDTMF(BluetoothDevice device, byte code) {
+ if (DBG) log("sendDTMF()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.sendDTMF(device, code);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get a number corresponding to last voice tag recorded on AG.
+ *
+ * @param device remote device
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_LAST_VTAG}
+ * or {@link #ACTION_RESULT} intent;
+ *
+ * <p>Feature required for successful execution is being reported by:
+ * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}.
+ * This method invocation will fail silently when feature is not supported.</p>
+ */
+ public boolean getLastVoiceTagNumber(BluetoothDevice device) {
+ if (DBG) log("getLastVoiceTagNumber()");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getLastVoiceTagNumber(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Accept the incoming connection.
+ */
+ public boolean acceptIncomingConnect(BluetoothDevice device) {
+ if (DBG) log("acceptIncomingConnect");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.acceptIncomingConnect(device);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Reject the incoming connection.
+ */
+ public boolean rejectIncomingConnect(BluetoothDevice device) {
+ if (DBG) log("rejectIncomingConnect");
+ if (mService != null) {
+ try {
+ return mService.rejectIncomingConnect(device);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Returns current audio state of Audio Gateway.
+ *
+ * Note: This is an internal function and shouldn't be exposed
+ */
+ public int getAudioState(BluetoothDevice device) {
+ if (VDBG) log("getAudioState");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getAudioState(device);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
+ }
+
+ /**
+ * Initiates a connection of audio channel.
+ *
+ * It setup SCO channel with remote connected Handsfree AG device.
+ *
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED}
+ * intent;
+ */
+ public boolean connectAudio() {
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.connectAudio();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Disconnects audio channel.
+ *
+ * It tears down the SCO channel from remote AG device.
+ *
+ * @return <code>true</code> if command has been issued successfully;
+ * <code>false</code> otherwise;
+ * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED}
+ * intent;
+ */
+ public boolean disconnectAudio() {
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.disconnectAudio();
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Get Audio Gateway features
+ *
+ * @param device remote device
+ * @return bundle of AG features; null if no service or
+ * AG not connected
+ */
+ public Bundle getCurrentAgFeatures(BluetoothDevice device) {
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getCurrentAgFeatures(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return null;
+ }
+
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) Log.d(TAG, "Proxy object connected");
+ mService = IBluetoothHeadsetClient.Stub.asInterface(service);
+
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
+ BluetoothHeadsetClient.this);
+ }
+ }
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.d(TAG, "Proxy object disconnected");
+ mService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
+ }
+ }
+ };
+
+ private boolean isEnabled() {
+ if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl b/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl
new file mode 100644
index 000000000000..35f792387ec7
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.aidl
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth;
+
+parcelable BluetoothHeadsetClientCall;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
new file mode 100644
index 000000000000..a15bd975ad84
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class represents a single call, its state and properties.
+ * It implements {@link Parcelable} for inter-process message passing.
+ * @hide
+ */
+public final class BluetoothHeadsetClientCall implements Parcelable {
+
+ /* Call state */
+ /**
+ * Call is active.
+ */
+ public static final int CALL_STATE_ACTIVE = 0;
+ /**
+ * Call is in held state.
+ */
+ public static final int CALL_STATE_HELD = 1;
+ /**
+ * Outgoing call that is being dialed right now.
+ */
+ public static final int CALL_STATE_DIALING = 2;
+ /**
+ * Outgoing call that remote party has already been alerted about.
+ */
+ public static final int CALL_STATE_ALERTING = 3;
+ /**
+ * Incoming call that can be accepted or rejected.
+ */
+ public static final int CALL_STATE_INCOMING = 4;
+ /**
+ * Waiting call state when there is already an active call.
+ */
+ public static final int CALL_STATE_WAITING = 5;
+ /**
+ * Call that has been held by response and hold
+ * (see Bluetooth specification for further references).
+ */
+ public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6;
+ /**
+ * Call that has been already terminated and should not be referenced as a valid call.
+ */
+ public static final int CALL_STATE_TERMINATED = 7;
+
+ private final int mId;
+ private int mState;
+ private String mNumber;
+ private boolean mMultiParty;
+ private final boolean mOutgoing;
+
+ /**
+ * Creates BluetoothHeadsetClientCall instance.
+ */
+ public BluetoothHeadsetClientCall(int id, int state, String number, boolean multiParty,
+ boolean outgoing) {
+ mId = id;
+ mState = state;
+ mNumber = number != null ? number : "";
+ mMultiParty = multiParty;
+ mOutgoing = outgoing;
+ }
+
+ /**
+ * Sets call's state.
+ *
+ * <p>Note: This is an internal function and shouldn't be exposed</p>
+ *
+ * @param state new call state.
+ */
+ public void setState(int state) {
+ mState = state;
+ }
+
+ /**
+ * Sets call's number.
+ *
+ * <p>Note: This is an internal function and shouldn't be exposed</p>
+ *
+ * @param number String representing phone number.
+ */
+ public void setNumber(String number) {
+ mNumber = number;
+ }
+
+ /**
+ * Sets this call as multi party call.
+ *
+ * <p>Note: This is an internal function and shouldn't be exposed</p>
+ *
+ * @param multiParty if <code>true</code> sets this call as a part
+ * of multi party conference.
+ */
+ public void setMultiParty(boolean multiParty) {
+ mMultiParty = multiParty;
+ }
+
+ /**
+ * Gets call's Id.
+ *
+ * @return call id.
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Gets call's current state.
+ *
+ * @return state of this particular phone call.
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Gets call's number.
+ *
+ * @return string representing phone number.
+ */
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /**
+ * Checks if call is an active call in a conference mode (aka multi party).
+ *
+ * @return <code>true</code> if call is a multi party call,
+ * <code>false</code> otherwise.
+ */
+ public boolean isMultiParty() {
+ return mMultiParty;
+ }
+
+ /**
+ * Checks if this call is an outgoing call.
+ *
+ * @return <code>true</code> if its outgoing call,
+ * <code>false</code> otherwise.
+ */
+ public boolean isOutgoing() {
+ return mOutgoing;
+ }
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mId: ");
+ builder.append(mId);
+ builder.append(", mState: ");
+ switch (mState) {
+ case CALL_STATE_ACTIVE: builder.append("ACTIVE"); break;
+ case CALL_STATE_HELD: builder.append("HELD"); break;
+ case CALL_STATE_DIALING: builder.append("DIALING"); break;
+ case CALL_STATE_ALERTING: builder.append("ALERTING"); break;
+ case CALL_STATE_INCOMING: builder.append("INCOMING"); break;
+ case CALL_STATE_WAITING: builder.append("WAITING"); break;
+ case CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: builder.append("HELD_BY_RESPONSE_AND_HOLD"); break;
+ case CALL_STATE_TERMINATED: builder.append("TERMINATED"); break;
+ default: builder.append(mState); break;
+ }
+ builder.append(", mNumber: ");
+ builder.append(mNumber);
+ builder.append(", mMultiParty: ");
+ builder.append(mMultiParty);
+ builder.append(", mOutgoing: ");
+ builder.append(mOutgoing);
+ builder.append("}");
+ return builder.toString();
+ }
+
+ /**
+ * {@link Parcelable.Creator} interface implementation.
+ */
+ public static final Parcelable.Creator<BluetoothHeadsetClientCall> CREATOR =
+ new Parcelable.Creator<BluetoothHeadsetClientCall>() {
+ @Override
+ public BluetoothHeadsetClientCall createFromParcel(Parcel in) {
+ return new BluetoothHeadsetClientCall(in.readInt(), in.readInt(),
+ in.readString(), in.readInt() == 1, in.readInt() == 1);
+ }
+
+ @Override
+ public BluetoothHeadsetClientCall[] newArray(int size) {
+ return new BluetoothHeadsetClientCall[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mId);
+ out.writeInt(mState);
+ out.writeString(mNumber);
+ out.writeInt(mMultiParty ? 1 : 0);
+ out.writeInt(mOutgoing ? 1 : 0);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index d89806028556..136740505a4a 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2010-2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -110,6 +110,18 @@ public interface BluetoothProfile {
public static final int A2DP_SINK = 10;
/**
+ * AVRCP Controller Profile
+ * @hide
+ */
+ public static final int AVRCP_CONTROLLER = 11;
+
+ /**
+ * Headset Client - HFP HF Role
+ * @hide
+ */
+ public static final int HEADSET_CLIENT = 16;
+
+ /**
* Default priority for devices that we try to auto-connect to and
* and allow incoming connections for the profile
* @hide
diff --git a/core/java/android/bluetooth/IBluetoothA2dpSink.aidl b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
new file mode 100644
index 000000000000..b7c647677000
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothA2dpSink.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothAudioConfig;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * APIs for Bluetooth A2DP sink service
+ *
+ * @hide
+ */
+interface IBluetoothA2dpSink {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ BluetoothAudioConfig getAudioConfig(in BluetoothDevice device);
+}
diff --git a/core/java/android/bluetooth/IBluetoothAvrcpController.aidl b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
new file mode 100644
index 000000000000..f917a50860b7
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothAvrcpController.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * APIs for Bluetooth AVRCP controller service
+ *
+ * @hide
+ */
+interface IBluetoothAvrcpController {
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ void sendPassThroughCmd(in BluetoothDevice device, int keyCode, int keyState);
+}
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
new file mode 100644
index 000000000000..e518b7d225f8
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClientCall;
+import android.os.Bundle;
+
+/**
+ * API for Bluetooth Headset Client service (HFP HF Role)
+ *
+ * {@hide}
+ */
+interface IBluetoothHeadsetClient {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+
+ boolean acceptIncomingConnect(in BluetoothDevice device);
+ boolean rejectIncomingConnect(in BluetoothDevice device);
+
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
+
+ boolean startVoiceRecognition(in BluetoothDevice device);
+ boolean stopVoiceRecognition(in BluetoothDevice device);
+
+ List<BluetoothHeadsetClientCall> getCurrentCalls(in BluetoothDevice device);
+ Bundle getCurrentAgEvents(in BluetoothDevice device);
+
+ boolean acceptCall(in BluetoothDevice device, int flag);
+ boolean holdCall(in BluetoothDevice device);
+ boolean rejectCall(in BluetoothDevice device);
+ boolean terminateCall(in BluetoothDevice device, int index);
+
+ boolean enterPrivateMode(in BluetoothDevice device, int index);
+ boolean explicitCallTransfer(in BluetoothDevice device);
+
+ boolean redial(in BluetoothDevice device);
+ boolean dial(in BluetoothDevice device, String number);
+ boolean dialMemory(in BluetoothDevice device, int location);
+
+ boolean sendDTMF(in BluetoothDevice device, byte code);
+ boolean getLastVoiceTagNumber(in BluetoothDevice device);
+
+ int getAudioState(in BluetoothDevice device);
+ boolean connectAudio();
+ boolean disconnectAudio();
+
+ Bundle getCurrentAgFeatures(in BluetoothDevice device);
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 453ee179a239..f75ae5588ba5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13529,6 +13529,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
throw new IllegalStateException("This view must be attached to a window first");
}
+ if (getWidth() == 0 || getHeight() == 0) {
+ return;
+ }
+
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
// The only part of a hardware layer we can build in response to
diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java
index 588b868726c3..4a7f5fdf1f66 100644
--- a/core/java/android/webkit/ClientCertRequest.java
+++ b/core/java/android/webkit/ClientCertRequest.java
@@ -27,7 +27,7 @@ import java.security.cert.X509Certificate;
* such as the host name and the port number requesting the cert, the acceptable
* key types and the principals.
*
- * The user should call one of the interface methods to indicate how to deal
+ * The user should call one of the class methods to indicate how to deal
* with the client certificate request. All methods should be called on
* UI thread.
*
@@ -37,42 +37,45 @@ import java.security.cert.X509Certificate;
* {@link WebView#clearClientCertPreferences}.
*
*/
-public interface ClientCertRequest {
+public abstract class ClientCertRequest {
+
+ public ClientCertRequest() { }
+
/**
* Returns the acceptable types of asymmetric keys (can be null).
*/
- public String[] getKeyTypes();
+ public abstract String[] getKeyTypes();
/**
* Returns the acceptable certificate issuers for the certificate
* matching the private key (can be null).
*/
- public Principal[] getPrincipals();
+ public abstract Principal[] getPrincipals();
/**
* Returns the host name of the server requesting the certificate.
*/
- public String getHost();
+ public abstract String getHost();
/**
* Returns the port number of the server requesting the certificate.
*/
- public int getPort();
+ public abstract int getPort();
/**
* Proceed with the specified private key and client certificate chain.
* Remember the user's positive choice and use it for future requests.
*/
- public void proceed(PrivateKey privateKey, X509Certificate[] chain);
+ public abstract void proceed(PrivateKey privateKey, X509Certificate[] chain);
/**
* Ignore the request for now. Do not remember user's choice.
*/
- public void ignore();
+ public abstract void ignore();
/**
* Cancel this request. Remember the user's choice and use it for
* future requests.
*/
- public void cancel();
+ public abstract void cancel();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 91ca7b4619f9..482c7e8aa2a3 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1486,11 +1486,11 @@ public class WebView extends AbsoluteLayout
}
/**
- * Clears the client certificate preferences table stored in response
- * to proceeding/cancelling client cert requests. Note that webview
+ * Clears the client certificate preferences stored in response
+ * to proceeding/cancelling client cert requests. Note that Webview
* automatically clears these preferences when it receives a
- * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The client certificate
- * preferences are global for all Webviews.
+ * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The preferences are
+ * shared by all the webviews that are created by the embedder application.
*
* @param onCleared A runnable to be invoked when client certs are cleared.
* The embedder can pass null if not interested in the
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3067cdd0209d..b628b7ca918e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -123,10 +123,30 @@
<protected-broadcast
android:name="android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT" />
<protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AG_EVENT" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.AG_CALL_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.RESULT" />
+ <protected-broadcast
+ android:name="android.bluetooth.headsetclient.profile.action.LAST_VTAG" />
+ <protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED" />
<protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.PLAYING_STATE_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.a2dp-sink.profile.action.AUDIO_CONFIG_CHANGED" />
+ <protected-broadcast
+ android:name="android.bluetooth.avrcp-controller.profile.action.CONNECTION_STATE_CHANGED" />
+ <protected-broadcast
android:name="android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED" />
<protected-broadcast
android:name="android.bluetooth.input.profile.action.PROTOCOL_MODE_CHANGED" />
diff --git a/core/res/assets/images/android-logo-mask.png b/core/res/assets/images/android-logo-mask.png
index 3078b28886cf..ad40645e8943 100644
--- a/core/res/assets/images/android-logo-mask.png
+++ b/core/res/assets/images/android-logo-mask.png
Binary files differ
diff --git a/core/res/assets/images/android-logo-shine.png b/core/res/assets/images/android-logo-shine.png
index add67968840f..cb65f229eb52 100644
--- a/core/res/assets/images/android-logo-shine.png
+++ b/core/res/assets/images/android-logo-shine.png
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index a5a074cd0e91..e1dec9d7e940 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -537,4 +537,3 @@ public class AnimatedStateListDrawable extends StateListDrawable {
}
}
}
-
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 16548d0801ef..1ee022490e7b 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -91,10 +91,10 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
@Override
public boolean setVisible(boolean visible, boolean restart) {
- boolean changed = super.setVisible(visible, restart);
+ final boolean changed = super.setVisible(visible, restart);
if (visible) {
if (changed || restart) {
- setFrame(0, true, restart || mCurFrame >= 0);
+ setFrame(0, true, mAnimating);
}
} else {
unscheduleSelf(this);
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 0d70e7503792..345400e399da 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -38,15 +38,18 @@ import java.util.ArrayList;
*/
class Ripple {
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
- private static final TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator(4);
+ private static final TimeInterpolator DECEL_INTERPOLATOR = new LogInterpolator();
private static final float GLOBAL_SPEED = 1.0f;
private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED;
- private static final float WAVE_TOUCH_UP_ACCELERATION = 3096.0f * GLOBAL_SPEED;
- private static final float WAVE_OPACITY_DECAY_VELOCITY = 1.9f / GLOBAL_SPEED;
- private static final float WAVE_OUTER_OPACITY_VELOCITY = 1.2f * GLOBAL_SPEED;
+ private static final float WAVE_TOUCH_UP_ACCELERATION = 3400.0f * GLOBAL_SPEED;
+ private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED;
+ private static final float WAVE_OUTER_OPACITY_VELOCITY_MAX = 4.5f * GLOBAL_SPEED;
+ private static final float WAVE_OUTER_OPACITY_VELOCITY_MIN = 1.5f * GLOBAL_SPEED;
+ private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f;
+ private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f;
- private static final long RIPPLE_ENTER_DELAY = 100;
+ private static final long RIPPLE_ENTER_DELAY = 80;
// Hardware animators.
private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
@@ -311,7 +314,7 @@ class Ripple {
public void enter() {
final int radiusDuration = (int)
(1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5);
- final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_VELOCITY);
+ final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_VELOCITY_MIN);
final ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radiusGravity", 1);
radius.setAutoCancel(true);
@@ -355,7 +358,6 @@ class Ripple {
*/
public void exit() {
cancelSoftwareAnimations();
-
final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
final float remaining;
if (mAnimRadius != null && mAnimRadius.isRunning()) {
@@ -368,13 +370,23 @@ class Ripple {
+ WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5);
final int opacityDuration = (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f);
+ // Scale the outer max opacity and opacity velocity based
+ // on the size of the outer radius
+
+ float outerSizeInfluence = MathUtils.constrain(
+ (mOuterRadius - WAVE_OUTER_SIZE_INFLUENCE_MIN * mDensity)
+ / (WAVE_OUTER_SIZE_INFLUENCE_MAX * mDensity), 0, 1);
+ float outerOpacityVelocity = MathUtils.lerp(WAVE_OUTER_OPACITY_VELOCITY_MIN,
+ WAVE_OUTER_OPACITY_VELOCITY_MAX, outerSizeInfluence);
+
// Determine at what time the inner and outer opacity intersect.
// inner(t) = mOpacity - t * WAVE_OPACITY_DECAY_VELOCITY / 1000
// outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000
+
final int outerInflection = Math.max(0, (int) (1000 * (mOpacity - mOuterOpacity)
- / (WAVE_OPACITY_DECAY_VELOCITY + WAVE_OUTER_OPACITY_VELOCITY) + 0.5f));
+ / (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f));
final int inflectionOpacity = (int) (255 * (mOuterOpacity + outerInflection
- * WAVE_OUTER_OPACITY_VELOCITY / 1000) + 0.5f);
+ * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
if (mCanUseHardware) {
exitHardware(radiusDuration, opacityDuration, outerInflection, inflectionOpacity);
@@ -606,4 +618,14 @@ class Ripple {
removeSelf();
}
};
+
+ /**
+ * Interpolator with a smooth log deceleration
+ */
+ private static final class LogInterpolator implements TimeInterpolator {
+ @Override
+ public float getInterpolation(float input) {
+ return 1 - (float) Math.pow(400, -input * 1.4);
+ }
+ }
}
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
index fa5a0f0382a8..b28624f7f79d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
index d88397ec0c97..9ce434d67b66 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
index 59d4695abf4a..51dce693418c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index bbebcb1317ad..3f3e288a46e3 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
index 93dc268b746b..9856cbf871b8 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
index 00738729bc8e..6910456f1523 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
index 00738729bc8e..e8c6ec63fead 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
index 8a3d69c1ad70..06dcd2079e73 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
index 0afd6fe1484d..240f536bbcd6 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
index 6ca3652c0366..e464347cf07d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
index 66f5c06aee34..f8b59e883543 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
index e49a2af970a0..1b578a68f322 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
index 84879b99c5b3..80ecaba37ae9 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
index d005f61c3a3c..c7bf2c7794b0 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
index dca30abaf865..278de4263027 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
index 6915a4a18de9..464831ccbb9a 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
index 309fd4e3abe0..c24132cd5068 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
index 23b570e5438d..bc84f221271c 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
index 1c5f73f26535..f4e219ee098c 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
index 40cf808793ee..ece2e378d4e7 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
index 36dd2be22bc5..d524dcfc8b7b 100644
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
index 3b979cd5e724..373e84a999db 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
index e8d1dea2196e..e5a102ab22ea 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
index 0ab099162905..6b19593ea805 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
index 4ced46b608d1..a5e0686be797 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
index 891397c5c56f..f878093ab387 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
index 5cf38551453f..7780b160437a 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
index edb5b1fd157c..343d0dd31d2f 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
index 3212336ea36b..8e9583b231bb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
index 7aff620e8ab6..7d387037134b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
index 9f66c14aa63e..6e186a34a458 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
index 9f66c14aa63e..12b40427a9b2 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
index 972b1a855473..e2a89c3ce8ac 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
index 473b0cbe5c77..311720b37ffb 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
index 8ad60a559ccd..67e4ee78ce8a 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
index 17cc7221dd40..dfef430806c8 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
index 6fa0d5f03a7a..de6d1092f4a7 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
index 70b3ef643046..7d0c3fbe6c18 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
index be6a5ef134f2..3baeb52c26a7 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
index b26600d7f554..d5b48e8a25ae 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
index b26600d7f554..26d7e7b8a7af 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
index f2cb7be85f05..c49198dcf88d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
index 170bdb67ebbc..2a21f29c0c8e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
index b4bea6d899fd..538d7d1fc97e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
index eb0eca1efa24..eb8e80b6d286 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
index 3d8d19b136bb..1c2c35a3fc0e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
index 0f6fdadf0c46..eec613f3cfb2 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
index cbe5f77c0bc1..1c0bad8a99b6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
index 80eb80359a3f..1293fa8a55b1 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
index 80eb80359a3f..96a9cce282cb 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
index a6d892f1a877..9ffc80ada55e 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
index 7183b81360b9..aa9b57bcebf4 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
index 657d546bda2d..b34352225809 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
index df23594d7853..f2f7b506113c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
index ab27aecc4762..383398ce1e60 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
index 31f98e10db0c..53444ab88f97 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
index 104aed78bd93..4294937a0885 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
index 18e113aae328..7cb3ee45e164 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
index 18e113aae328..b0179460ccc3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
index 079e68d6d0f8..e8dd07c7e9b0 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
index c38b43ae2f41..f396ea9075d6 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
index c9507af7620d..1b817cf41f73 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
index 242677660e32..21b7a06bc2da 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
index 48fb7816c4b8..676fc14d591c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
index c6fb9bf59d49..26f4ba9fa2f5 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
index 528df6d500d4..ea21b609b334 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
index 055070ab9474..c7d77c2f8fcd 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
index 055070ab9474..ae12cfdd6b27 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
index e17e8f42e8cc..8c27d451bb04 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
index aafee031d96e..c98827c80b18 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index e3cf7a683a06..ec2951d3f219 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
index 7e034b84e4f4..5103190e096b 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index a4b3a684e00a..818aa4fa7607 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 321fadb20f30..254f75774368 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index 6e3219f543d6..f0de417d80dc 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index 2b6021b55b1f..97f1526ba6ac 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index 2b6021b55b1f..773fa9486530 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index 023ca546b95a..8a8e94130375 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index 3c9dccbf6a65..ad7dfc3862d2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
index d8f170311dd4..77969b895860 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
index 4e12cc94ba17..b171f920f6a1 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
index 37951a041a16..ad35c65045d4 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
index 7281482d976e..d60229f600b9 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
index a13418c006a6..8fffa8e3410b 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
index 066c2d9ed9ad..921505519bf3 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
index a619a940ee3b..bcf7eb18569f 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
index 115109a1ed94..a261f850798c 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
index 3101cb021873..4c612f721a47 100755..100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 09a94f50df65..c8851dc7d83c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -120,11 +120,13 @@
duration of the transition in to recents. -->
<integer name="recents_animate_task_bar_enter_delay">225</integer>
<!-- The min animation duration for animating the task bar out. -->
+ <integer name="recents_animate_task_exit_to_home_duration">225</integer>
+ <!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_bar_exit_duration">125</integer>
<!-- The min animation duration for animating the task in when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_duration">325</integer>
+ <integer name="recents_animate_task_enter_from_home_duration">275</integer>
<!-- The animation stagger to apply to each task animation when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_delay">16</integer>
+ <integer name="recents_animate_task_enter_from_home_delay">10</integer>
<!-- The min animation duration for animating the nav bar scrim in. -->
<integer name="recents_nav_bar_scrim_enter_duration">400</integer>
<!-- The animation duration for animating the removal of a task view. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 8861752133d4..3e61f87771a1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -287,7 +287,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
/** Updates each of the task animation rects. */
void updateAnimationRects() {
- if (mServiceIsBound && mBootCompleted) {
+ if (mServiceIsBound) {
Resources res = mContext.getResources();
int statusBarHeight = res.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index cd4d206fcd4f..1d355cd2daf4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,7 +26,7 @@ public class Constants {
public static class App {
// Enables the home->Recents transition
- public static final boolean EnableHomeTransition = false;
+ public static final boolean EnableHomeTransition = true;
// Enables the screenshot app->Recents transition
public static final boolean EnableScreenshotAppTransition = false;
// Enables the filtering of tasks according to their grouping
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index b1f37336f899..433dcb4988eb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -70,6 +70,7 @@ public class RecentsConfiguration {
/** Task view animation and styles */
public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeDelay;
+ public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
public int taskViewTranslationZMinPx;
@@ -174,6 +175,8 @@ public class RecentsConfiguration {
res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
taskViewEnterFromHomeDelay =
res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+ taskViewExitToHomeDuration =
+ res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_remove_duration);
taskViewRemoveAnimTranslationXPx =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 7376255b3e7b..ffd41357047f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -327,8 +327,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
animate()
.translationY(ctx.offscreenTranslationY)
.setStartDelay(0)
- .setInterpolator(mConfig.fastOutSlowInInterpolator)
- .setDuration(mConfig.taskViewEnterFromHomeDuration)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskViewExitToHomeDuration)
.withLayer()
.withEndAction(ctx.postAnimationTrigger.decrementAsRunnable())
.start();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0cb2ab930310..b9416576cecc 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1104,7 +1104,7 @@ public class UserManagerService extends IUserManager.Stub {
final UserInfo user;
synchronized (mPackagesLock) {
user = mUsers.get(userHandle);
- if (userHandle == 0 || user == null) {
+ if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
return false;
}
mRemovingUserIds.put(userHandle, true);