• 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.systeminterface;
18 
19 import java.time.Duration;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.concurrent.Executors;
24 import java.util.concurrent.ScheduledExecutorService;
25 import java.util.concurrent.TimeUnit;
26 
27 import com.android.car.procfsinspector.ProcessInfo;
28 import com.android.car.procfsinspector.ProcfsInspector;
29 import com.android.internal.car.ICarServiceHelper;
30 
31 import android.content.BroadcastReceiver;
32 import android.content.Context;
33 import android.content.Intent;
34 import android.content.IntentFilter;
35 import android.os.PowerManager;
36 import android.os.SystemClock;
37 import android.util.Log;
38 import android.util.Pair;
39 
40 /**
41  * Interface that abstracts system status (booted, sleeping, ...) operations
42  */
43 public interface SystemStateInterface {
44     static final String TAG = SystemStateInterface.class.getSimpleName();
shutdown()45     void shutdown();
enterDeepSleep(int sleepDurationSec)46     boolean enterDeepSleep(int sleepDurationSec);
scheduleActionForBootCompleted(Runnable action, Duration delay)47     void scheduleActionForBootCompleted(Runnable action, Duration delay);
48 
isWakeupCausedByTimer()49     default boolean isWakeupCausedByTimer() {
50         //TODO bug: 32061842, check wake up reason and do necessary operation information should
51         // come from kernel. it can be either power on or wake up for maintenance
52         // power on will involve GPIO trigger from power controller
53         // its own wakeup will involve timer expiration.
54         return false;
55     }
56 
isSystemSupportingDeepSleep()57     default boolean isSystemSupportingDeepSleep() {
58         //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
59         return false;
60     }
61 
getRunningProcesses()62     default List<ProcessInfo> getRunningProcesses() {
63         return ProcfsInspector.readProcessTable();
64     }
65 
setCarServiceHelper(ICarServiceHelper helper)66     default void setCarServiceHelper(ICarServiceHelper helper) {
67         // Do nothing
68     }
69 
70     class DefaultImpl implements SystemStateInterface {
71         private final static Duration MIN_BOOT_COMPLETE_ACTION_DELAY = Duration.ofSeconds(10);
72         private final static int SUSPEND_TRY_TIMEOUT_MS = 1000;
73 
74         private ICarServiceHelper mICarServiceHelper;
75         private final Context mContext;
76         private final PowerManager mPowerManager;
77         private List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
78         private ScheduledExecutorService mExecutorService;
79         private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
80             @Override
81             public void onReceive(Context context, Intent intent) {
82                 if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
83                     for (Pair<Runnable, Duration> action : mActionsList) {
84                         mExecutorService.schedule(action.first,
85                             action.second.toMillis(), TimeUnit.MILLISECONDS);
86                     }
87                 }
88             }
89         };
90 
DefaultImpl(Context context)91         DefaultImpl(Context context) {
92             mContext = context;
93             mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
94         }
95 
96         @Override
shutdown()97         public void shutdown() {
98             mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
99         }
100 
101         @Override
enterDeepSleep(int sleepDurationSec)102         public boolean enterDeepSleep(int sleepDurationSec) {
103             boolean deviceEnteredSleep;
104             //TODO set wake up time via VHAL, bug: 32061842
105             try {
106                 int retVal;
107                 retVal = mICarServiceHelper.forceSuspend(SUSPEND_TRY_TIMEOUT_MS);
108                 deviceEnteredSleep = retVal == 0;
109 
110             } catch (Exception e) {
111                 Log.e(TAG, "Unable to enter deep sleep", e);
112                 deviceEnteredSleep = false;
113             }
114             return deviceEnteredSleep;
115         }
116 
117         @Override
scheduleActionForBootCompleted(Runnable action, Duration delay)118         public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
119             if (MIN_BOOT_COMPLETE_ACTION_DELAY.compareTo(delay) < 0) {
120                 // TODO: consider adding some degree of randomness here
121                 delay = MIN_BOOT_COMPLETE_ACTION_DELAY;
122             }
123             if (mActionsList.isEmpty()) {
124                 final int corePoolSize = 1;
125                 mExecutorService = Executors.newScheduledThreadPool(corePoolSize);
126                 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
127                 mContext.registerReceiver(mBroadcastReceiver, intentFilter);
128             }
129             mActionsList.add(Pair.create(action, delay));
130         }
131 
132         @Override
setCarServiceHelper(ICarServiceHelper helper)133         public void setCarServiceHelper(ICarServiceHelper helper) {
134             mICarServiceHelper = helper;
135         }
136     }
137 }
138