Go to the documentation of this file.00001 package asc.tool.screencontroller;
00002
00003 import java.io.IOException;
00004 import java.io.InputStream;
00005 import java.util.ArrayList;
00006 import java.util.NoSuchElementException;
00007 import java.util.Scanner;
00008
00009 import android.app.KeyguardManager;
00010 import android.app.Notification;
00011 import android.app.Service;
00012 import android.content.BroadcastReceiver;
00013 import android.content.Context;
00014 import android.content.Intent;
00015 import android.content.IntentFilter;
00016 import android.content.pm.ActivityInfo;
00017 import android.net.LocalServerSocket;
00018 import android.net.LocalSocket;
00019 import android.os.Handler;
00020 import android.os.IBinder;
00021 import android.os.PowerManager;
00022 import android.os.Process;
00023 import android.util.Log;
00024 import android.view.View;
00025 import android.view.WindowManager;
00026 import android.view.WindowManager.LayoutParams;
00027
00028 public class ScreenControllerService extends Service {
00029 String tag = "ASC";
00030 ScreenControllerService _this = this;
00031 Handler mainthreadAccessor;
00032 WindowManager wm;
00033 PowerManager powerManager;
00034 KeyguardManager keyguardManager;
00035 boolean debug;
00036 ArrayList<LocalSocket> conAry = new ArrayList<LocalSocket>();
00037
00038 @Override
00039 public void onCreate() {
00040 super.onCreate();
00041
00042 String socketName = getPackageName();
00043 LocalServerSocket srv;
00044 try {
00045 srv = new LocalServerSocket(socketName);
00046 } catch (Throwable e) {
00047 e.printStackTrace();
00048 stopSelf();
00049 return;
00050 }
00051 final LocalServerSocket _srv = srv;
00052
00053 mainthreadAccessor = new Handler();
00054
00055 IntentFilter screenStateFilter = new IntentFilter();
00056 screenStateFilter.addAction(Intent.ACTION_SCREEN_ON);
00057 screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
00058 registerReceiver(stateReceiver, screenStateFilter);
00059
00060 new Thread() {
00061 public void run() {
00062 for (;;) {
00063 LocalSocket con;
00064 try {
00065 con = _srv.accept();
00066 } catch (Throwable e) {
00067 e.printStackTrace();
00068 System.exit(2);
00069 return;
00070 }
00071 InputStream ins;
00072 try {
00073 ins = con.getInputStream();
00074 } catch (IOException e) {
00075 e.printStackTrace();
00076 continue;
00077 }
00078
00079 synchronized (conAry) {
00080 conAry.add(con);
00081 }
00082
00083 mainthreadAccessor.post(action_startForeground);
00084
00085 final LocalSocket _con = con;
00086 final Scanner _scanner = new Scanner(ins);
00087
00088 new Thread() {
00089 public void run() {
00090 final Orient orient = new Orient();
00091 final Screen screen = new Screen();
00092 for (;;) {
00093 String cmd;
00094 try {
00095 cmd = _scanner.nextLine();
00096 } catch (NoSuchElementException e) {
00097 orient.free();
00098 screen.free();
00099 break;
00100 }
00101
00102 if ("orient:landscape".equals(cmd)) {
00103 orient.set("landscape");
00104 } else if ("orient:portrait".equals(cmd)) {
00105 orient.set("portrait");
00106 } else if ("orient:free".equals(cmd)) {
00107 orient.free();
00108 } else if ("screen:on".equals(cmd)) {
00109 screen.turnOn(false);
00110 } else if ("screen:on+unlock".equals(cmd)) {
00111 screen.turnOn(true);
00112 } else if ("screen:free".equals(cmd)) {
00113 screen.free();
00114 } else if ("debug".equals(cmd)) {
00115 debug = true;
00116 } else if ("nodebug".equals(cmd)) {
00117 debug = false;
00118 }
00119 }
00120
00121 _scanner.close();
00122
00123 synchronized (conAry) {
00124 conAry.remove(_con);
00125 }
00126
00127 mainthreadAccessor.post(action_stopForeground);
00128
00129 };
00130 }.start();
00131 }
00132 };
00133 }.start();
00134 }
00135
00136 @Override
00137 public void onDestroy() {
00138 super.onDestroy();
00139 System.exit(1);
00140 }
00141
00142 @Override
00143 public IBinder onBind(Intent intent) {
00144 return null;
00145 }
00146
00147 class Orient {
00148 View ghostView;
00149 LayoutParams lp;
00150
00151 public void set(final String orientStr) {
00152 mainthreadAccessor.post(new Runnable() {
00153 public void run() {
00154 if (debug)
00155 Log.d(tag, "orient:" + orientStr);
00156
00157 if (wm == null)
00158 wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
00159 View ghostView_to_deleted = ghostView;
00160 ghostView = new View(_this);
00161 if (lp == null)
00162 lp = newGhostLayout();
00163
00164 lp.screenOrientation = "landscape".equals(orientStr) ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
00165
00166 wm.addView(ghostView, lp);
00167
00168 if (ghostView_to_deleted != null)
00169 wm.removeView(ghostView_to_deleted);
00170 }
00171 });
00172 }
00173
00174 public void free() {
00175 mainthreadAccessor.post(new Runnable() {
00176 public void run() {
00177 if (ghostView != null) {
00178 if (debug)
00179 Log.d(tag, "orient:free");
00180 wm.removeView(ghostView);
00181 ghostView = null;
00182 }
00183 }
00184 });
00185 }
00186 }
00187
00188 class Screen {
00189 View ghostView;
00190 LayoutParams lp;
00191
00192 PowerManager.WakeLock wakeLock;
00193
00194 KeyguardManager.KeyguardLock keyguardLock;
00195
00196 public void turnOn(final boolean unlock) {
00197 mainthreadAccessor.post(new Runnable() {
00198 public void run() {
00199 if (debug)
00200 Log.d(tag, "screen:on" + (unlock ? "+unlock" : ""));
00201
00202 if (wm == null)
00203 wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
00204 View old_ghostView = ghostView;
00205 ghostView = new View(_this);
00206 if (lp == null) {
00207 lp = newGhostLayout();
00208 lp.flags |= LayoutParams.FLAG_SHOW_WHEN_LOCKED;
00209 lp.flags |= LayoutParams.FLAG_TURN_SCREEN_ON;
00210 lp.flags |= LayoutParams.FLAG_KEEP_SCREEN_ON;
00211 }
00212 if (unlock)
00213 lp.flags |= LayoutParams.FLAG_DISMISS_KEYGUARD;
00214
00215 wm.addView(ghostView, lp);
00216
00217 if (old_ghostView != null)
00218 wm.removeView(old_ghostView);
00219
00220 if (powerManager == null)
00221 powerManager = (PowerManager) getSystemService(POWER_SERVICE);
00222 PowerManager.WakeLock old_wakeLock = wakeLock;
00223 wakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, _this.getPackageName() + '#' + Thread.currentThread().getId());
00224 wakeLock.acquire();
00225
00226 if (old_wakeLock != null)
00227 old_wakeLock.release();
00228
00229 if (unlock) {
00230 if (keyguardManager == null)
00231 keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
00232 if (keyguardLock == null) {
00233 keyguardLock = keyguardManager.newKeyguardLock(_this.getPackageName() + '#' + Thread.currentThread().getId());
00234 }
00235 keyguardLock.disableKeyguard();
00236 }
00237 }
00238 });
00239 }
00240
00241 public void free() {
00242 mainthreadAccessor.post(new Runnable() {
00243 public void run() {
00244 if (debug && (ghostView != null || wakeLock != null || keyguardLock != null))
00245 Log.d(tag, "screen:free");
00246
00247 if (ghostView != null) {
00248 wm.removeView(ghostView);
00249 ghostView = null;
00250 }
00251 if (wakeLock != null) {
00252 wakeLock.release();
00253 wakeLock = null;
00254 }
00255 if (keyguardLock != null) {
00256 keyguardLock.reenableKeyguard();
00257 }
00258 }
00259 });
00260 }
00261 }
00262
00263 LayoutParams newGhostLayout() {
00264 LayoutParams lp = new LayoutParams();
00265 lp.type = LayoutParams.TYPE_SYSTEM_ERROR;
00266 lp.width = 0;
00267 lp.height = 0;
00268 lp.flags = 0;
00269 lp.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
00270 lp.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
00271 return lp;
00272 }
00273
00274 int foreground_count = 0;
00275 Runnable action_startForeground = new Runnable() {
00276 public void run() {
00277 if (foreground_count == 0) {
00278 startForeground(Process.myPid(), new Notification());
00279 }
00280 foreground_count++;
00281 }
00282 };
00283
00284 Runnable action_stopForeground = new Runnable() {
00285 public void run() {
00286 foreground_count--;
00287 if (foreground_count <= 0) {
00288 foreground_count = 0;
00289 stopForeground(true);
00290 }
00291 }
00292 };
00293
00294 BroadcastReceiver stateReceiver = new BroadcastReceiver() {
00295 byte[] on = "screen:on\n".getBytes();
00296 byte[] off = "screen:off\n".getBytes();
00297
00298 public void onReceive(Context context, Intent intent) {
00299 if (intent == null || intent.getAction() == null)
00300 return;
00301 if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
00302 notifyClient(off);
00303 } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
00304 notifyClient(on);
00305 }
00306 }
00307
00308 void notifyClient(byte[] buf) {
00309 synchronized (conAry) {
00310 for (LocalSocket con : conAry) {
00311 try {
00312 con.getOutputStream().write(buf);
00313 } catch (IOException e) {
00314 e.printStackTrace();
00315 }
00316 }
00317 }
00318 }
00319 };
00320 }