blob: 6311d80209af5c7154680bb30516f55f82689f2a [file] [log] [blame]
Pavel Maltsev0d07c762016-11-03 16:40:15 -07001/*
2 * Copyright (C) 2016 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
17package com.android.car;
18
19import android.content.Context;
20import android.hardware.display.DisplayManager;
21import android.os.PowerManager;
22import android.os.PowerManager.WakeLock;
23import android.os.SystemClock;
24import android.util.Log;
25import android.view.Display;
26
27/**
28 * Interface to abstract all system interaction.
29 */
30public abstract class SystemInterface {
31 public abstract void setDisplayState(boolean on);
32 public abstract void releaseAllWakeLocks();
33 public abstract void shutdown();
34 public abstract void enterDeepSleep(int wakeupTimeSec);
35 public abstract void switchToPartialWakeLock();
36 public abstract void switchToFullWakeLock();
37 public abstract void startDisplayStateMonitoring(CarPowerManagementService service);
38 public abstract void stopDisplayStateMonitoring();
39 public abstract boolean isSystemSupportingDeepSleep();
40 public abstract boolean isWakeupCausedByTimer();
41
42
43 public static SystemInterface getDefault(Context context) {
44 return new SystemInterfaceImpl(context);
45 }
46
47 private static class SystemInterfaceImpl extends SystemInterface {
48 private final PowerManager mPowerManager;
49 private final DisplayManager mDisplayManager;
50 private final WakeLock mFullWakeLock;
51 private final WakeLock mPartialWakeLock;
52 private final DisplayStateListener mDisplayListener;
53 private CarPowerManagementService mService;
54 private boolean mDisplayStateSet;
55
56 private SystemInterfaceImpl(Context context) {
57 mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
58 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
59 mFullWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
60 CarLog.TAG_POWER);
61 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
62 CarLog.TAG_POWER);
63 mDisplayListener = new DisplayStateListener();
64 }
65
66 @Override
67 public void startDisplayStateMonitoring(CarPowerManagementService service) {
68 synchronized (this) {
69 mService = service;
70 mDisplayStateSet = isMainDisplayOn();
71 }
72 mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
73 }
74
75 @Override
76 public void stopDisplayStateMonitoring() {
77 mDisplayManager.unregisterDisplayListener(mDisplayListener);
78 }
79
80 @Override
81 public void setDisplayState(boolean on) {
82 synchronized (this) {
83 mDisplayStateSet = on;
84 }
85 if (on) {
86 switchToFullWakeLock();
87 Log.i(CarLog.TAG_POWER, "on display");
88 mPowerManager.wakeUp(SystemClock.uptimeMillis());
89 } else {
90 switchToPartialWakeLock();
91 Log.i(CarLog.TAG_POWER, "off display");
92 mPowerManager.goToSleep(SystemClock.uptimeMillis());
93 }
94 }
95
96 private boolean isMainDisplayOn() {
97 Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
98 return disp.getState() == Display.STATE_ON;
99 }
100
101 @Override
102 public void shutdown() {
103 mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
104 }
105
106 @Override
107 public void enterDeepSleep(int wakeupTimeSec) {
108 //TODO set wake up time, bug: 32061842
109 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
110 PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
111 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
112 }
113
114 @Override
115 public boolean isSystemSupportingDeepSleep() {
116 //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
117 return false;
118 }
119
120 @Override
121 public void switchToPartialWakeLock() {
122 if (!mPartialWakeLock.isHeld()) {
123 mPartialWakeLock.acquire();
124 }
125 if (mFullWakeLock.isHeld()) {
126 mFullWakeLock.release();
127 }
128 }
129
130 @Override
131 public void switchToFullWakeLock() {
132 if (!mFullWakeLock.isHeld()) {
133 mFullWakeLock.acquire();
134 }
135 if (mPartialWakeLock.isHeld()) {
136 mPartialWakeLock.release();
137 }
138 }
139
140 @Override
141 public void releaseAllWakeLocks() {
142 if (mPartialWakeLock.isHeld()) {
143 mPartialWakeLock.release();
144 }
145 if (mFullWakeLock.isHeld()) {
146 mFullWakeLock.release();
147 }
148 }
149
150 @Override
151 public boolean isWakeupCausedByTimer() {
152 //TODO bug: 32061842, check wake up reason and do necessary operation information should
153 // come from kernel. it can be either power on or wake up for maintenance
154 // power on will involve GPIO trigger from power controller
155 // its own wakeup will involve timer expiration.
156 return false;
157 }
158
159 private void handleMainDisplayChanged() {
160 boolean isOn = isMainDisplayOn();
161 CarPowerManagementService service;
162 synchronized (this) {
163 if (mDisplayStateSet == isOn) { // same as what is set
164 return;
165 }
166 service = mService;
167 }
168 service.handleMainDisplayChanged(isOn);
169 }
170
171 private class DisplayStateListener implements DisplayManager.DisplayListener {
172
173 @Override
174 public void onDisplayAdded(int displayId) {
175 //ignore
176 }
177
178 @Override
179 public void onDisplayChanged(int displayId) {
180 if (displayId == Display.DEFAULT_DISPLAY) {
181 handleMainDisplayChanged();
182 }
183 }
184
185 @Override
186 public void onDisplayRemoved(int displayId) {
187 //ignore
188 }
189 }
190 }
191}