diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java new file mode 100644 index 0000000000000..fbfa5e5ea109b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import static com.android.systemui.statusbar.policy.DevicePostureController.Callback; + +import android.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Listener for device posture changes. This can be used to query the current posture, or register + * for events when it changes. + */ +public interface DevicePostureController extends CallbackController { + @IntDef(prefix = {"DEVICE_POSTURE_"}, value = { + DEVICE_POSTURE_UNKNOWN, + DEVICE_POSTURE_CLOSED, + DEVICE_POSTURE_HALF_OPENED, + DEVICE_POSTURE_OPENED, + DEVICE_POSTURE_FLIPPED + }) + @Retention(RetentionPolicy.SOURCE) + @interface DevicePostureInt {} + + // NOTE: These constants **must** match those defined for Jetpack Sidecar. This is because we + // use the Device State -> Jetpack Posture map in DevicePostureControllerImpl to translate + // between the two. + int DEVICE_POSTURE_UNKNOWN = 0; + int DEVICE_POSTURE_CLOSED = 1; + int DEVICE_POSTURE_HALF_OPENED = 2; + int DEVICE_POSTURE_OPENED = 3; + int DEVICE_POSTURE_FLIPPED = 4; + + /** Return the current device posture. */ + @DevicePostureInt int getDevicePosture(); + + /** Callback to be notified about device posture changes. */ + interface Callback { + /** Called when the posture changes. */ + void onPostureChanged(@DevicePostureInt int posture); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java new file mode 100644 index 0000000000000..8471e0aa1640f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureControllerImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.Context; +import android.hardware.devicestate.DeviceStateManager; +import android.util.SparseIntArray; + +import androidx.annotation.NonNull; + +import com.android.internal.R; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +import javax.inject.Inject; + +/** Implementation of {@link DevicePostureController} using the DeviceStateManager. */ +@SysUISingleton +public class DevicePostureControllerImpl implements DevicePostureController { + private final List mListeners = new ArrayList<>(); + private int mCurrentDevicePosture = DEVICE_POSTURE_UNKNOWN; + + private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); + + @Inject + public DevicePostureControllerImpl( + Context context, DeviceStateManager deviceStateManager, @Main Executor executor) { + // Most of this is borrowed from WindowManager/Jetpack/DeviceStateManagerPostureProducer. + // Using the sidecar/extension libraries directly brings in a new dependency that it'd be + // good to avoid (along with the fact that sidecar is deprecated, and extensions isn't fully + // ready yet), and we'd have to make our own layer over the sidecar library anyway to easily + // allow the implementation to change, so it was easier to just interface with + // DeviceStateManager directly. + String[] deviceStatePosturePairs = context.getResources() + .getStringArray(R.array.config_device_state_postures); + for (String deviceStatePosturePair : deviceStatePosturePairs) { + String[] deviceStatePostureMapping = deviceStatePosturePair.split(":"); + if (deviceStatePostureMapping.length != 2) { + continue; + } + + int deviceState; + int posture; + try { + deviceState = Integer.parseInt(deviceStatePostureMapping[0]); + posture = Integer.parseInt(deviceStatePostureMapping[1]); + } catch (NumberFormatException e) { + continue; + } + + mDeviceStateToPostureMap.put(deviceState, posture); + } + + deviceStateManager.registerCallback(executor, state -> { + mCurrentDevicePosture = + mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN); + + mListeners.forEach(l -> l.onPostureChanged(mCurrentDevicePosture)); + }); + } + + @Override + public void addCallback(@NonNull Callback listener) { + mListeners.add(listener); + } + + @Override + public void removeCallback(@NonNull Callback listener) { + mListeners.remove(listener); + } + + @Override + public int getDevicePosture() { + return mCurrentDevicePosture; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java index 9fb0453a28888..c224cf574528c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java @@ -28,6 +28,8 @@ import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastControllerImpl; import com.android.systemui.statusbar.policy.DeviceControlsController; import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl; +import com.android.systemui.statusbar.policy.DevicePostureController; +import com.android.systemui.statusbar.policy.DevicePostureControllerImpl; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.ExtensionControllerImpl; import com.android.systemui.statusbar.policy.FlashlightController; @@ -129,6 +131,11 @@ public interface StatusBarPolicyModule { NetworkController.AccessPointController provideAccessPointController( AccessPointControllerImpl accessPointControllerImpl); + /** */ + @Binds + DevicePostureController provideDevicePostureController( + DevicePostureControllerImpl devicePostureControllerImpl); + /** */ @SysUISingleton @Provides