• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.car;
18 
19 import android.content.Context;
20 import android.hardware.display.DisplayManager;
21 import android.os.PowerManager;
22 import android.os.PowerManager.WakeLock;
23 import android.os.SystemClock;
24 import android.util.Log;
25 import android.view.Display;
26 
27 /**
28  * Interface to abstract all system interaction.
29  */
30 public abstract class SystemInterface {
setDisplayState(boolean on)31     public abstract void setDisplayState(boolean on);
releaseAllWakeLocks()32     public abstract void releaseAllWakeLocks();
shutdown()33     public abstract void shutdown();
enterDeepSleep(int wakeupTimeSec)34     public abstract void enterDeepSleep(int wakeupTimeSec);
switchToPartialWakeLock()35     public abstract void switchToPartialWakeLock();
switchToFullWakeLock()36     public abstract void switchToFullWakeLock();
startDisplayStateMonitoring(CarPowerManagementService service)37     public abstract void startDisplayStateMonitoring(CarPowerManagementService service);
stopDisplayStateMonitoring()38     public abstract void stopDisplayStateMonitoring();
isSystemSupportingDeepSleep()39     public abstract boolean isSystemSupportingDeepSleep();
isWakeupCausedByTimer()40     public abstract boolean isWakeupCausedByTimer();
41 
42 
getDefault(Context context)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 
SystemInterfaceImpl(Context context)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
startDisplayStateMonitoring(CarPowerManagementService service)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
stopDisplayStateMonitoring()76         public void stopDisplayStateMonitoring() {
77             mDisplayManager.unregisterDisplayListener(mDisplayListener);
78         }
79 
80         @Override
setDisplayState(boolean on)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 
isMainDisplayOn()96         private boolean isMainDisplayOn() {
97             Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
98             return disp.getState() == Display.STATE_ON;
99         }
100 
101         @Override
shutdown()102         public void shutdown() {
103             mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
104         }
105 
106         @Override
enterDeepSleep(int wakeupTimeSec)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
isSystemSupportingDeepSleep()115         public boolean isSystemSupportingDeepSleep() {
116             //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
117             return false;
118         }
119 
120         @Override
switchToPartialWakeLock()121         public void switchToPartialWakeLock() {
122             if (!mPartialWakeLock.isHeld()) {
123                 mPartialWakeLock.acquire();
124             }
125             if (mFullWakeLock.isHeld()) {
126                 mFullWakeLock.release();
127             }
128         }
129 
130         @Override
switchToFullWakeLock()131         public void switchToFullWakeLock() {
132             if (!mFullWakeLock.isHeld()) {
133                 mFullWakeLock.acquire();
134             }
135             if (mPartialWakeLock.isHeld()) {
136                 mPartialWakeLock.release();
137             }
138         }
139 
140         @Override
releaseAllWakeLocks()141         public void releaseAllWakeLocks() {
142             if (mPartialWakeLock.isHeld()) {
143                 mPartialWakeLock.release();
144             }
145             if (mFullWakeLock.isHeld()) {
146                 mFullWakeLock.release();
147             }
148         }
149 
150         @Override
isWakeupCausedByTimer()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 
handleMainDisplayChanged()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
onDisplayAdded(int displayId)174             public void onDisplayAdded(int displayId) {
175                 //ignore
176             }
177 
178             @Override
onDisplayChanged(int displayId)179             public void onDisplayChanged(int displayId) {
180                 if (displayId == Display.DEFAULT_DISPLAY) {
181                     handleMainDisplayChanged();
182                 }
183             }
184 
185             @Override
onDisplayRemoved(int displayId)186             public void onDisplayRemoved(int displayId) {
187                 //ignore
188             }
189         }
190     }
191 }
192