blob: 0cd0643ee8c07b2e14d332c3887145390ec1d6c5 [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 com.android.coretests.apps.bstatstestapp;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.R;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class TestService extends Service {
private static final String TAG = TestService.class.getSimpleName();
private static final int FLAG_START_FOREGROUND = 1;
private static final String NOTIFICATION_CHANNEL_ID = TAG;
private static final int NOTIFICATION_ID = 42;
private static final int TIMEOUT_OVERLAY_SEC = 2;
private Context mOverlayContext;
private View mOverlay;
@Override
public void onCreate() {
Log.d(TAG, "onCreate called. myUid=" + Process.myUid());
final DisplayManager dm = getSystemService(DisplayManager.class);
final Display defaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
final Context defaultDisplayContext = createDisplayContext(defaultDisplay);
mOverlayContext = defaultDisplayContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand called. myUid=" + Process.myUid());
if (intent != null && (intent.getFlags() & FLAG_START_FOREGROUND) != 0) {
startForeground();
}
notifyServiceLaunched(intent);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind called. myUid=" + Process.myUid());
return null;
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy called. myUid=" + Process.myUid());
removeOverlays();
}
private void notifyServiceLaunched(Intent intent) {
Common.notifyLaunched(intent, mReceiver.asBinder(), TAG);
}
private void startForeground() {
final NotificationManager noMan = getSystemService(NotificationManager.class);
noMan.createNotificationChannel(new NotificationChannel(
NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
NotificationManager.IMPORTANCE_DEFAULT));
Log.d(TAG, "Starting foreground. myUid=" + Process.myUid());
startForeground(NOTIFICATION_ID,
new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_dialog_alert)
.build());
}
private void removeOverlays() {
if (mOverlay != null) {
final WindowManager wm = mOverlayContext.getSystemService(WindowManager.class);
wm.removeView(mOverlay);
mOverlay = null;
}
}
private BaseCmdReceiver mReceiver = new BaseCmdReceiver() {
@Override
public void doSomeWork(int durationMs) {
Common.doSomeWork(durationMs);
}
@Override
public void showApplicationOverlay() throws RemoteException {
final WindowManager wm = mOverlayContext.getSystemService(WindowManager.class);
final Rect bounds = wm.getCurrentWindowMetrics().getBounds();
final WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(
TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
wmlp.width = bounds.width() / 2;
wmlp.height = bounds.height() / 2;
wmlp.gravity = Gravity.CENTER | Gravity.LEFT;
wmlp.setTitle(TAG);
final ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mOverlay = new View(mOverlayContext);
mOverlay.setBackgroundColor(Color.GREEN);
mOverlay.setLayoutParams(vglp);
final CountDownLatch latch = new CountDownLatch(1);
final Handler handler = new Handler(TestService.this.getMainLooper());
handler.post(() -> {
wm.addView(mOverlay, wmlp);
latch.countDown();
});
try {
if (!latch.await(TIMEOUT_OVERLAY_SEC, TimeUnit.SECONDS)) {
throw new RemoteException("Timed out waiting for the overlay");
}
} catch (InterruptedException e) {
throw new RemoteException("Error while adding overlay: " + e.toString());
}
Log.d(TAG, "Overlay displayed, myUid=" + Process.myUid());
}
@Override
public void finishHost() {
removeOverlays();
stopSelf();
}
};
}