/* * 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 com.android.app2; import android.app.Service; import android.content.Intent; import android.graphics.Point; 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.View; import android.view.WindowManager; import android.widget.TextView; import java.util.LinkedList; import static android.graphics.Color.BLUE; 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; /** Service for creating and managing alert windows. */ public class AlertWindowService extends Service { private static final String TAG = "AlertWindowService"; private static final boolean DEBUG = false; 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 String NOTIFICATION_MESSENGER_EXTRA = "com.android.app2.AlertWindowService.NOTIFICATION_MESSENGER_EXTRA"; public static final int MSG_ON_ALERT_WINDOW_ADDED = 4; public static final int MSG_ON_ALERT_WINDOW_REMOVED = 5; private LinkedList mAlertWindows = new LinkedList<>(); private Messenger mOutgoingMessenger = null; private final Messenger mIncomingMessenger = new Messenger(new IncomingHandler()); 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 = getSystemService(WindowManager.class); wm.getDefaultDisplay().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(this); 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 = getSystemService(WindowManager.class); 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 IBinder onBind(Intent intent) { if (DEBUG) Log.e(TAG, "onBind"); mOutgoingMessenger = intent.getParcelableExtra(NOTIFICATION_MESSENGER_EXTRA); return mIncomingMessenger.getBinder(); } @Override public boolean onUnbind(Intent intent) { if (DEBUG) Log.e(TAG, "onUnbind"); removeAllAlertWindows(); return super.onUnbind(intent); } }