blob: 4201b396d6dfa4b1b363c7515e7e8753e31861b5 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 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.util.Log;
20
21import java.net.ServerSocket;
22import java.net.Socket;
23import java.net.InetAddress;
24import java.io.IOException;
25import java.io.BufferedReader;
26import java.io.InputStreamReader;
27
28/**
29 * The ViewServer is local socket server that can be used to communicate with the
30 * views of the opened windows. Communication with the views is ensured by the
31 * {@link com.android.server.WindowManagerService} and is a cross-process operation.
32 *
33 * {@hide}
34 */
35class ViewServer implements Runnable {
36 /**
37 * The default port used to start view servers.
38 */
39 public static final int VIEW_SERVER_DEFAULT_PORT = 4939;
40
41 // Debug facility
42 private static final String LOG_TAG = "ViewServer";
43
44 // Protocol commands
45 // Lists all of the available windows in the system
46 private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST";
47
48 private ServerSocket mServer;
49 private Thread mThread;
50
51 private final WindowManagerService mWindowManager;
52 private final int mPort;
53
54 /**
55 * Creates a new ViewServer associated with the specified window manager.
56 * The server uses the default port {@link #VIEW_SERVER_DEFAULT_PORT}. The server
57 * is not started by default.
58 *
59 * @param windowManager The window manager used to communicate with the views.
60 *
61 * @see #start()
62 */
63 ViewServer(WindowManagerService windowManager) {
64 this(windowManager, VIEW_SERVER_DEFAULT_PORT);
65 }
66
67 /**
68 * Creates a new ViewServer associated with the specified window manager on the
69 * specified local port. The server is not started by default.
70 *
71 * @param windowManager The window manager used to communicate with the views.
72 * @param port The port for the server to listen to.
73 *
74 * @see #start()
75 */
76 ViewServer(WindowManagerService windowManager, int port) {
77 mWindowManager = windowManager;
78 mPort = port;
79 }
80
81 /**
82 * Starts the server.
83 *
84 * @return True if the server was successfully created, or false if it already exists.
85 * @throws IOException If the server cannot be created.
86 *
87 * @see #stop()
88 * @see #isRunning()
89 * @see WindowManagerService#startViewServer(int)
90 */
91 boolean start() throws IOException {
92 if (mThread != null) {
93 return false;
94 }
95
96 mServer = new ServerSocket(mPort, 1, InetAddress.getLocalHost());
97 mThread = new Thread(this, "Remote View Server [port=" + mPort + "]");
98 mThread.start();
99
100 return true;
101 }
102
103 /**
104 * Stops the server.
105 *
106 * @return True if the server was stopped, false if an error occured or if the
107 * server wasn't started.
108 *
109 * @see #start()
110 * @see #isRunning()
111 * @see WindowManagerService#stopViewServer()
112 */
113 boolean stop() {
114 if (mThread != null) {
115 mThread.interrupt();
116 mThread = null;
117 try {
118 mServer.close();
119 mServer = null;
120 return true;
121 } catch (IOException e) {
122 Log.w(LOG_TAG, "Could not close the view server");
123 }
124 }
125 return false;
126 }
127
128 /**
129 * Indicates whether the server is currently running.
130 *
131 * @return True if the server is running, false otherwise.
132 *
133 * @see #start()
134 * @see #stop()
135 * @see WindowManagerService#isViewServerRunning()
136 */
137 boolean isRunning() {
138 return mThread != null && mThread.isAlive();
139 }
140
141 /**
142 * Main server loop.
143 */
144 public void run() {
145 final ServerSocket server = mServer;
146
147 while (Thread.currentThread() == mThread) {
148 Socket client = null;
149 // Any uncaught exception will crash the system process
150 try {
151 client = server.accept();
152
153 BufferedReader in = null;
154 try {
155 in = new BufferedReader(new InputStreamReader(client.getInputStream()), 1024);
156
157 final String request = in.readLine();
158
159 String command;
160 String parameters;
161
162 int index = request.indexOf(' ');
163 if (index == -1) {
164 command = request;
165 parameters = "";
166 } else {
167 command = request.substring(0, index);
168 parameters = request.substring(index + 1);
169 }
170
171 boolean result;
172 if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {
173 result = mWindowManager.viewServerListWindows(client);
174 } else {
175 result = mWindowManager.viewServerWindowCommand(client,
176 command, parameters);
177 }
178
179 if (!result) {
180 Log.w(LOG_TAG, "An error occured with the command: " + command);
181 }
182 } finally {
183 if (in != null) {
184 in.close();
185 }
186 }
187 } catch (Exception e) {
188 Log.w(LOG_TAG, "Connection error: ", e);
189 } finally {
190 if (client != null) {
191 try {
192 client.close();
193 } catch (IOException e) {
194 e.printStackTrace();
195 }
196 }
197 }
198 }
199 }
200}