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