blob: 5271d11b6d753b53b04dfe945d50e832802067a7 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package android.server.wm.alertwindowservice;
import static android.graphics.Color.BLUE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Gravity.LEFT;
import static android.view.Gravity.TOP;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import java.util.LinkedList;
/** Service for creating and managing alert windows. */
public final class AlertWindowService extends Service {
private static final String TAG = "AlertWindowService";
private static final boolean DEBUG = false;
public static final String EXTRA_MESSENGER = "messenger";
public static final int MSG_ADD_ALERT_WINDOW = 1;
public static final int MSG_REMOVE_ALERT_WINDOW = 2;
public static final int MSG_REMOVE_ALL_ALERT_WINDOWS = 3;
public static final int MSG_ON_ALERT_WINDOW_ADDED = 4;
public static final int MSG_ON_ALERT_WINDOW_REMOVED = 5;
private LinkedList<View> mAlertWindows = new LinkedList<>();
private Messenger mOutgoingMessenger = null;
private final Messenger mIncomingMessenger = new Messenger(new IncomingHandler());
private Context mWindowContext;
private WindowManager mWindowManager;
private class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ADD_ALERT_WINDOW:
addAlertWindow();
break;
case MSG_REMOVE_ALERT_WINDOW:
removeAlertWindow();
break;
case MSG_REMOVE_ALL_ALERT_WINDOWS:
removeAllAlertWindows();
break;
default:
super.handleMessage(msg);
}
}
}
private void addAlertWindow() {
final Point size = new Point();
final WindowManager wm = mWindowManager;
mWindowContext.getDisplay().getSize(size);
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
TYPE_APPLICATION_OVERLAY,
FLAG_NOT_FOCUSABLE | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_TOUCHABLE);
params.width = size.x / 3;
params.height = size.y / 3;
params.gravity = TOP | LEFT;
final TextView view = new TextView(mWindowContext);
view.setText("AlertWindowService" + mAlertWindows.size());
view.setBackgroundColor(BLUE);
wm.addView(view, params);
mAlertWindows.add(view);
if (DEBUG) Log.e(TAG, "addAlertWindow " + mAlertWindows.size());
if (mOutgoingMessenger != null) {
try {
mOutgoingMessenger.send(Message.obtain(null, MSG_ON_ALERT_WINDOW_ADDED));
} catch (RemoteException e) {
}
}
}
private void removeAlertWindow() {
if (mAlertWindows.size() == 0) {
return;
}
final WindowManager wm = mWindowManager;
wm.removeView(mAlertWindows.pop());
if (DEBUG) Log.e(TAG, "removeAlertWindow " + mAlertWindows.size());
if (mOutgoingMessenger != null) {
try {
mOutgoingMessenger.send(Message.obtain(null, MSG_ON_ALERT_WINDOW_REMOVED));
} catch (RemoteException e) {
}
}
}
private void removeAllAlertWindows() {
while (mAlertWindows.size() > 0) {
removeAlertWindow();
}
}
@Override
public void onCreate() {
super.onCreate();
final Display display = getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
mWindowContext = createDisplayContext(display)
.createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
mWindowManager = mWindowContext.getSystemService(WindowManager.class);
}
@Override
public IBinder onBind(Intent intent) {
if (DEBUG) Log.e(TAG, "onBind");
mOutgoingMessenger = intent.getParcelableExtra(EXTRA_MESSENGER);
return mIncomingMessenger.getBinder();
}
@Override
public boolean onUnbind(Intent intent) {
if (DEBUG) Log.e(TAG, "onUnbind");
removeAllAlertWindows();
return super.onUnbind(intent);
}
}