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 package com.android.car;
17 
18 import android.os.Handler;
19 import android.os.Message;
20 import android.util.Log;
21 
22 import com.android.internal.annotations.GuardedBy;
23 import com.android.internal.annotations.VisibleForTesting;
24 
25 import java.lang.ref.WeakReference;
26 
27 /**
28 * An wrapper class that can be backed by a real DeviceIdleController or a mocked one.
29 */
30 public abstract class DeviceIdleControllerWrapper {
31     private static final String TAG = "Garage_DeviceIdleWrapper";
32 
33     private static final int MSG_REPORT_ACTIVE = 1;
34 
35     @VisibleForTesting
36     protected WeakReference<DeviceMaintenanceActivityListener> mListener;
37 
38     public interface DeviceMaintenanceActivityListener {
onMaintenanceActivityChanged(boolean active)39         public void onMaintenanceActivityChanged(boolean active);
40     }
41     private final Object mLock = new Object();
42     @GuardedBy("mLock")
43     private boolean mActive;
44 
45     private Handler mHandler = new IdleControllerHandler();
46 
47     private class IdleControllerHandler extends Handler {
48         @Override
handleMessage(Message msg)49         public void handleMessage(Message msg) {
50             switch (msg.what) {
51                 case MSG_REPORT_ACTIVE:
52                     boolean active  = msg.arg1 == 1;
53                     if (mListener.get() != null) {
54                         mListener.get().onMaintenanceActivityChanged(active);
55                     }
56                     break;
57             }
58         }
59     }
60 
startTracking(DeviceMaintenanceActivityListener listener)61     public boolean startTracking(DeviceMaintenanceActivityListener listener) {
62         synchronized (mLock) {
63             mListener = new WeakReference<DeviceMaintenanceActivityListener>(listener);
64             mActive = startLocked();
65             return mActive;
66         }
67     }
68 
startLocked()69     protected abstract boolean startLocked();
70 
stopTracking()71     public abstract void stopTracking();
72 
73     @VisibleForTesting
reportActiveLocked(final boolean active)74     protected void reportActiveLocked(final boolean active) {
75         // post to a handler instead of calling the callback directly to avoid potential deadlock.
76         mHandler.sendMessage(mHandler.obtainMessage(MSG_REPORT_ACTIVE, active ? 1 : 0, 0));
77     }
78 
79     @VisibleForTesting
setMaintenanceActivity(final boolean active)80     protected void setMaintenanceActivity(final boolean active) {
81         synchronized (mLock) {
82             if (mActive == active) {
83                 return;
84             }
85             mActive = active;
86 
87             if (mListener.get() == null) {
88                 // do cleanup if the listener has gone and did not call release.
89                 stopTracking();
90                 return;
91             }
92             reportActiveLocked(active);
93         }
94     }
95 }
96