blob: 72c0767995bbd70a9d65744af41cd5e437196aad [file] [log] [blame]
Dan Murphyc9f4eaf2009-08-12 15:15:43 -05001/*
2 * Copyright (C) 2008 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
Jeff Brown4f8ecd82012-06-18 18:29:13 -070019import com.android.server.power.PowerManagerService;
20
Jaikumar Ganesh3fbf7b62009-12-02 17:28:38 -080021import android.bluetooth.BluetoothAdapter;
22import android.bluetooth.BluetoothDevice;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050023import android.content.ContentResolver;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050024import android.content.Context;
25import android.content.Intent;
Daniel Sandlerec2c88d2010-02-20 01:04:57 -050026import android.media.AudioManager;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050027import android.media.Ringtone;
28import android.media.RingtoneManager;
29import android.net.Uri;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050030import android.os.Handler;
31import android.os.Message;
Ken Schultzf02c0742009-09-10 18:37:37 -050032import android.os.SystemClock;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050033import android.os.UEventObserver;
Dianne Hackborn49493342009-10-02 10:44:41 -070034import android.provider.Settings;
Jaikumar Ganesh3fbf7b62009-12-02 17:28:38 -080035import android.server.BluetoothService;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050036import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080037import android.util.Slog;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050038
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050039import java.io.FileNotFoundException;
Jaikumar Ganesh3fbf7b62009-12-02 17:28:38 -080040import java.io.FileReader;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050041
42/**
43 * <p>DockObserver monitors for a docking station.
44 */
45class DockObserver extends UEventObserver {
46 private static final String TAG = DockObserver.class.getSimpleName();
47 private static final boolean LOG = false;
48
49 private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
50 private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
51
Bernd Holzheybfca3a02010-02-10 17:39:51 +010052 private static final int MSG_DOCK_STATE = 0;
Bernd Holzheybfca3a02010-02-10 17:39:51 +010053
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070054 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050055 private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
56
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070057 private boolean mSystemReady;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050058
59 private final Context mContext;
60
Ken Schultzf02c0742009-09-10 18:37:37 -050061 private PowerManagerService mPowerManager;
Bernd Holzheybfca3a02010-02-10 17:39:51 +010062
Ken Schultzf02c0742009-09-10 18:37:37 -050063 public DockObserver(Context context, PowerManagerService pm) {
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050064 mContext = context;
Ken Schultzf02c0742009-09-10 18:37:37 -050065 mPowerManager = pm;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050066 init(); // set initial status
Tobias Haamel27b28b32010-02-09 23:09:17 +010067
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070068 startObserving(DOCK_UEVENT_MATCH);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050069 }
70
71 @Override
72 public void onUEvent(UEventObserver.UEvent event) {
73 if (Log.isLoggable(TAG, Log.VERBOSE)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080074 Slog.v(TAG, "Dock UEVENT: " + event.toString());
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050075 }
76
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070077 synchronized (this) {
78 try {
79 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
80 if (newState != mDockState) {
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050081 mPreviousDockState = mDockState;
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070082 mDockState = newState;
83 if (mSystemReady) {
Mike Lockwood1d069922009-11-11 18:09:25 -050084 // Don't force screen on when undocking from the desk dock.
85 // The change in power state will do this anyway.
86 // FIXME - we should be configurable.
Jeff Brown1a693182011-11-08 14:44:16 -080087 if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK
88 && mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
89 && mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
Daniel Sandler0e9d2af2010-01-25 11:33:03 -050090 mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
Mike Lockwood1d069922009-11-11 18:09:25 -050091 mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
92 false, true);
93 }
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070094 update();
95 }
96 }
97 } catch (NumberFormatException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080098 Slog.e(TAG, "Could not parse switch state from event " + event);
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070099 }
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500100 }
101 }
102
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700103 private final void init() {
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500104 char[] buffer = new char[1024];
105
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500106 try {
107 FileReader file = new FileReader(DOCK_STATE_PATH);
108 int len = file.read(buffer, 0, 1024);
Brian Carlstromfd9ddd12010-11-04 11:24:58 -0700109 file.close();
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500110 mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500111 } catch (FileNotFoundException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800112 Slog.w(TAG, "This kernel does not have dock station support");
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500113 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800114 Slog.e(TAG, "" , e);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500115 }
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500116 }
117
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700118 void systemReady() {
119 synchronized (this) {
120 // don't bother broadcasting undocked here
121 if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
122 update();
123 }
124 mSystemReady = true;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500125 }
126 }
127
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700128 private final void update() {
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100129 mHandler.sendEmptyMessage(MSG_DOCK_STATE);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500130 }
131
132 private final Handler mHandler = new Handler() {
133 @Override
134 public void handleMessage(Message msg) {
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100135 switch (msg.what) {
136 case MSG_DOCK_STATE:
137 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800138 Slog.i(TAG, "Dock state changed: " + mDockState);
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500139
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100140 final ContentResolver cr = mContext.getContentResolver();
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500141
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100142 if (Settings.Secure.getInt(cr,
143 Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800144 Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100145 return;
Daniel Sandler0e9d2af2010-01-25 11:33:03 -0500146 }
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100147 // Pack up the values and broadcast them to everyone
148 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
149 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn7299c412010-03-04 18:41:49 -0800150 intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100151
152 // Check if this is Bluetooth Dock
153 String address = BluetoothService.readDockBluetoothAddress();
154 if (address != null)
155 intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
156 BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
157
158 // User feedback to confirm dock connection. Particularly
159 // useful for flaky contact pins...
160 if (Settings.System.getInt(cr,
161 Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
162 {
163 String whichSound = null;
164 if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
Praveen Bharathi21e941b2010-10-06 15:23:14 -0500165 if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
166 (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
167 (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100168 whichSound = Settings.System.DESK_UNDOCK_SOUND;
169 } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
170 whichSound = Settings.System.CAR_UNDOCK_SOUND;
171 }
172 } else {
Praveen Bharathi21e941b2010-10-06 15:23:14 -0500173 if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) ||
174 (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
175 (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) {
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100176 whichSound = Settings.System.DESK_DOCK_SOUND;
177 } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
178 whichSound = Settings.System.CAR_DOCK_SOUND;
179 }
180 }
181
182 if (whichSound != null) {
183 final String soundPath = Settings.System.getString(cr, whichSound);
184 if (soundPath != null) {
185 final Uri soundUri = Uri.parse("file://" + soundPath);
186 if (soundUri != null) {
187 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
Daniel Sandlerec2c88d2010-02-20 01:04:57 -0500188 if (sfx != null) {
189 sfx.setStreamType(AudioManager.STREAM_SYSTEM);
190 sfx.play();
191 }
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100192 }
193 }
194 }
195 }
196
Dianne Hackborn7299c412010-03-04 18:41:49 -0800197 mContext.sendStickyBroadcast(intent);
Bernd Holzheybfca3a02010-02-10 17:39:51 +0100198 }
199 break;
200 }
201 }
Tobias Haamel27b28b32010-02-09 23:09:17 +0100202 };
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500203}