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 */
16package com.android.car;
17
18import android.os.Handler;
19import android.os.Message;
20import android.util.Log;
21
22import com.android.internal.annotations.GuardedBy;
23import com.android.internal.annotations.VisibleForTesting;
24
25import java.lang.ref.WeakReference;
26
27/**
28* An wrapper class that can be backed by a real DeviceIdleController or a mocked one.
29*/
30public 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 {
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
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
61    public boolean startTracking(DeviceMaintenanceActivityListener listener) {
62        synchronized (mLock) {
63            mListener = new WeakReference<DeviceMaintenanceActivityListener>(listener);
64            mActive = startLocked();
65            return mActive;
66        }
67    }
68
69    protected abstract boolean startLocked();
70
71    public abstract void stopTracking();
72
73    @VisibleForTesting
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
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