diff options
Diffstat (limited to 'packages/SystemUI/src')
5 files changed, 196 insertions, 54 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 08844f3..d2dc425 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1629,6 +1629,7 @@ public class NotificationPanelView extends PanelView implements } else { mSecureCameraLaunchManager.startSecureCameraLaunch(); } + mStatusBar.startLaunchTransitionTimeout(); mBlockTouches = true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index ec2d30c..8b328aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -203,8 +203,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000; private static final int MSG_CLOSE_PANELS = 1001; private static final int MSG_OPEN_SETTINGS_PANEL = 1002; + private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; // 1020-1040 reserved for BaseStatusBar + // Time after we abort the launch transition. + private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000; + private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService @@ -2196,6 +2200,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, escalateHeadsUp(); setHeadsUpVisibility(false); break; + case MSG_LAUNCH_TRANSITION_TIMEOUT: + onLaunchTransitionTimeout(); + break; } } } @@ -3528,12 +3535,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mLaunchTransitionFadingAway) { mNotificationPanel.animate().cancel(); mNotificationPanel.setAlpha(1f); - if (mLaunchTransitionEndRunnable != null) { - mLaunchTransitionEndRunnable.run(); - } - mLaunchTransitionEndRunnable = null; + runLaunchTransitionEndRunnable(); mLaunchTransitionFadingAway = false; } + mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); setBarState(StatusBarState.KEYGUARD); updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); if (!mScreenOnFromKeyguard) { @@ -3574,6 +3579,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, */ public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, Runnable endRunnable) { + mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); mLaunchTransitionEndRunnable = endRunnable; Runnable hideRunnable = new Runnable() { @Override @@ -3592,10 +3598,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void run() { mNotificationPanel.setAlpha(1); - if (mLaunchTransitionEndRunnable != null) { - mLaunchTransitionEndRunnable.run(); - } - mLaunchTransitionEndRunnable = null; + runLaunchTransitionEndRunnable(); mLaunchTransitionFadingAway = false; } }); @@ -3609,6 +3612,32 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } /** + * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that + * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen + * because the launched app crashed or something else went wrong. + */ + public void startLaunchTransitionTimeout() { + mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT, + LAUNCH_TRANSITION_TIMEOUT_MS); + } + + private void onLaunchTransitionTimeout() { + Log.w(TAG, "Launch transition: Timeout!"); + mNotificationPanel.resetViews(); + } + + private void runLaunchTransitionEndRunnable() { + if (mLaunchTransitionEndRunnable != null) { + Runnable r = mLaunchTransitionEndRunnable; + + // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, + // which would lead to infinite recursion. Protect against it. + mLaunchTransitionEndRunnable = null; + r.run(); + } + } + + /** * @return true if we would like to stay in the shade, false if it should go away entirely */ public boolean hideKeyguard() { @@ -3631,6 +3660,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mQSPanel != null) { mQSPanel.refreshAllTiles(); } + mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); return staying; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 77da70a..f4edab5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -199,7 +199,7 @@ public class StatusBarKeyguardViewManager { new Runnable() { @Override public void run() { - mStatusBarWindowManager.setKeyguardOccluded(true); + mStatusBarWindowManager.setKeyguardOccluded(mOccluded); reset(); } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index 80fec5b..076cfe2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -19,15 +19,21 @@ package com.android.systemui.statusbar.policy; import static android.bluetooth.BluetoothAdapter.ERROR; import static com.android.systemui.statusbar.policy.BluetoothUtil.connectionStateToString; import static com.android.systemui.statusbar.policy.BluetoothUtil.deviceToString; -import static com.android.systemui.statusbar.policy.BluetoothUtil.profileStateToString; import static com.android.systemui.statusbar.policy.BluetoothUtil.profileToString; import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidToProfile; import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidToString; import static com.android.systemui.statusbar.policy.BluetoothUtil.uuidsToString; +import android.bluetooth.BluetoothA2dp; +import android.bluetooth.BluetoothA2dpSink; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothHeadsetClient; +import android.bluetooth.BluetoothInputDevice; import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothMap; +import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; import android.content.BroadcastReceiver; @@ -38,24 +44,37 @@ import android.os.ParcelUuid; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; -import android.util.SparseBooleanArray; +import android.util.SparseArray; import com.android.systemui.statusbar.policy.BluetoothUtil.Profile; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; import java.util.Set; public class BluetoothControllerImpl implements BluetoothController { private static final String TAG = "BluetoothController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + // This controls the order in which we check the states. Since a device can only have + // one state on screen, but can have multiple profiles, the later states override the + // value of earlier states. So if a device has a profile in CONNECTING and one in + // CONNECTED, it will show as CONNECTED, theoretically this shouldn't really happen often, + // but seemed worth noting. + private static final int[] CONNECTION_STATES = { + BluetoothProfile.STATE_DISCONNECTED, + BluetoothProfile.STATE_DISCONNECTING, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_CONNECTED, + }; private final Context mContext; private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final BluetoothAdapter mAdapter; private final Receiver mReceiver = new Receiver(); private final ArrayMap<BluetoothDevice, DeviceInfo> mDeviceInfo = new ArrayMap<>(); + private final SparseArray<BluetoothProfile> mProfiles = new SparseArray<>(); private boolean mEnabled; private boolean mConnecting; @@ -73,7 +92,8 @@ public class BluetoothControllerImpl implements BluetoothController { mReceiver.register(); setAdapterState(mAdapter.getState()); - updateBondedBluetoothDevices(); + updateBluetoothDevices(); + bindAllProfiles(); } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -83,6 +103,7 @@ public class BluetoothControllerImpl implements BluetoothController { pw.print(" mConnecting="); pw.println(mConnecting); pw.print(" mLastDevice="); pw.println(mLastDevice); pw.print(" mCallbacks.size="); pw.println(mCallbacks.size()); + pw.print(" mProfiles="); pw.println(profilesToString(mProfiles)); pw.print(" mDeviceInfo.size="); pw.println(mDeviceInfo.size()); for (int i = 0; i < mDeviceInfo.size(); i++) { final BluetoothDevice device = mDeviceInfo.keyAt(i); @@ -95,7 +116,22 @@ public class BluetoothControllerImpl implements BluetoothController { private static String infoToString(DeviceInfo info) { return info == null ? null : ("connectionState=" + - connectionStateToString(info.connectionState) + ",bonded=" + info.bonded); + connectionStateToString(info.connectionState) + ",bonded=" + info.bonded + + ",profiles=" + profilesToString(info.connectedProfiles)); + } + + private static String profilesToString(SparseArray<?> profiles) { + final int N = profiles.size(); + final StringBuffer buffer = new StringBuffer(); + buffer.append('['); + for (int i = 0; i < N; i++) { + if (i != 0) { + buffer.append(','); + } + buffer.append(BluetoothUtil.profileToString(profiles.keyAt(i))); + } + buffer.append(']'); + return buffer.toString(); } public void addStateChangedCallback(Callback cb) { @@ -178,6 +214,7 @@ public class BluetoothControllerImpl implements BluetoothController { private void connect(PairedDevice pd, final boolean connect) { if (mAdapter == null || pd == null || pd.tag == null) return; final BluetoothDevice device = (BluetoothDevice) pd.tag; + final DeviceInfo info = mDeviceInfo.get(device); final String action = connect ? "connect" : "disconnect"; if (DEBUG) Log.d(TAG, action + " " + deviceToString(device)); final ParcelUuid[] uuids = device.getUuids(); @@ -185,43 +222,35 @@ public class BluetoothControllerImpl implements BluetoothController { Log.w(TAG, "No uuids returned, aborting " + action + " for " + deviceToString(device)); return; } - final SparseBooleanArray profiles = new SparseBooleanArray(); - for (ParcelUuid uuid : uuids) { - final int profile = uuidToProfile(uuid); - if (profile == 0) { - Log.w(TAG, "Device " + deviceToString(device) + " has an unsupported uuid: " - + uuidToString(uuid)); - continue; - } - final int profileState = mAdapter.getProfileConnectionState(profile); - if (DEBUG && !profiles.get(profile)) Log.d(TAG, "Profile " + profileToString(profile) - + " state = " + profileStateToString(profileState)); - final boolean connected = profileState == BluetoothProfile.STATE_CONNECTED; - if (connect != connected) { - profiles.put(profile, true); + SparseArray<Boolean> profiles = new SparseArray<>(); + if (connect) { + // When connecting add every profile we can recognize by uuid. + for (ParcelUuid uuid : uuids) { + final int profile = uuidToProfile(uuid); + if (profile == 0) { + Log.w(TAG, "Device " + deviceToString(device) + " has an unsupported uuid: " + + uuidToString(uuid)); + continue; + } + final boolean connected = info.connectedProfiles.get(profile, false); + if (!connected) { + profiles.put(profile, true); + } } + } else { + // When disconnecting, just add every profile we know they are connected to. + profiles = info.connectedProfiles; } for (int i = 0; i < profiles.size(); i++) { final int profile = profiles.keyAt(i); - mAdapter.getProfileProxy(mContext, new ServiceListener() { - @Override - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (DEBUG) Log.d(TAG, "onServiceConnected " + profileToString(profile)); - final Profile p = BluetoothUtil.getProfile(proxy); - if (p == null) { - Log.w(TAG, "Unable get get Profile for " + profileToString(profile)); - } else { - final boolean ok = connect ? p.connect(device) : p.disconnect(device); - if (DEBUG) Log.d(TAG, action + " " + profileToString(profile) + " " - + (ok ? "succeeded" : "failed")); - } - } - - @Override - public void onServiceDisconnected(int profile) { - if (DEBUG) Log.d(TAG, "onServiceDisconnected " + profileToString(profile)); - } - }, profile); + if (mProfiles.indexOfKey(profile) >= 0) { + final Profile p = BluetoothUtil.getProfile(mProfiles.get(profile)); + final boolean ok = connect ? p.connect(device) : p.disconnect(device); + if (DEBUG) Log.d(TAG, action + " " + profileToString(profile) + " " + + (ok ? "succeeded" : "failed")); + } else { + Log.w(TAG, "Unable get get Profile for " + profileToString(profile)); + } } } @@ -230,11 +259,13 @@ public class BluetoothControllerImpl implements BluetoothController { return mLastDevice != null ? mLastDevice.getAliasName() : null; } - private void updateBondedBluetoothDevices() { + private void updateBluetoothDevices() { if (mAdapter == null) return; final Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices(); for (DeviceInfo info : mDeviceInfo.values()) { info.bonded = false; + info.connectionState = ERROR; + info.connectedProfiles.clear(); } int bondedCount = 0; BluetoothDevice lastBonded = null; @@ -248,12 +279,62 @@ public class BluetoothControllerImpl implements BluetoothController { } } } + final int N = mProfiles.size(); + final int[] connectionType = new int[1]; + for (int i = 0; i < CONNECTION_STATES.length; i++) { + connectionType[0] = CONNECTION_STATES[i]; + for (int j = 0; j < N; j++) { + int profile = mProfiles.keyAt(j); + List<BluetoothDevice> devices = mProfiles.get(profile) + .getDevicesMatchingConnectionStates(connectionType); + for (int k = 0; k < devices.size(); k++) { + DeviceInfo info = mDeviceInfo.get(devices.get(k)); + info.connectionState = CONNECTION_STATES[i]; + if (CONNECTION_STATES[i] == BluetoothProfile.STATE_CONNECTED) { + info.connectedProfiles.put(profile, true); + } + } + } + } if (mLastDevice == null && bondedCount == 1) { mLastDevice = lastBonded; } + // If we are no longer connected to the current device, see if we are connected to + // something else, so we don't display a name we aren't connected to. + if (mLastDevice != null && + mDeviceInfo.get(mLastDevice).connectionState != BluetoothProfile.STATE_CONNECTED) { + // Make sure we don't keep this device while it isn't connected. + mLastDevice = null; + // Look for anything else connected. + final int size = mDeviceInfo.size(); + for (int i = 0; i < size; i++) { + BluetoothDevice device = mDeviceInfo.keyAt(i); + DeviceInfo info = mDeviceInfo.valueAt(i); + if (info.connectionState == BluetoothProfile.STATE_CONNECTED) { + mLastDevice = device; + break; + } + } + } firePairedDevicesChanged(); } + private void bindAllProfiles() { + // Note: This needs to contain all of the types that can be returned by BluetoothUtil + // otherwise we can't find the profiles we need when we connect/disconnect. + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP_SINK); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.AVRCP_CONTROLLER); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET_CLIENT); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.INPUT_DEVICE); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.MAP); + mAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.PAN); + // Note Health is not in this list because health devices aren't 'connected'. + // If profiles are expanded to use more than just connection state and connect/disconnect + // then it should be added. + } + private void firePairedDevicesChanged() { for (Callback cb : mCallbacks) { cb.onBluetoothPairedDevicesChanged(); @@ -283,6 +364,20 @@ public class BluetoothControllerImpl implements BluetoothController { cb.onBluetoothStateChange(mEnabled, mConnecting); } + private final ServiceListener mProfileListener = new ServiceListener() { + @Override + public void onServiceDisconnected(int profile) { + mProfiles.remove(profile); + updateBluetoothDevices(); + } + + @Override + public void onServiceConnected(int profile, BluetoothProfile proxy) { + mProfiles.put(profile, proxy); + updateBluetoothDevices(); + } + }; + private final class Receiver extends BroadcastReceiver { public void register() { final IntentFilter filter = new IntentFilter(); @@ -290,6 +385,15 @@ public class BluetoothControllerImpl implements BluetoothController { filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); filter.addAction(BluetoothDevice.ACTION_ALIAS_CHANGED); + filter.addAction(BluetoothDevice.ACTION_CLASS_CHANGED); + filter.addAction(BluetoothDevice.ACTION_UUID); + filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothMap.ACTION_CONNECTION_STATE_CHANGED); + filter.addAction(BluetoothPan.ACTION_CONNECTION_STATE_CHANGED); mContext.registerReceiver(this, filter); } @@ -301,16 +405,13 @@ public class BluetoothControllerImpl implements BluetoothController { setAdapterState(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, ERROR)); if (DEBUG) Log.d(TAG, "ACTION_STATE_CHANGED " + mEnabled); } else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { - final DeviceInfo info = updateInfo(device); + updateInfo(device); final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, ERROR); - if (state != ERROR) { - info.connectionState = state; - } mLastDevice = device; if (DEBUG) Log.d(TAG, "ACTION_CONNECTION_STATE_CHANGED " + connectionStateToString(state) + " " + deviceToString(device)); - setConnecting(info.connectionState == BluetoothAdapter.STATE_CONNECTING); + setConnecting(state == BluetoothAdapter.STATE_CONNECTING); } else if (action.equals(BluetoothDevice.ACTION_ALIAS_CHANGED)) { updateInfo(device); mLastDevice = device; @@ -318,7 +419,8 @@ public class BluetoothControllerImpl implements BluetoothController { if (DEBUG) Log.d(TAG, "ACTION_BOND_STATE_CHANGED " + device); // we'll update all bonded devices below } - updateBondedBluetoothDevices(); + // Always update bluetooth devices state. + updateBluetoothDevices(); } } @@ -332,5 +434,6 @@ public class BluetoothControllerImpl implements BluetoothController { private static class DeviceInfo { int connectionState = BluetoothAdapter.STATE_DISCONNECTED; boolean bonded; // per getBondedDevices + SparseArray<Boolean> connectedProfiles = new SparseArray<>(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothUtil.java index 1b4be85..ed8ac2c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothUtil.java @@ -36,7 +36,10 @@ public class BluetoothUtil { if (profile == BluetoothProfile.HEADSET) return "HEADSET"; if (profile == BluetoothProfile.A2DP) return "A2DP"; if (profile == BluetoothProfile.AVRCP_CONTROLLER) return "AVRCP_CONTROLLER"; - return "UNKNOWN"; + if (profile == BluetoothProfile.PAN) return "PAN"; + if (profile == BluetoothProfile.INPUT_DEVICE) return "INPUT_DEVICE"; + if (profile == BluetoothProfile.MAP) return "MAP"; + return "UNKNOWN(" + profile + ")"; } public static String profileStateToString(int state) { @@ -106,6 +109,11 @@ public class BluetoothUtil { if (BluetoothUuid.AvrcpController.equals(uuid)) return BluetoothProfile.AVRCP_CONTROLLER; + if (BluetoothUuid.Hid.equals(uuid)) return BluetoothProfile.INPUT_DEVICE; + if (BluetoothUuid.Hogp.equals(uuid)) return BluetoothProfile.INPUT_DEVICE; + + if (BluetoothUuid.NAP.equals(uuid)) return BluetoothProfile.PAN; + return 0; } |
