1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.window.common;
18 
19 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.content.Context;
24 import android.hardware.devicestate.DeviceStateManager;
25 import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
26 import android.util.Log;
27 import android.util.SparseIntArray;
28 
29 import androidx.window.util.BaseDataProducer;
30 
31 import com.android.internal.R;
32 
33 import java.util.Optional;
34 
35 /**
36  * An implementation of {@link androidx.window.util.DataProducer} that returns the device's posture
37  * by mapping the state returned from {@link DeviceStateManager} to values provided in the resources
38  * config at {@link R.array#config_device_state_postures}.
39  */
40 public final class DeviceStateManagerPostureProducer extends BaseDataProducer<Integer> {
41     private static final String TAG = "ConfigDevicePostureProducer";
42     private static final boolean DEBUG = false;
43 
44     private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
45 
46     private int mCurrentDeviceState = INVALID_DEVICE_STATE;
47 
48     private final DeviceStateCallback mDeviceStateCallback = (state) -> {
49         mCurrentDeviceState = state;
50         notifyDataChanged();
51     };
52 
DeviceStateManagerPostureProducer(@onNull Context context)53     public DeviceStateManagerPostureProducer(@NonNull Context context) {
54         String[] deviceStatePosturePairs = context.getResources()
55                 .getStringArray(R.array.config_device_state_postures);
56         for (String deviceStatePosturePair : deviceStatePosturePairs) {
57             String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
58             if (deviceStatePostureMapping.length != 2) {
59                 if (DEBUG) {
60                     Log.e(TAG, "Malformed device state posture pair: " + deviceStatePosturePair);
61                 }
62                 continue;
63             }
64 
65             int deviceState;
66             int posture;
67             try {
68                 deviceState = Integer.parseInt(deviceStatePostureMapping[0]);
69                 posture = Integer.parseInt(deviceStatePostureMapping[1]);
70             } catch (NumberFormatException e) {
71                 if (DEBUG) {
72                     Log.e(TAG, "Failed to parse device state or posture: " + deviceStatePosturePair,
73                             e);
74                 }
75                 continue;
76             }
77 
78             mDeviceStateToPostureMap.put(deviceState, posture);
79         }
80 
81         if (mDeviceStateToPostureMap.size() > 0) {
82             context.getSystemService(DeviceStateManager.class)
83                     .registerCallback(context.getMainExecutor(), mDeviceStateCallback);
84         }
85     }
86 
87     @Override
88     @Nullable
getData()89     public Optional<Integer> getData() {
90         final int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, -1);
91         return posture != -1 ? Optional.of(posture) : Optional.empty();
92     }
93 }
94