blob: aee28fb6b2958cb3707a47df0a1fd1878cb75b55 [file] [log] [blame]
Bryce Leebc58f592015-09-25 16:43:01 -07001/*
2 * Copyright (C) 2015 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
17package com.android.server;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageManager;
22import android.os.Binder;
23import android.os.Handler;
24import android.os.Message;
25import android.os.PowerManager;
26import android.os.UEventObserver;
27import android.os.UserHandle;
28
29import java.io.FileDescriptor;
30import java.io.PrintWriter;
31
32/**
33 * ThermalObserver for monitoring temperature changes.
34 */
35public class ThermalObserver extends SystemService {
36 private static final String TAG = "ThermalObserver";
37
38 private static final String CALLSTATE_UEVENT_MATCH =
39 "DEVPATH=/devices/virtual/switch/thermalstate";
40
41 private static final int MSG_THERMAL_STATE_CHANGED = 0;
42
43 private static final int SWITCH_STATE_NORMAL = 0;
44 private static final int SWITCH_STATE_WARNING = 1;
45 private static final int SWITCH_STATE_EXCEEDED = 2;
46
47 private final PowerManager mPowerManager;
48 private final PowerManager.WakeLock mWakeLock;
49
50 private final Object mLock = new Object();
51 private Integer mLastState;
52
53 private final UEventObserver mThermalWarningObserver = new UEventObserver() {
54 @Override
55 public void onUEvent(UEventObserver.UEvent event) {
56 updateLocked(Integer.parseInt(event.get("SWITCH_STATE")));
57 }
58 };
59
60 private final Handler mHandler = new Handler(true /*async*/) {
61 @Override
62 public void handleMessage(Message msg) {
63 switch (msg.what) {
64 case MSG_THERMAL_STATE_CHANGED:
65 handleThermalStateChange(msg.arg1);
66 mWakeLock.release();
67 break;
68 }
69 }
70 };
71
72 public ThermalObserver(Context context) {
73 super(context);
74 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
75 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
76
77 mThermalWarningObserver.startObserving(CALLSTATE_UEVENT_MATCH);
78 }
79
80 private void updateLocked(int state) {
81 Message message = new Message();
82 message.what = MSG_THERMAL_STATE_CHANGED;
83 message.arg1 = state;
84
85 mWakeLock.acquire();
86 mHandler.sendMessage(message);
87 }
88
89 private void handleThermalStateChange(int state) {
90 synchronized (mLock) {
91 mLastState = state;
92 Intent intent = new Intent(Intent.ACTION_THERMAL_EVENT);
93 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
94
95 final int thermalState;
96
97 switch (state) {
98 case SWITCH_STATE_WARNING:
99 thermalState = Intent.EXTRA_THERMAL_STATE_WARNING;
100 break;
101 case SWITCH_STATE_EXCEEDED:
102 thermalState = Intent.EXTRA_THERMAL_STATE_EXCEEDED;
103 break;
104 case SWITCH_STATE_NORMAL:
105 default:
106 thermalState = Intent.EXTRA_THERMAL_STATE_NORMAL;
107 break;
108 }
109
110 intent.putExtra(Intent.EXTRA_THERMAL_STATE, thermalState);
111
112 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
113 }
114 }
115
116 @Override
117 public void onStart() {
118 publishBinderService(TAG, new BinderService());
119 }
120
121 private final class BinderService extends Binder {
122 @Override
123 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
124 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
125 != PackageManager.PERMISSION_GRANTED) {
126 pw.println("Permission Denial: can't dump thermal observer service from from pid="
127 + Binder.getCallingPid()
128 + ", uid=" + Binder.getCallingUid());
129 return;
130 }
131
132 final long ident = Binder.clearCallingIdentity();
133 try {
134 synchronized (mLock) {
135 if (args == null || args.length == 0 || "-a".equals(args[0])) {
136 pw.println("Current Thermal Observer Service state:");
137 pw.println(" last state change: "
138 + (mLastState != null ? mLastState : "none"));
139 }
140 }
141 } finally {
142 Binder.restoreCallingIdentity(ident);
143 }
144 }
145 }
146}