Merge "Add callbacks for change in supported device states and non-override state." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e72cce5235
@@ -1021,17 +1021,19 @@ package android.hardware.camera2 {
|
||||
package android.hardware.devicestate {
|
||||
|
||||
public final class DeviceStateManager {
|
||||
method public void addDeviceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateListener);
|
||||
method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
|
||||
method @NonNull public int[] getSupportedStates();
|
||||
method public void removeDeviceStateListener(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateListener);
|
||||
method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
|
||||
method @RequiresPermission(android.Manifest.permission.CONTROL_DEVICE_STATE) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
|
||||
method public void unregisterCallback(@NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
|
||||
field public static final int MAXIMUM_DEVICE_STATE = 255; // 0xff
|
||||
field public static final int MINIMUM_DEVICE_STATE = 0; // 0x0
|
||||
}
|
||||
|
||||
public static interface DeviceStateManager.DeviceStateListener {
|
||||
method public void onDeviceStateChanged(int);
|
||||
public static interface DeviceStateManager.DeviceStateCallback {
|
||||
method public default void onBaseStateChanged(int);
|
||||
method public void onStateChanged(int);
|
||||
method public default void onSupportedStatesChanged(@NonNull int[]);
|
||||
}
|
||||
|
||||
public final class DeviceStateRequest {
|
||||
|
||||
19
core/java/android/hardware/devicestate/DeviceStateInfo.aidl
Normal file
19
core/java/android/hardware/devicestate/DeviceStateInfo.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 android.hardware.devicestate;
|
||||
|
||||
parcelable DeviceStateInfo;
|
||||
162
core/java/android/hardware/devicestate/DeviceStateInfo.java
Normal file
162
core/java/android/hardware/devicestate/DeviceStateInfo.java
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* 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 android.hardware.devicestate;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
|
||||
/**
|
||||
* Information about the state of the device.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class DeviceStateInfo implements Parcelable {
|
||||
/** Bit that indicates the {@link #supportedStates} field has changed. */
|
||||
public static final int CHANGED_SUPPORTED_STATES = 1 << 0;
|
||||
|
||||
/** Bit that indicates the {@link #baseState} field has changed. */
|
||||
public static final int CHANGED_BASE_STATE = 1 << 1;
|
||||
|
||||
/** Bit that indicates the {@link #currentState} field has changed. */
|
||||
public static final int CHANGED_CURRENT_STATE = 1 << 2;
|
||||
|
||||
@IntDef(prefix = {"CHANGED_"}, flag = true, value = {
|
||||
CHANGED_SUPPORTED_STATES,
|
||||
CHANGED_BASE_STATE,
|
||||
CHANGED_CURRENT_STATE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ChangeFlags {}
|
||||
|
||||
/**
|
||||
* The list of states supported by the device.
|
||||
*/
|
||||
@NonNull
|
||||
public final int[] supportedStates;
|
||||
|
||||
/**
|
||||
* The base (non-override) state of the device. The base state is the state of the device
|
||||
* ignoring any override requests made through a call to {@link DeviceStateManager#requestState(
|
||||
* DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
|
||||
*/
|
||||
public final int baseState;
|
||||
|
||||
/**
|
||||
* The state of the device.
|
||||
*/
|
||||
public final int currentState;
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link DeviceStateInfo}.
|
||||
* <p>
|
||||
* NOTE: Unlike {@link #DeviceStateInfo(DeviceStateInfo)}, this constructor does not copy the
|
||||
* supplied parameters.
|
||||
*/
|
||||
public DeviceStateInfo(@NonNull int[] supportedStates, int baseState, int state) {
|
||||
this.supportedStates = supportedStates;
|
||||
this.baseState = baseState;
|
||||
this.currentState = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link DeviceStateInfo} copying the fields of {@code info} into
|
||||
* the fields of the returned instance.
|
||||
*/
|
||||
public DeviceStateInfo(@NonNull DeviceStateInfo info) {
|
||||
this(Arrays.copyOf(info.supportedStates, info.supportedStates.length),
|
||||
info.baseState, info.currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) return true;
|
||||
if (other == null || getClass() != other.getClass()) return false;
|
||||
DeviceStateInfo that = (DeviceStateInfo) other;
|
||||
return baseState == that.baseState
|
||||
&& currentState == that.currentState
|
||||
&& Arrays.equals(supportedStates, that.supportedStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hash(baseState, currentState);
|
||||
result = 31 * result + Arrays.hashCode(supportedStates);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns a bitmask of the differences between this instance and {@code other}. */
|
||||
@ChangeFlags
|
||||
public int diff(@NonNull DeviceStateInfo other) {
|
||||
int diff = 0;
|
||||
if (!Arrays.equals(supportedStates, other.supportedStates)) {
|
||||
diff |= CHANGED_SUPPORTED_STATES;
|
||||
}
|
||||
if (baseState != other.baseState) {
|
||||
diff |= CHANGED_BASE_STATE;
|
||||
}
|
||||
if (currentState != other.currentState) {
|
||||
diff |= CHANGED_CURRENT_STATE;
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(supportedStates.length);
|
||||
for (int i = 0; i < supportedStates.length; i++) {
|
||||
dest.writeInt(supportedStates[i]);
|
||||
}
|
||||
|
||||
dest.writeInt(baseState);
|
||||
dest.writeInt(currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<DeviceStateInfo> CREATOR = new Creator<DeviceStateInfo>() {
|
||||
@Override
|
||||
public DeviceStateInfo createFromParcel(Parcel source) {
|
||||
final int numberOfSupportedStates = source.readInt();
|
||||
final int[] supportedStates = new int[numberOfSupportedStates];
|
||||
for (int i = 0; i < numberOfSupportedStates; i++) {
|
||||
supportedStates[i] = source.readInt();
|
||||
}
|
||||
final int baseState = source.readInt();
|
||||
final int currentState = source.readInt();
|
||||
|
||||
return new DeviceStateInfo(supportedStates, baseState, currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStateInfo[] newArray(int size) {
|
||||
return new DeviceStateInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -111,38 +111,63 @@ public final class DeviceStateManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to receive notifications about changes in device state.
|
||||
* Registers a callback to receive notifications about changes in device state.
|
||||
*
|
||||
* @param executor the executor to process notifications.
|
||||
* @param listener the listener to register.
|
||||
* @param callback the callback to register.
|
||||
*
|
||||
* @see DeviceStateListener
|
||||
* @see DeviceStateCallback
|
||||
*/
|
||||
public void addDeviceStateListener(@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull DeviceStateListener listener) {
|
||||
mGlobal.registerDeviceStateListener(listener, executor);
|
||||
public void registerCallback(@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull DeviceStateCallback callback) {
|
||||
mGlobal.registerDeviceStateCallback(callback, executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a listener previously registered with
|
||||
* {@link #addDeviceStateListener(Executor, DeviceStateListener)}.
|
||||
* Unregisters a callback previously registered with
|
||||
* {@link #registerCallback(Executor, DeviceStateCallback)}.
|
||||
*/
|
||||
public void removeDeviceStateListener(@NonNull DeviceStateListener listener) {
|
||||
mGlobal.unregisterDeviceStateListener(listener);
|
||||
public void unregisterCallback(@NonNull DeviceStateCallback callback) {
|
||||
mGlobal.unregisterDeviceStateCallback(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in device states.
|
||||
*/
|
||||
public interface DeviceStateListener {
|
||||
/** Callback to receive notifications about changes in device state. */
|
||||
public interface DeviceStateCallback {
|
||||
/**
|
||||
* Called in response to a change in the states supported by the device.
|
||||
* <p>
|
||||
* Guaranteed to be called once on registration of the callback with the initial value and
|
||||
* then on every subsequent change in the supported states.
|
||||
*
|
||||
* @param supportedStates the new supported states.
|
||||
*
|
||||
* @see DeviceStateManager#getSupportedStates()
|
||||
*/
|
||||
default void onSupportedStatesChanged(@NonNull int[] supportedStates) {}
|
||||
|
||||
/**
|
||||
* Called in response to a change in the base device state.
|
||||
* <p>
|
||||
* The base state is the state of the device without considering any requests made through
|
||||
* calls to {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}
|
||||
* from any client process. The base state is guaranteed to match the state provided with a
|
||||
* call to {@link #onStateChanged(int)} when there are no active requests from any process.
|
||||
* <p>
|
||||
* Guaranteed to be called once on registration of the callback with the initial value and
|
||||
* then on every subsequent change in the non-override state.
|
||||
*
|
||||
* @param state the new base device state.
|
||||
*/
|
||||
default void onBaseStateChanged(int state) {}
|
||||
|
||||
/**
|
||||
* Called in response to device state changes.
|
||||
* <p>
|
||||
* Guaranteed to be called once on registration of the listener with the
|
||||
* initial value and then on every subsequent change in device state.
|
||||
* Guaranteed to be called once on registration of the callback with the initial value and
|
||||
* then on every subsequent change in device state.
|
||||
*
|
||||
* @param deviceState the new device state.
|
||||
* @param state the new device state.
|
||||
*/
|
||||
void onDeviceStateChanged(int deviceState);
|
||||
void onStateChanged(int state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package android.hardware.devicestate;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.devicestate.DeviceStateManager.DeviceStateListener;
|
||||
import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -31,12 +31,14 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Provides communication with the device state system service on behalf of applications.
|
||||
*
|
||||
* @see DeviceStateManager
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||
@@ -68,13 +70,13 @@ public final class DeviceStateManagerGlobal {
|
||||
private DeviceStateManagerCallback mCallback;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayList<DeviceStateListenerWrapper> mListeners = new ArrayList<>();
|
||||
private final ArrayList<DeviceStateCallbackWrapper> mCallbacks = new ArrayList<>();
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayMap<IBinder, DeviceStateRequestWrapper> mRequests = new ArrayMap<>();
|
||||
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
private Integer mLastReceivedState;
|
||||
private DeviceStateInfo mLastReceivedInfo;
|
||||
|
||||
@VisibleForTesting
|
||||
public DeviceStateManagerGlobal(@NonNull IDeviceStateManager deviceStateManager) {
|
||||
@@ -87,18 +89,31 @@ public final class DeviceStateManagerGlobal {
|
||||
* @see DeviceStateManager#getSupportedStates()
|
||||
*/
|
||||
public int[] getSupportedStates() {
|
||||
try {
|
||||
return mDeviceStateManager.getSupportedDeviceStates();
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
synchronized (mLock) {
|
||||
final DeviceStateInfo currentInfo;
|
||||
if (mLastReceivedInfo != null) {
|
||||
// If we have mLastReceivedInfo a callback is registered for this instance and it
|
||||
// is receiving the most recent info from the server. Use that info here.
|
||||
currentInfo = mLastReceivedInfo;
|
||||
} else {
|
||||
// If mLastReceivedInfo is null there is no registered callback so we manually
|
||||
// fetch the current info.
|
||||
try {
|
||||
currentInfo = mDeviceStateManager.getDeviceStateInfo();
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
return Arrays.copyOf(currentInfo.supportedStates, currentInfo.supportedStates.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits a {@link DeviceStateRequest request} to modify the device state.
|
||||
*
|
||||
* @see DeviceStateManager#requestState(DeviceStateRequest,
|
||||
* Executor, DeviceStateRequest.Callback)
|
||||
* @see DeviceStateManager#requestState(DeviceStateRequest, Executor,
|
||||
* DeviceStateRequest.Callback)
|
||||
* @see DeviceStateRequest
|
||||
*/
|
||||
public void requestState(@NonNull DeviceStateRequest request,
|
||||
@@ -157,49 +172,56 @@ public final class DeviceStateManagerGlobal {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to receive notifications about changes in device state.
|
||||
* Registers a callback to receive notifications about changes in device state.
|
||||
*
|
||||
* @see DeviceStateManager#addDeviceStateListener(Executor, DeviceStateListener)
|
||||
* @see DeviceStateManager#registerCallback(Executor, DeviceStateCallback)
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||
public void registerDeviceStateListener(@NonNull DeviceStateListener listener,
|
||||
public void registerDeviceStateCallback(@NonNull DeviceStateCallback callback,
|
||||
@NonNull Executor executor) {
|
||||
Integer stateToReport;
|
||||
DeviceStateListenerWrapper wrapper;
|
||||
DeviceStateCallbackWrapper wrapper;
|
||||
DeviceStateInfo currentInfo;
|
||||
synchronized (mLock) {
|
||||
registerCallbackIfNeededLocked();
|
||||
|
||||
int index = findListenerLocked(listener);
|
||||
int index = findCallbackLocked(callback);
|
||||
if (index != -1) {
|
||||
// This listener is already registered.
|
||||
// This callback is already registered.
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper = new DeviceStateListenerWrapper(listener, executor);
|
||||
mListeners.add(wrapper);
|
||||
stateToReport = mLastReceivedState;
|
||||
registerCallbackIfNeededLocked();
|
||||
if (mLastReceivedInfo == null) {
|
||||
// Initialize the last received info with the current info if this is the first
|
||||
// callback being registered.
|
||||
try {
|
||||
mLastReceivedInfo = mDeviceStateManager.getDeviceStateInfo();
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
currentInfo = new DeviceStateInfo(mLastReceivedInfo);
|
||||
|
||||
wrapper = new DeviceStateCallbackWrapper(callback, executor);
|
||||
mCallbacks.add(wrapper);
|
||||
}
|
||||
|
||||
if (stateToReport != null) {
|
||||
// Notify the listener with the most recent device state from the server. If the state
|
||||
// to report is null this is likely the first listener added and we're still waiting
|
||||
// from the callback from the server.
|
||||
wrapper.notifyDeviceStateChanged(stateToReport);
|
||||
}
|
||||
wrapper.notifySupportedStatesChanged(currentInfo.supportedStates);
|
||||
wrapper.notifyBaseStateChanged(currentInfo.baseState);
|
||||
wrapper.notifyStateChanged(currentInfo.currentState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a listener previously registered with
|
||||
* {@link #registerDeviceStateListener(DeviceStateListener, Executor)}.
|
||||
* Unregisters a callback previously registered with
|
||||
* {@link #registerDeviceStateCallback(DeviceStateCallback, Executor)}}.
|
||||
*
|
||||
* @see DeviceStateManager#addDeviceStateListener(Executor, DeviceStateListener)
|
||||
* @see DeviceStateManager#unregisterCallback(DeviceStateCallback)
|
||||
*/
|
||||
@VisibleForTesting(visibility = Visibility.PACKAGE)
|
||||
public void unregisterDeviceStateListener(DeviceStateListener listener) {
|
||||
public void unregisterDeviceStateCallback(@NonNull DeviceStateCallback callback) {
|
||||
synchronized (mLock) {
|
||||
int indexToRemove = findListenerLocked(listener);
|
||||
int indexToRemove = findCallbackLocked(callback);
|
||||
if (indexToRemove != -1) {
|
||||
mListeners.remove(indexToRemove);
|
||||
mCallbacks.remove(indexToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,14 +232,15 @@ public final class DeviceStateManagerGlobal {
|
||||
try {
|
||||
mDeviceStateManager.registerCallback(mCallback);
|
||||
} catch (RemoteException ex) {
|
||||
mCallback = null;
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int findListenerLocked(DeviceStateListener listener) {
|
||||
for (int i = 0; i < mListeners.size(); i++) {
|
||||
if (mListeners.get(i).mDeviceStateListener.equals(listener)) {
|
||||
private int findCallbackLocked(DeviceStateCallback callback) {
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
if (mCallbacks.get(i).mDeviceStateCallback.equals(callback)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -234,16 +257,34 @@ public final class DeviceStateManagerGlobal {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Handles a call from the server that the device state has changed. */
|
||||
private void handleDeviceStateChanged(int newDeviceState) {
|
||||
ArrayList<DeviceStateListenerWrapper> listeners;
|
||||
/** Handles a call from the server that the device state info has changed. */
|
||||
private void handleDeviceStateInfoChanged(@NonNull DeviceStateInfo info) {
|
||||
ArrayList<DeviceStateCallbackWrapper> callbacks;
|
||||
DeviceStateInfo oldInfo;
|
||||
synchronized (mLock) {
|
||||
mLastReceivedState = newDeviceState;
|
||||
listeners = new ArrayList<>(mListeners);
|
||||
oldInfo = mLastReceivedInfo;
|
||||
mLastReceivedInfo = info;
|
||||
callbacks = new ArrayList<>(mCallbacks);
|
||||
}
|
||||
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
listeners.get(i).notifyDeviceStateChanged(newDeviceState);
|
||||
final int diff = oldInfo == null ? 1 : info.diff(oldInfo);
|
||||
if ((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0) {
|
||||
for (int i = 0; i < callbacks.size(); i++) {
|
||||
// Copy the array to prevent callbacks from modifying the internal state.
|
||||
final int[] supportedStates = Arrays.copyOf(info.supportedStates,
|
||||
info.supportedStates.length);
|
||||
callbacks.get(i).notifySupportedStatesChanged(supportedStates);
|
||||
}
|
||||
}
|
||||
if ((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0) {
|
||||
for (int i = 0; i < callbacks.size(); i++) {
|
||||
callbacks.get(i).notifyBaseStateChanged(info.baseState);
|
||||
}
|
||||
}
|
||||
if ((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0) {
|
||||
for (int i = 0; i < callbacks.size(); i++) {
|
||||
callbacks.get(i).notifyStateChanged(info.currentState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,8 +332,8 @@ public final class DeviceStateManagerGlobal {
|
||||
|
||||
private final class DeviceStateManagerCallback extends IDeviceStateManagerCallback.Stub {
|
||||
@Override
|
||||
public void onDeviceStateChanged(int deviceState) {
|
||||
handleDeviceStateChanged(deviceState);
|
||||
public void onDeviceStateInfoChanged(DeviceStateInfo info) {
|
||||
handleDeviceStateInfoChanged(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,17 +352,29 @@ public final class DeviceStateManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DeviceStateListenerWrapper {
|
||||
private final DeviceStateListener mDeviceStateListener;
|
||||
private static final class DeviceStateCallbackWrapper {
|
||||
@NonNull
|
||||
private final DeviceStateCallback mDeviceStateCallback;
|
||||
@NonNull
|
||||
private final Executor mExecutor;
|
||||
|
||||
DeviceStateListenerWrapper(DeviceStateListener listener, Executor executor) {
|
||||
mDeviceStateListener = listener;
|
||||
DeviceStateCallbackWrapper(@NonNull DeviceStateCallback callback,
|
||||
@NonNull Executor executor) {
|
||||
mDeviceStateCallback = callback;
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
void notifyDeviceStateChanged(int newDeviceState) {
|
||||
mExecutor.execute(() -> mDeviceStateListener.onDeviceStateChanged(newDeviceState));
|
||||
void notifySupportedStatesChanged(int[] newSupportedStates) {
|
||||
mExecutor.execute(() ->
|
||||
mDeviceStateCallback.onSupportedStatesChanged(newSupportedStates));
|
||||
}
|
||||
|
||||
void notifyBaseStateChanged(int newBaseState) {
|
||||
mExecutor.execute(() -> mDeviceStateCallback.onBaseStateChanged(newBaseState));
|
||||
}
|
||||
|
||||
void notifyStateChanged(int newDeviceState) {
|
||||
mExecutor.execute(() -> mDeviceStateCallback.onStateChanged(newDeviceState));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ public final class DeviceStateRequest {
|
||||
* requested state.
|
||||
* <p>
|
||||
* Guaranteed to be called after a call to
|
||||
* {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)} with a state
|
||||
* {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)} with a state
|
||||
* matching the requested state.
|
||||
*/
|
||||
default void onRequestActivated(@NonNull DeviceStateRequest request) {}
|
||||
@@ -125,7 +125,7 @@ public final class DeviceStateRequest {
|
||||
* Called to indicate the request has been temporarily suspended.
|
||||
* <p>
|
||||
* Guaranteed to be called before a call to
|
||||
* {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)}.
|
||||
* {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
|
||||
*/
|
||||
default void onRequestSuspended(@NonNull DeviceStateRequest request) {}
|
||||
|
||||
@@ -135,7 +135,7 @@ public final class DeviceStateRequest {
|
||||
* DeviceStateRequest.Callback)}.
|
||||
* <p>
|
||||
* Guaranteed to be called before a call to
|
||||
* {@link DeviceStateManager.DeviceStateListener#onDeviceStateChanged(int)}.
|
||||
* {@link DeviceStateManager.DeviceStateCallback#onStateChanged(int)}.
|
||||
* <p>
|
||||
* Note: A call to {@link #onRequestSuspended(DeviceStateRequest)} is not guaranteed to
|
||||
* occur before this method.
|
||||
|
||||
@@ -16,25 +16,26 @@
|
||||
|
||||
package android.hardware.devicestate;
|
||||
|
||||
import android.hardware.devicestate.DeviceStateInfo;
|
||||
import android.hardware.devicestate.IDeviceStateManagerCallback;
|
||||
|
||||
/** @hide */
|
||||
interface IDeviceStateManager {
|
||||
/** Returns the current device state info. */
|
||||
DeviceStateInfo getDeviceStateInfo();
|
||||
|
||||
/**
|
||||
* Registers a callback to receive notifications from the device state manager. Only one
|
||||
* callback can be registered per-process.
|
||||
* <p>
|
||||
* As the callback mechanism is used to alert the caller of changes to request status a callback
|
||||
* <b>MUST</b> be registered before calling {@link #requestState(IBinder, int, int)} or
|
||||
* {@link #cancelRequest(IBinder)}. Otherwise an exception will be thrown.
|
||||
* {@link #cancelRequest(IBinder)}, otherwise an exception will be thrown.
|
||||
*
|
||||
* @throws SecurityException if a callback is already registered for the calling process.
|
||||
*/
|
||||
void registerCallback(in IDeviceStateManagerCallback callback);
|
||||
|
||||
/** Returns the array of supported device state identifiers. */
|
||||
int[] getSupportedDeviceStates();
|
||||
|
||||
/**
|
||||
* Requests that the device enter the supplied {@code state}. A callback <b>MUST</b> have been
|
||||
* previously registered with {@link #registerCallback(IDeviceStateManagerCallback)} before a
|
||||
|
||||
@@ -16,20 +16,23 @@
|
||||
|
||||
package android.hardware.devicestate;
|
||||
|
||||
import android.hardware.devicestate.DeviceStateInfo;
|
||||
|
||||
/** @hide */
|
||||
interface IDeviceStateManagerCallback {
|
||||
/**
|
||||
* Called in response to a change in device state. Guaranteed to be called once with the initial
|
||||
* value on registration of the callback.
|
||||
* Called in response to a change in {@link DeviceStateInfo}.
|
||||
*
|
||||
* @param deviceState the new state of the device.
|
||||
* @param info the new device state info.
|
||||
*
|
||||
* @see DeviceStateInfo
|
||||
*/
|
||||
oneway void onDeviceStateChanged(int deviceState);
|
||||
oneway void onDeviceStateInfoChanged(in DeviceStateInfo info);
|
||||
|
||||
/**
|
||||
* Called to notify the callback that a request has become active. Guaranteed to be called
|
||||
* after a subsequent call to {@link #onDeviceStateChanged(int)} if the request becoming active
|
||||
* resulted in a device state change.
|
||||
* after a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
|
||||
* becoming active resulted in a change of device state info.
|
||||
*
|
||||
* @param token the request token previously registered with
|
||||
* {@link IDeviceStateManager#requestState(IBinder, int, int)}
|
||||
@@ -38,8 +41,8 @@ interface IDeviceStateManagerCallback {
|
||||
|
||||
/**
|
||||
* Called to notify the callback that a request has become suspended. Guaranteed to be called
|
||||
* before a subsequent call to {@link #onDeviceStateChanged(int)} if the request becoming
|
||||
* suspended resulted in a device state change.
|
||||
* before a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
|
||||
* becoming suspended resulted in a change of device state info.
|
||||
*
|
||||
* @param token the request token previously registered with
|
||||
* {@link IDeviceStateManager#requestState(IBinder, int, int)}
|
||||
@@ -49,8 +52,8 @@ interface IDeviceStateManagerCallback {
|
||||
/**
|
||||
* Called to notify the callback that a request has become canceled. No further callbacks will
|
||||
* be triggered for this request. Guaranteed to be called before a subsequent call to
|
||||
* {@link #onDeviceStateChanged(int)} if the request becoming canceled resulted in a device
|
||||
* state change.
|
||||
* {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request becoming canceled resulted
|
||||
* in a change of device state info.
|
||||
*
|
||||
* @param token the request token previously registered with
|
||||
* {@link IDeviceStateManager#requestState(IBinder, int, int)}
|
||||
|
||||
@@ -28,6 +28,7 @@ android_test {
|
||||
static_libs: [
|
||||
"androidx.test.rules",
|
||||
"frameworks-base-testutils",
|
||||
"mockito-target-minus-junit4",
|
||||
],
|
||||
libs: ["android.test.runner"],
|
||||
platform_apis: true,
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 android.hardware.devicestate;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DeviceStateInfo}.
|
||||
* <p/>
|
||||
* Run with <code>atest DeviceStateInfoTest</code>.
|
||||
*/
|
||||
@RunWith(JUnit4.class)
|
||||
@SmallTest
|
||||
public final class DeviceStateInfoTest {
|
||||
@Test
|
||||
public void create() {
|
||||
final int[] supportedStates = new int[] { 0, 1, 2 };
|
||||
final int baseState = 0;
|
||||
final int currentState = 2;
|
||||
|
||||
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
|
||||
assertNotNull(info.supportedStates);
|
||||
assertEquals(supportedStates, info.supportedStates);
|
||||
assertEquals(baseState, info.baseState);
|
||||
assertEquals(currentState, info.currentState);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals() {
|
||||
final int[] supportedStates = new int[] { 0, 1, 2 };
|
||||
final int baseState = 0;
|
||||
final int currentState = 2;
|
||||
|
||||
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
|
||||
assertTrue(info.equals(info));
|
||||
|
||||
final DeviceStateInfo sameInfo = new DeviceStateInfo(supportedStates, baseState,
|
||||
currentState);
|
||||
assertTrue(info.equals(sameInfo));
|
||||
|
||||
final DeviceStateInfo differentInfo = new DeviceStateInfo(new int[]{ 0, 2}, baseState,
|
||||
currentState);
|
||||
assertFalse(info.equals(differentInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diff_sameObject() {
|
||||
final int[] supportedStates = new int[] { 0, 1, 2 };
|
||||
final int baseState = 0;
|
||||
final int currentState = 2;
|
||||
|
||||
final DeviceStateInfo info = new DeviceStateInfo(supportedStates, baseState, currentState);
|
||||
assertEquals(0, info.diff(info));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diff_differentSupportedStates() {
|
||||
final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 0);
|
||||
final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 2 }, 0, 0);
|
||||
final int diff = info.diff(otherInfo);
|
||||
assertTrue((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diff_differentNonOverrideState() {
|
||||
final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 1, 0);
|
||||
final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 2, 0);
|
||||
final int diff = info.diff(otherInfo);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
|
||||
assertTrue((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void diff_differentState() {
|
||||
final DeviceStateInfo info = new DeviceStateInfo(new int[] { 1 }, 0, 1);
|
||||
final DeviceStateInfo otherInfo = new DeviceStateInfo(new int[] { 1 }, 0, 2);
|
||||
final int diff = info.diff(otherInfo);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_SUPPORTED_STATES) > 0);
|
||||
assertFalse((diff & DeviceStateInfo.CHANGED_BASE_STATE) > 0);
|
||||
assertTrue((diff & DeviceStateInfo.CHANGED_CURRENT_STATE) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeToParcel() {
|
||||
final int[] supportedStates = new int[] { 0, 1, 2 };
|
||||
final int nonOverrideState = 0;
|
||||
final int state = 2;
|
||||
final DeviceStateInfo originalInfo =
|
||||
new DeviceStateInfo(supportedStates, nonOverrideState, state);
|
||||
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
originalInfo.writeToParcel(parcel, 0 /* flags */);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
final DeviceStateInfo info = DeviceStateInfo.CREATOR.createFromParcel(parcel);
|
||||
assertEquals(originalInfo, info);
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,15 @@
|
||||
|
||||
package android.hardware.devicestate;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
@@ -32,6 +36,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -58,42 +63,75 @@ public final class DeviceStateManagerGlobalTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerListener() {
|
||||
mService.setBaseState(DEFAULT_DEVICE_STATE);
|
||||
public void registerCallback() {
|
||||
DeviceStateCallback callback1 = mock(DeviceStateCallback.class);
|
||||
DeviceStateCallback callback2 = mock(DeviceStateCallback.class);
|
||||
|
||||
TestDeviceStateListener listener1 = new TestDeviceStateListener();
|
||||
TestDeviceStateListener listener2 = new TestDeviceStateListener();
|
||||
|
||||
mDeviceStateManagerGlobal.registerDeviceStateListener(listener1,
|
||||
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback1,
|
||||
ConcurrentUtils.DIRECT_EXECUTOR);
|
||||
mDeviceStateManagerGlobal.registerDeviceStateListener(listener2,
|
||||
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback2,
|
||||
ConcurrentUtils.DIRECT_EXECUTOR);
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener1.getLastReportedState().intValue());
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener2.getLastReportedState().intValue());
|
||||
|
||||
// Verify initial callbacks
|
||||
verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
|
||||
verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
|
||||
verify(callback1).onStateChanged(eq(mService.getMergedState()));
|
||||
verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
|
||||
verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
|
||||
verify(callback2).onStateChanged(eq(mService.getMergedState()));
|
||||
|
||||
Mockito.reset(callback1);
|
||||
Mockito.reset(callback2);
|
||||
|
||||
// Change the supported states and verify callback
|
||||
mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE });
|
||||
verify(callback1).onSupportedStatesChanged(eq(mService.getSupportedStates()));
|
||||
verify(callback2).onSupportedStatesChanged(eq(mService.getSupportedStates()));
|
||||
mService.setSupportedStates(new int[]{ DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE });
|
||||
|
||||
Mockito.reset(callback1);
|
||||
Mockito.reset(callback2);
|
||||
|
||||
// Change the base state and verify callback
|
||||
mService.setBaseState(OTHER_DEVICE_STATE);
|
||||
assertEquals(OTHER_DEVICE_STATE, listener1.getLastReportedState().intValue());
|
||||
assertEquals(OTHER_DEVICE_STATE, listener2.getLastReportedState().intValue());
|
||||
verify(callback1).onBaseStateChanged(eq(mService.getBaseState()));
|
||||
verify(callback1).onStateChanged(eq(mService.getMergedState()));
|
||||
verify(callback2).onBaseStateChanged(eq(mService.getBaseState()));
|
||||
verify(callback2).onStateChanged(eq(mService.getMergedState()));
|
||||
|
||||
Mockito.reset(callback1);
|
||||
Mockito.reset(callback2);
|
||||
|
||||
// Change the requested state and verify callback
|
||||
DeviceStateRequest request = DeviceStateRequest.newBuilder(DEFAULT_DEVICE_STATE).build();
|
||||
mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
|
||||
|
||||
verify(callback1).onStateChanged(eq(mService.getMergedState()));
|
||||
verify(callback2).onStateChanged(eq(mService.getMergedState()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unregisterListener() {
|
||||
mService.setBaseState(DEFAULT_DEVICE_STATE);
|
||||
public void unregisterCallback() {
|
||||
DeviceStateCallback callback = mock(DeviceStateCallback.class);
|
||||
|
||||
TestDeviceStateListener listener = new TestDeviceStateListener();
|
||||
|
||||
mDeviceStateManagerGlobal.registerDeviceStateListener(listener,
|
||||
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
|
||||
ConcurrentUtils.DIRECT_EXECUTOR);
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
|
||||
|
||||
mDeviceStateManagerGlobal.unregisterDeviceStateListener(listener);
|
||||
// Verify initial callbacks
|
||||
verify(callback).onSupportedStatesChanged(eq(mService.getSupportedStates()));
|
||||
verify(callback).onBaseStateChanged(eq(mService.getBaseState()));
|
||||
verify(callback).onStateChanged(eq(mService.getMergedState()));
|
||||
Mockito.reset(callback);
|
||||
|
||||
mDeviceStateManagerGlobal.unregisterDeviceStateCallback(callback);
|
||||
|
||||
mService.setSupportedStates(new int[]{OTHER_DEVICE_STATE});
|
||||
mService.setBaseState(OTHER_DEVICE_STATE);
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
|
||||
verifyZeroInteractions(callback);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submittingRequestRegisteredCallback() {
|
||||
public void submittingRequestRegistersCallback() {
|
||||
assertTrue(mService.mCallbacks.isEmpty());
|
||||
|
||||
DeviceStateRequest request = DeviceStateRequest.newBuilder(DEFAULT_DEVICE_STATE).build();
|
||||
@@ -104,37 +142,22 @@ public final class DeviceStateManagerGlobalTest {
|
||||
|
||||
@Test
|
||||
public void submitRequest() {
|
||||
mService.setBaseState(DEFAULT_DEVICE_STATE);
|
||||
|
||||
TestDeviceStateListener listener = new TestDeviceStateListener();
|
||||
mDeviceStateManagerGlobal.registerDeviceStateListener(listener,
|
||||
DeviceStateCallback callback = mock(DeviceStateCallback.class);
|
||||
mDeviceStateManagerGlobal.registerDeviceStateCallback(callback,
|
||||
ConcurrentUtils.DIRECT_EXECUTOR);
|
||||
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
|
||||
verify(callback).onStateChanged(eq(mService.getBaseState()));
|
||||
Mockito.reset(callback);
|
||||
|
||||
DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
|
||||
mDeviceStateManagerGlobal.requestState(request, null /* executor */, null /* callback */);
|
||||
|
||||
assertEquals(OTHER_DEVICE_STATE, listener.getLastReportedState().intValue());
|
||||
verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
|
||||
Mockito.reset(callback);
|
||||
|
||||
mDeviceStateManagerGlobal.cancelRequest(request);
|
||||
|
||||
assertEquals(DEFAULT_DEVICE_STATE, listener.getLastReportedState().intValue());
|
||||
}
|
||||
|
||||
private final class TestDeviceStateListener implements DeviceStateManager.DeviceStateListener {
|
||||
@Nullable
|
||||
private Integer mLastReportedDeviceState;
|
||||
|
||||
@Override
|
||||
public void onDeviceStateChanged(int deviceState) {
|
||||
mLastReportedDeviceState = deviceState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getLastReportedState() {
|
||||
return mLastReportedDeviceState;
|
||||
}
|
||||
verify(callback).onStateChanged(eq(mService.getBaseState()));
|
||||
}
|
||||
|
||||
private static final class TestDeviceStateManagerService extends IDeviceStateManager.Stub {
|
||||
@@ -150,12 +173,34 @@ public final class DeviceStateManagerGlobalTest {
|
||||
}
|
||||
}
|
||||
|
||||
private int[] mSupportedStates = new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
|
||||
private int mBaseState = DEFAULT_DEVICE_STATE;
|
||||
private int mMergedState = DEFAULT_DEVICE_STATE;
|
||||
private ArrayList<Request> mRequests = new ArrayList<>();
|
||||
|
||||
private Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
|
||||
|
||||
private DeviceStateInfo getInfo() {
|
||||
final int mergedState = mRequests.isEmpty()
|
||||
? mBaseState : mRequests.get(mRequests.size() - 1).state;
|
||||
return new DeviceStateInfo(mSupportedStates, mBaseState, mergedState);
|
||||
}
|
||||
|
||||
private void notifyDeviceStateInfoChanged() {
|
||||
final DeviceStateInfo info = getInfo();
|
||||
for (IDeviceStateManagerCallback callback : mCallbacks) {
|
||||
try {
|
||||
callback.onDeviceStateInfoChanged(info);
|
||||
} catch (RemoteException e) {
|
||||
// Do nothing. Should never happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceStateInfo getDeviceStateInfo() {
|
||||
return getInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCallback(IDeviceStateManagerCallback callback) {
|
||||
if (mCallbacks.contains(callback)) {
|
||||
@@ -163,16 +208,6 @@ public final class DeviceStateManagerGlobalTest {
|
||||
}
|
||||
|
||||
mCallbacks.add(callback);
|
||||
try {
|
||||
callback.onDeviceStateChanged(mMergedState);
|
||||
} catch (RemoteException e) {
|
||||
// Do nothing. Should never happen.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSupportedDeviceStates() {
|
||||
return new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,7 +225,7 @@ public final class DeviceStateManagerGlobalTest {
|
||||
|
||||
final Request request = new Request(token, state, flags);
|
||||
mRequests.add(request);
|
||||
notifyStateChangedIfNeeded();
|
||||
notifyDeviceStateInfoChanged();
|
||||
|
||||
for (IDeviceStateManagerCallback callback : mCallbacks) {
|
||||
try {
|
||||
@@ -223,32 +258,29 @@ public final class DeviceStateManagerGlobalTest {
|
||||
// Do nothing. Should never happen.
|
||||
}
|
||||
}
|
||||
notifyStateChangedIfNeeded();
|
||||
notifyDeviceStateInfoChanged();
|
||||
}
|
||||
|
||||
public void setSupportedStates(int[] states) {
|
||||
mSupportedStates = states;
|
||||
notifyDeviceStateInfoChanged();
|
||||
}
|
||||
|
||||
public int[] getSupportedStates() {
|
||||
return mSupportedStates;
|
||||
}
|
||||
|
||||
public void setBaseState(int state) {
|
||||
mBaseState = state;
|
||||
notifyStateChangedIfNeeded();
|
||||
notifyDeviceStateInfoChanged();
|
||||
}
|
||||
|
||||
private void notifyStateChangedIfNeeded() {
|
||||
final int originalMergedState = mMergedState;
|
||||
public int getBaseState() {
|
||||
return mBaseState;
|
||||
}
|
||||
|
||||
if (!mRequests.isEmpty()) {
|
||||
mMergedState = mRequests.get(mRequests.size() - 1).state;
|
||||
} else {
|
||||
mMergedState = mBaseState;
|
||||
}
|
||||
|
||||
if (mMergedState != originalMergedState) {
|
||||
for (IDeviceStateManagerCallback callback : mCallbacks) {
|
||||
try {
|
||||
callback.onDeviceStateChanged(mMergedState);
|
||||
} catch (RemoteException e) {
|
||||
// Do nothing. Should never happen.
|
||||
}
|
||||
}
|
||||
}
|
||||
public int getMergedState() {
|
||||
return getInfo().currentState;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.hardware.devicestate.DeviceStateInfo;
|
||||
import android.hardware.devicestate.DeviceStateManager;
|
||||
import android.hardware.devicestate.IDeviceStateManager;
|
||||
import android.hardware.devicestate.IDeviceStateManagerCallback;
|
||||
@@ -47,6 +48,7 @@ import com.android.server.policy.DeviceStatePolicyImpl;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -76,6 +78,9 @@ import java.util.Optional;
|
||||
public final class DeviceStateManagerService extends SystemService {
|
||||
private static final String TAG = "DeviceStateManagerService";
|
||||
private static final boolean DEBUG = false;
|
||||
// The device state to use as a placeholder before callback from the DeviceStateProvider occurs.
|
||||
private static final DeviceState UNSPECIFIED_DEVICE_STATE =
|
||||
new DeviceState(MINIMUM_DEVICE_STATE, "UNSPECIFIED");
|
||||
|
||||
private final Object mLock = new Object();
|
||||
@NonNull
|
||||
@@ -87,11 +92,11 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
@GuardedBy("mLock")
|
||||
private SparseArray<DeviceState> mDeviceStates = new SparseArray<>();
|
||||
|
||||
// The current committed device state. The default of UNSET will be replaced by
|
||||
// the current state after the initial callback from the DeviceStateProvider.
|
||||
// The current committed device state. The default of UNSPECIFIED_DEVICE_STATE will be replaced
|
||||
// by the current state after the initial callback from the DeviceStateProvider.
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
private DeviceState mCommittedState = new DeviceState(MINIMUM_DEVICE_STATE, "UNSET");
|
||||
private DeviceState mCommittedState = UNSPECIFIED_DEVICE_STATE;
|
||||
// The device state that is currently awaiting callback from the policy to be committed.
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
@@ -103,7 +108,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
// The device state that is set by the device state provider.
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
private Optional<DeviceState> mBaseState = Optional.empty();
|
||||
private DeviceState mBaseState = UNSPECIFIED_DEVICE_STATE;
|
||||
|
||||
// List of processes registered to receive notifications about changes to device state and
|
||||
// request status indexed by process id.
|
||||
@@ -166,7 +171,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
* @see #getOverrideState()
|
||||
*/
|
||||
@NonNull
|
||||
Optional<DeviceState> getBaseState() {
|
||||
DeviceState getBaseState() {
|
||||
synchronized (mLock) {
|
||||
return mBaseState;
|
||||
}
|
||||
@@ -203,33 +208,47 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
/** Returns the list of currently supported device state identifiers. */
|
||||
private int[] getSupportedStateIdentifiers() {
|
||||
synchronized (mLock) {
|
||||
int[] supportedStates = new int[mDeviceStates.size()];
|
||||
for (int i = 0; i < supportedStates.length; i++) {
|
||||
supportedStates[i] = mDeviceStates.valueAt(i).getIdentifier();
|
||||
}
|
||||
return supportedStates;
|
||||
return getSupportedStateIdentifiersLocked();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the list of currently supported device state identifiers. */
|
||||
private int[] getSupportedStateIdentifiersLocked() {
|
||||
int[] supportedStates = new int[mDeviceStates.size()];
|
||||
for (int i = 0; i < supportedStates.length; i++) {
|
||||
supportedStates[i] = mDeviceStates.valueAt(i).getIdentifier();
|
||||
}
|
||||
return supportedStates;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private DeviceStateInfo getDeviceStateInfoLocked() {
|
||||
final int[] supportedStates = getSupportedStateIdentifiersLocked();
|
||||
final int baseState = mBaseState.getIdentifier();
|
||||
final int currentState = mCommittedState.getIdentifier();
|
||||
|
||||
return new DeviceStateInfo(supportedStates, baseState, currentState);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
IDeviceStateManager getBinderService() {
|
||||
return mBinderService;
|
||||
}
|
||||
|
||||
private void updateSupportedStates(DeviceState[] supportedDeviceStates) {
|
||||
boolean updatedPendingState;
|
||||
synchronized (mLock) {
|
||||
final int[] oldStateIdentifiers = getSupportedStateIdentifiersLocked();
|
||||
|
||||
mDeviceStates.clear();
|
||||
for (int i = 0; i < supportedDeviceStates.length; i++) {
|
||||
DeviceState state = supportedDeviceStates[i];
|
||||
mDeviceStates.put(state.getIdentifier(), state);
|
||||
}
|
||||
|
||||
if (mBaseState.isPresent()
|
||||
&& !isSupportedStateLocked(mBaseState.get().getIdentifier())) {
|
||||
// The current base state is no longer valid. We'll clear it here, though
|
||||
// we won't actually update the current state until a callback comes from the
|
||||
// provider with the most recent state.
|
||||
mBaseState = Optional.empty();
|
||||
final int[] newStateIdentifiers = getSupportedStateIdentifiersLocked();
|
||||
if (Arrays.equals(oldStateIdentifiers, newStateIdentifiers)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int requestSize = mRequestRecords.size();
|
||||
@@ -240,7 +259,14 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
updatePendingStateLocked();
|
||||
updatedPendingState = updatePendingStateLocked();
|
||||
}
|
||||
|
||||
if (!updatedPendingState) {
|
||||
// If the change in the supported states didn't result in a change of the pending state
|
||||
// commitPendingState() will never be called and the callbacks will never be notified
|
||||
// of the change.
|
||||
notifyDeviceStateInfoChanged();
|
||||
}
|
||||
|
||||
notifyRequestsOfStatusChangeIfNeeded();
|
||||
@@ -265,23 +291,25 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to set the base state. The request may not be honored under certain conditions, for
|
||||
* example if the provided state is not supported.
|
||||
* Sets the base state.
|
||||
*
|
||||
* @throws IllegalArgumentException if the {@code identifier} is not a supported state.
|
||||
*
|
||||
* @see #isSupportedStateLocked(int)
|
||||
*/
|
||||
private void setBaseState(int identifier) {
|
||||
boolean updatedPendingState;
|
||||
synchronized (mLock) {
|
||||
if (mBaseState.isPresent() && mBaseState.get().getIdentifier() == identifier) {
|
||||
// Base state hasn't changed. Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
final Optional<DeviceState> baseState = getStateLocked(identifier);
|
||||
if (!baseState.isPresent()) {
|
||||
final Optional<DeviceState> baseStateOptional = getStateLocked(identifier);
|
||||
if (!baseStateOptional.isPresent()) {
|
||||
throw new IllegalArgumentException("Base state is not supported");
|
||||
}
|
||||
|
||||
final DeviceState baseState = baseStateOptional.get();
|
||||
if (mBaseState.equals(baseState)) {
|
||||
// Base state hasn't changed. Nothing to do.
|
||||
return;
|
||||
}
|
||||
mBaseState = baseState;
|
||||
|
||||
final int requestSize = mRequestRecords.size();
|
||||
@@ -292,7 +320,14 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
updatePendingStateLocked();
|
||||
updatedPendingState = updatePendingStateLocked();
|
||||
}
|
||||
|
||||
if (!updatedPendingState) {
|
||||
// If the change in base state didn't result in a change of the pending state
|
||||
// commitPendingState() will never be called and the callbacks will never be notified
|
||||
// of the change.
|
||||
notifyDeviceStateInfoChanged();
|
||||
}
|
||||
|
||||
notifyRequestsOfStatusChangeIfNeeded();
|
||||
@@ -303,32 +338,39 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
* Tries to update the current pending state with the current requested state. Must call
|
||||
* {@link #notifyPolicyIfNeeded()} to actually notify the policy that the state is being
|
||||
* changed.
|
||||
*
|
||||
* @return {@code true} if the pending state has changed as a result of this call, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
private void updatePendingStateLocked() {
|
||||
private boolean updatePendingStateLocked() {
|
||||
if (mPendingState.isPresent()) {
|
||||
// Have pending state, can not configure a new state until the state is committed.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
final DeviceState stateToConfigure;
|
||||
if (!mRequestRecords.isEmpty()) {
|
||||
stateToConfigure = mRequestRecords.get(mRequestRecords.size() - 1).mRequestedState;
|
||||
} else if (isSupportedStateLocked(mBaseState.getIdentifier())) {
|
||||
// Base state could have recently become unsupported after a change in supported states.
|
||||
stateToConfigure = mBaseState;
|
||||
} else {
|
||||
stateToConfigure = mBaseState.orElse(null);
|
||||
stateToConfigure = null;
|
||||
}
|
||||
|
||||
if (stateToConfigure == null) {
|
||||
// No currently requested state.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stateToConfigure == mCommittedState) {
|
||||
if (stateToConfigure.equals(mCommittedState)) {
|
||||
// The state requesting to be committed already matches the current committed state.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mPendingState = Optional.of(stateToConfigure);
|
||||
mIsPolicyWaitingForState = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,13 +416,11 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
*/
|
||||
private void commitPendingState() {
|
||||
// Update the current state.
|
||||
int newState;
|
||||
synchronized (mLock) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Committing state: " + mPendingState);
|
||||
}
|
||||
mCommittedState = mPendingState.get();
|
||||
newState = mCommittedState.getIdentifier();
|
||||
|
||||
if (!mRequestRecords.isEmpty()) {
|
||||
final OverrideRequestRecord topRequest =
|
||||
@@ -393,7 +433,7 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
// Notify callbacks of a change.
|
||||
notifyDeviceStateChanged(newState);
|
||||
notifyDeviceStateInfoChanged();
|
||||
|
||||
// Notify the top request that it's active.
|
||||
notifyRequestsOfStatusChangeIfNeeded();
|
||||
@@ -402,14 +442,15 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
notifyPolicyIfNeeded();
|
||||
}
|
||||
|
||||
private void notifyDeviceStateChanged(int deviceState) {
|
||||
private void notifyDeviceStateInfoChanged() {
|
||||
if (Thread.holdsLock(mLock)) {
|
||||
throw new IllegalStateException(
|
||||
"Attempting to notify callbacks with service lock held.");
|
||||
}
|
||||
|
||||
// Grab the lock and copy the process records.
|
||||
// Grab the lock and copy the process records and the current info.
|
||||
ArrayList<ProcessRecord> registeredProcesses;
|
||||
DeviceStateInfo info;
|
||||
synchronized (mLock) {
|
||||
if (mProcessRecords.size() == 0) {
|
||||
return;
|
||||
@@ -419,11 +460,13 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
for (int i = 0; i < mProcessRecords.size(); i++) {
|
||||
registeredProcesses.add(mProcessRecords.valueAt(i));
|
||||
}
|
||||
|
||||
info = getDeviceStateInfoLocked();
|
||||
}
|
||||
|
||||
// After releasing the lock, send the notifications out.
|
||||
for (int i = 0; i < registeredProcesses.size(); i++) {
|
||||
registeredProcesses.get(i).notifyDeviceStateAsync(deviceState);
|
||||
registeredProcesses.get(i).notifyDeviceStateInfoAsync(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,28 +497,20 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private void registerProcess(int pid, IDeviceStateManagerCallback callback) {
|
||||
int currentState;
|
||||
ProcessRecord record;
|
||||
// Grab the lock to register the callback and get the current state.
|
||||
synchronized (mLock) {
|
||||
if (mProcessRecords.contains(pid)) {
|
||||
throw new SecurityException("The calling process has already registered an"
|
||||
+ " IDeviceStateManagerCallback.");
|
||||
}
|
||||
|
||||
record = new ProcessRecord(callback, pid);
|
||||
ProcessRecord record = new ProcessRecord(callback, pid);
|
||||
try {
|
||||
callback.asBinder().linkToDeath(record, 0);
|
||||
} catch (RemoteException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
mProcessRecords.put(pid, record);
|
||||
currentState = mCommittedState.getIdentifier();
|
||||
}
|
||||
|
||||
// Notify the callback of the state at registration.
|
||||
record.notifyDeviceStateAsync(currentState);
|
||||
}
|
||||
|
||||
private void handleProcessDied(ProcessRecord processRecord) {
|
||||
@@ -626,9 +661,9 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
handleProcessDied(this);
|
||||
}
|
||||
|
||||
public void notifyDeviceStateAsync(int devicestate) {
|
||||
public void notifyDeviceStateInfoAsync(@NonNull DeviceStateInfo info) {
|
||||
try {
|
||||
mCallback.onDeviceStateChanged(devicestate);
|
||||
mCallback.onDeviceStateInfoChanged(info);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.w(TAG, "Failed to notify process " + mPid + " that device state changed.",
|
||||
ex);
|
||||
@@ -751,6 +786,13 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
|
||||
/** Implementation of {@link IDeviceStateManager} published as a binder service. */
|
||||
private final class BinderService extends IDeviceStateManager.Stub {
|
||||
@Override // Binder call
|
||||
public DeviceStateInfo getDeviceStateInfo() {
|
||||
synchronized (mLock) {
|
||||
return getDeviceStateInfoLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void registerCallback(IDeviceStateManagerCallback callback) {
|
||||
if (callback == null) {
|
||||
@@ -766,16 +808,6 @@ public final class DeviceStateManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int[] getSupportedDeviceStates() {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return getSupportedStateIdentifiers();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void requestState(IBinder token, int state, int flags) {
|
||||
getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
|
||||
|
||||
@@ -64,13 +64,13 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
|
||||
|
||||
private void printState(PrintWriter pw) {
|
||||
DeviceState committedState = mService.getCommittedState();
|
||||
Optional<DeviceState> baseState = mService.getBaseState();
|
||||
DeviceState baseState = mService.getBaseState();
|
||||
Optional<DeviceState> overrideState = mService.getOverrideState();
|
||||
|
||||
pw.println("Committed state: " + committedState);
|
||||
if (overrideState.isPresent()) {
|
||||
pw.println("----------------------");
|
||||
pw.println("Base state: " + baseState.orElse(null));
|
||||
pw.println("Base state: " + baseState);
|
||||
pw.println("Override state: " + overrideState.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,7 +532,7 @@ public final class DisplayManagerService extends SystemService {
|
||||
|
||||
DeviceStateManager deviceStateManager =
|
||||
mContext.getSystemService(DeviceStateManager.class);
|
||||
deviceStateManager.addDeviceStateListener(new HandlerExecutor(mHandler),
|
||||
deviceStateManager.registerCallback(new HandlerExecutor(mHandler),
|
||||
new DeviceStateListener());
|
||||
|
||||
scheduleTraversalLocked(false);
|
||||
@@ -2974,9 +2974,9 @@ public final class DisplayManagerService extends SystemService {
|
||||
/**
|
||||
* Listens to changes in device state and reports the state to LogicalDisplayMapper.
|
||||
*/
|
||||
class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
|
||||
class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
|
||||
@Override
|
||||
public void onDeviceStateChanged(int deviceState) {
|
||||
public void onStateChanged(int deviceState) {
|
||||
synchronized (mSyncRoot) {
|
||||
mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class DisplayFoldController {
|
||||
mHandler = handler;
|
||||
|
||||
DeviceStateManager deviceStateManager = context.getSystemService(DeviceStateManager.class);
|
||||
deviceStateManager.addDeviceStateListener(new HandlerExecutor(handler),
|
||||
deviceStateManager.registerCallback(new HandlerExecutor(handler),
|
||||
new DeviceStateListener(context));
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ class DisplayFoldController {
|
||||
* matches the value in the {@link com.android.internal.R.integer.config_foldedDeviceState}
|
||||
* resource.
|
||||
*/
|
||||
private class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
|
||||
private class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
|
||||
private final int[] mFoldedDeviceStates;
|
||||
|
||||
DeviceStateListener(Context context) {
|
||||
@@ -217,7 +217,7 @@ class DisplayFoldController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceStateChanged(int deviceState) {
|
||||
public void onStateChanged(int deviceState) {
|
||||
boolean folded = false;
|
||||
for (int i = 0; i < mFoldedDeviceStates.length; i++) {
|
||||
if (deviceState == mFoldedDeviceStates[i]) {
|
||||
|
||||
@@ -21,8 +21,10 @@ import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STA
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.hardware.devicestate.DeviceStateInfo;
|
||||
import android.hardware.devicestate.DeviceStateRequest;
|
||||
import android.hardware.devicestate.IDeviceStateManagerCallback;
|
||||
import android.os.Binder;
|
||||
@@ -33,10 +35,13 @@ import android.platform.test.annotations.Presubmit;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -70,14 +75,14 @@ public final class DeviceStateManagerServiceTest {
|
||||
public void baseStateChanged() {
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
@@ -89,21 +94,21 @@ public final class DeviceStateManagerServiceTest {
|
||||
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mPolicy.resumeConfigure();
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
@@ -116,7 +121,7 @@ public final class DeviceStateManagerServiceTest {
|
||||
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
@@ -129,16 +134,19 @@ public final class DeviceStateManagerServiceTest {
|
||||
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportedStatesChanged() {
|
||||
public void supportedStatesChanged() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
|
||||
mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE });
|
||||
|
||||
@@ -146,27 +154,44 @@ public final class DeviceStateManagerServiceTest {
|
||||
// supported.
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
|
||||
assertArrayEquals(callback.getLastNotifiedInfo().supportedStates,
|
||||
new int[] { DEFAULT_DEVICE_STATE.getIdentifier() });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportedStatesChanged_unsupportedBaseState() {
|
||||
public void supportedStatesChanged_statesRemainSame() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
|
||||
mProvider.notifySupportedDeviceStates(new DeviceState[]{ OTHER_DEVICE_STATE });
|
||||
mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE,
|
||||
OTHER_DEVICE_STATE });
|
||||
|
||||
// The current requested state is cleared because it is no longer supported.
|
||||
// The current committed and requests states do not change because the current state remains
|
||||
// supported.
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
|
||||
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
|
||||
// The callback wasn't notified about a change in supported states as the states have not
|
||||
// changed.
|
||||
assertNull(callback.getLastNotifiedInfo());
|
||||
}
|
||||
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getPendingState(), Optional.empty());
|
||||
assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
|
||||
@Test
|
||||
public void getDeviceStateInfo() throws RemoteException {
|
||||
DeviceStateInfo info = mService.getBinderService().getDeviceStateInfo();
|
||||
assertNotNull(info);
|
||||
assertArrayEquals(info.supportedStates,
|
||||
new int[] { DEFAULT_DEVICE_STATE.getIdentifier(),
|
||||
OTHER_DEVICE_STATE.getIdentifier() });
|
||||
assertEquals(info.baseState, DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(info.currentState, DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -175,41 +200,33 @@ public final class DeviceStateManagerServiceTest {
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
|
||||
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertNotNull(callback.getLastNotifiedValue());
|
||||
assertEquals(callback.getLastNotifiedValue().intValue(),
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mProvider.setState(DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedValue().intValue(),
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mPolicy.blockConfigure();
|
||||
mProvider.setState(OTHER_DEVICE_STATE.getIdentifier());
|
||||
// The callback should not have been notified of the state change as the policy is still
|
||||
// pending callback.
|
||||
assertEquals(callback.getLastNotifiedValue().intValue(),
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mPolicy.resumeConfigure();
|
||||
// Now that the policy is finished processing the callback should be notified of the state
|
||||
// change.
|
||||
assertEquals(callback.getLastNotifiedValue().intValue(),
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void registerCallback_emitsInitialValue() throws RemoteException {
|
||||
TestDeviceStateManagerCallback callback = new TestDeviceStateManagerCallback();
|
||||
mService.getBinderService().registerCallback(callback);
|
||||
assertNotNull(callback.getLastNotifiedValue());
|
||||
assertEquals(callback.getLastNotifiedValue().intValue(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSupportedDeviceStates() throws RemoteException {
|
||||
final int[] expectedStates = new int[] { 0, 1 };
|
||||
assertEquals(mService.getBinderService().getSupportedDeviceStates(), expectedStates);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,11 +245,16 @@ public final class DeviceStateManagerServiceTest {
|
||||
TestDeviceStateManagerCallback.STATUS_ACTIVE);
|
||||
// Committed state changes as there is a requested override.
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
assertNotNull(callback.getLastNotifiedInfo());
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
|
||||
mService.getBinderService().cancelRequest(token);
|
||||
|
||||
@@ -240,10 +262,15 @@ public final class DeviceStateManagerServiceTest {
|
||||
TestDeviceStateManagerCallback.STATUS_CANCELED);
|
||||
// Committed state is set back to the requested state once the override is cleared.
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
|
||||
assertEquals(callback.getLastNotifiedInfo().baseState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
assertEquals(callback.getLastNotifiedInfo().currentState,
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -263,7 +290,7 @@ public final class DeviceStateManagerServiceTest {
|
||||
|
||||
// Committed state changes as there is a requested override.
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
@@ -275,7 +302,7 @@ public final class DeviceStateManagerServiceTest {
|
||||
TestDeviceStateManagerCallback.STATUS_CANCELED);
|
||||
// Committed state is set back to the requested state once the override is cleared.
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), OTHER_DEVICE_STATE);
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
@@ -297,7 +324,7 @@ public final class DeviceStateManagerServiceTest {
|
||||
TestDeviceStateManagerCallback.STATUS_ACTIVE);
|
||||
// Committed state changes as there is a requested override.
|
||||
assertEquals(mService.getCommittedState(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
OTHER_DEVICE_STATE.getIdentifier());
|
||||
@@ -310,7 +337,7 @@ public final class DeviceStateManagerServiceTest {
|
||||
// Committed state is set back to the requested state as the override state is no longer
|
||||
// supported.
|
||||
assertEquals(mService.getCommittedState(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState().get(), DEFAULT_DEVICE_STATE);
|
||||
assertEquals(mService.getBaseState(), DEFAULT_DEVICE_STATE);
|
||||
assertFalse(mService.getOverrideState().isPresent());
|
||||
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
|
||||
DEFAULT_DEVICE_STATE.getIdentifier());
|
||||
@@ -348,6 +375,10 @@ public final class DeviceStateManagerServiceTest {
|
||||
});
|
||||
}
|
||||
|
||||
private static void assertArrayEquals(int[] expected, int[] actual) {
|
||||
Assert.assertTrue(Arrays.equals(expected, actual));
|
||||
}
|
||||
|
||||
private static final class TestDeviceStatePolicy implements DeviceStatePolicy {
|
||||
private final DeviceStateProvider mProvider;
|
||||
private int mLastDeviceStateRequestedToConfigure = INVALID_DEVICE_STATE;
|
||||
@@ -429,12 +460,14 @@ public final class DeviceStateManagerServiceTest {
|
||||
public static final int STATUS_SUSPENDED = 2;
|
||||
public static final int STATUS_CANCELED = 3;
|
||||
|
||||
private Integer mLastNotifiedValue;
|
||||
@Nullable
|
||||
private DeviceStateInfo mLastNotifiedInfo;
|
||||
private boolean mNotifiedOfChangeInSupportedStates;
|
||||
private final HashMap<IBinder, Integer> mLastNotifiedStatus = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onDeviceStateChanged(int deviceState) {
|
||||
mLastNotifiedValue = deviceState;
|
||||
public void onDeviceStateInfoChanged(DeviceStateInfo info) {
|
||||
mLastNotifiedInfo = info;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -453,8 +486,8 @@ public final class DeviceStateManagerServiceTest {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Integer getLastNotifiedValue() {
|
||||
return mLastNotifiedValue;
|
||||
DeviceStateInfo getLastNotifiedInfo() {
|
||||
return mLastNotifiedInfo;
|
||||
}
|
||||
|
||||
int getLastNotifiedStatus(IBinder requestToken) {
|
||||
|
||||
Reference in New Issue
Block a user