blob: aa9c2438e4266ebc0d4dbf6de7245c9ba891f8d2 [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
Mike LeBeau1f6c7e62009-09-19 18:06:52 -070019import android.app.Activity;
Mike Lockwood733fdf32009-09-28 19:08:53 -040020import android.app.KeyguardManager;
Mike Lockwood9092ab42009-09-16 13:01:32 -040021import android.content.ActivityNotFoundException;
Mike LeBeau1f6c7e62009-09-19 18:06:52 -070022import android.content.BroadcastReceiver;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050023import android.content.Context;
24import android.content.Intent;
25import android.os.Handler;
26import android.os.Message;
Ken Schultzf02c0742009-09-10 18:37:37 -050027import android.os.SystemClock;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050028import android.os.UEventObserver;
29import android.util.Log;
30
Mike Lockwood733fdf32009-09-28 19:08:53 -040031import com.android.internal.widget.LockPatternUtils;
32
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050033import java.io.FileReader;
34import java.io.FileNotFoundException;
35
36/**
37 * <p>DockObserver monitors for a docking station.
38 */
39class DockObserver extends UEventObserver {
40 private static final String TAG = DockObserver.class.getSimpleName();
41 private static final boolean LOG = false;
42
43 private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
44 private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
45
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -070046 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
47 private boolean mSystemReady;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050048
49 private final Context mContext;
50
Ken Schultzf02c0742009-09-10 18:37:37 -050051 private PowerManagerService mPowerManager;
Mike Lockwood733fdf32009-09-28 19:08:53 -040052
53 private KeyguardManager.KeyguardLock mKeyguardLock;
54 private boolean mKeyguardDisabled;
55 private LockPatternUtils mLockPatternUtils;
56
Mike LeBeau1f6c7e62009-09-19 18:06:52 -070057 // The broadcast receiver which receives the result of the ordered broadcast sent when
58 // the dock state changes. The original ordered broadcast is sent with an initial result
59 // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
60 // to RESULT_CANCELED, then the intent to start a dock app will not be sent.
61 private final BroadcastReceiver mResultReceiver = new BroadcastReceiver() {
62 @Override
63 public void onReceive(Context context, Intent intent) {
64 if (getResultCode() != Activity.RESULT_OK) {
65 return;
66 }
67
68 // Launch a dock activity
69 String category;
70 switch (mDockState) {
71 case Intent.EXTRA_DOCK_STATE_CAR:
72 category = Intent.CATEGORY_CAR_DOCK;
73 break;
74 case Intent.EXTRA_DOCK_STATE_DESK:
75 category = Intent.CATEGORY_DESK_DOCK;
76 break;
77 default:
78 category = null;
79 break;
80 }
81 if (category != null) {
82 intent = new Intent(Intent.ACTION_MAIN);
83 intent.addCategory(category);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070084 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
85 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Mike LeBeau1f6c7e62009-09-19 18:06:52 -070086 try {
87 mContext.startActivity(intent);
88 } catch (ActivityNotFoundException e) {
89 Log.w(TAG, e.getCause());
90 }
91 }
92 }
93 };
Ken Schultzf02c0742009-09-10 18:37:37 -050094
95 public DockObserver(Context context, PowerManagerService pm) {
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050096 mContext = context;
Ken Schultzf02c0742009-09-10 18:37:37 -050097 mPowerManager = pm;
Mike Lockwood733fdf32009-09-28 19:08:53 -040098 mLockPatternUtils = new LockPatternUtils(context.getContentResolver());
Dan Murphyc9f4eaf2009-08-12 15:15:43 -050099 init(); // set initial status
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700100 startObserving(DOCK_UEVENT_MATCH);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500101 }
102
103 @Override
104 public void onUEvent(UEventObserver.UEvent event) {
105 if (Log.isLoggable(TAG, Log.VERBOSE)) {
106 Log.v(TAG, "Dock UEVENT: " + event.toString());
107 }
108
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700109 synchronized (this) {
110 try {
111 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
112 if (newState != mDockState) {
113 mDockState = newState;
114 if (mSystemReady) {
115 update();
116 }
117 }
118 } catch (NumberFormatException e) {
119 Log.e(TAG, "Could not parse switch state from event " + event);
120 }
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500121 }
122 }
123
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700124 private final void init() {
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500125 char[] buffer = new char[1024];
126
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500127 try {
128 FileReader file = new FileReader(DOCK_STATE_PATH);
129 int len = file.read(buffer, 0, 1024);
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700130 mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500131
132 } catch (FileNotFoundException e) {
133 Log.w(TAG, "This kernel does not have dock station support");
134 } catch (Exception e) {
135 Log.e(TAG, "" , e);
136 }
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500137 }
138
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700139 void systemReady() {
140 synchronized (this) {
Mike Lockwood733fdf32009-09-28 19:08:53 -0400141 KeyguardManager keyguardManager =
142 (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
143 mKeyguardLock = keyguardManager.newKeyguardLock(TAG);
144
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700145 // don't bother broadcasting undocked here
146 if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
147 update();
148 }
149 mSystemReady = true;
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500150 }
151 }
152
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700153 private final void update() {
154 mHandler.sendEmptyMessage(0);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500155 }
156
Mike Lockwood733fdf32009-09-28 19:08:53 -0400157 private final void updateKeyguardLocked() {
158 if (!mLockPatternUtils.isLockPatternEnabled()) {
159 if (!mKeyguardDisabled && mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
160 Log.d(TAG, "calling mKeyguardLock.disableKeyguard");
161 mKeyguardLock.disableKeyguard();
162 mKeyguardDisabled = true;
163 } else if (mKeyguardDisabled && mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
164 Log.d(TAG, "calling mKeyguardLock.reenableKeyguard");
165 mKeyguardLock.reenableKeyguard();
166 mKeyguardDisabled = false;
167 }
168 }
169 }
170
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500171 private final Handler mHandler = new Handler() {
172 @Override
173 public void handleMessage(Message msg) {
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700174 synchronized (this) {
Mike Lockwood733fdf32009-09-28 19:08:53 -0400175 updateKeyguardLocked();
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700176 Log.d(TAG, "Broadcasting dock state " + mDockState);
177 // Pack up the values and broadcast them to everyone
Ken Schultzf02c0742009-09-10 18:37:37 -0500178 mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
Mike Lockwoodd0e82ce2009-08-27 16:19:07 -0700179 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
180 intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
Mike LeBeau1f6c7e62009-09-19 18:06:52 -0700181
182 // Send the ordered broadcast; the result receiver will receive after all
183 // broadcasts have been sent. If any broadcast receiver changes the result
184 // code from the initial value of RESULT_OK, then the result receiver will
185 // not launch the corresponding dock application. This gives apps a chance
186 // to override the behavior and stay in their app even when the device is
187 // placed into a dock.
188 mContext.sendStickyOrderedBroadcast(
189 intent, mResultReceiver, null, Activity.RESULT_OK, null, null);
Dan Murphyc9f4eaf2009-08-12 15:15:43 -0500190 }
191 }
192 };
193}