Home | History | Annotate | Download | only in systeminterface
      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();
     45     void shutdown();
     46     boolean enterDeepSleep(int sleepDurationSec);
     47     void scheduleActionForBootCompleted(Runnable action, Duration delay);
     48 
     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 
     57     default boolean isSystemSupportingDeepSleep() {
     58         //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
     59         return false;
     60     }
     61 
     62     default List<ProcessInfo> getRunningProcesses() {
     63         return ProcfsInspector.readProcessTable();
     64     }
     65 
     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 
     91         DefaultImpl(Context context) {
     92             mContext = context;
     93             mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
     94         }
     95 
     96         @Override
     97         public void shutdown() {
     98             mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
     99         }
    100 
    101         @Override
    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
    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
    133         public void setCarServiceHelper(ICarServiceHelper helper) {
    134             mICarServiceHelper = helper;
    135         }
    136     }
    137 }
    138