blob: 63a2aed0d0d4158429f660ef715cce3f9cd2272f [file] [log] [blame]
/*
* Copyright (C) 2020 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.car.ui.paintbooth;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import androidx.core.app.NotificationCompat;
/**
* To start the service:
* adb shell am start-foreground-service com.android.car.ui.paintbooth/.DisplayService
*
* To stop the service:
* adb shell am stopservice com.android.car.ui.paintbooth/.DisplayService
*
* When the service is started it will draw a overlay view on top of the screen displayed. This
* overlay comes from a SVG file that can be modified to take different shapes. This service will be
* used to display different screen styles from OEMs.
*/
public class VisibleBoundsSimulator extends Service {
private static final int FOREGROUND_SERVICE_ID = 222;
private View mContainer;
private WindowManager mWindowManager;
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented.");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (MainActivity.STOP_SERVICE.equals(intent.getAction())) {
stopSelf();
}
return START_STICKY;
}
@Override
public void onCreate() {
Intent notificationIntent = new Intent(this, VisibleBoundsSimulator.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
NotificationChannel channel = new NotificationChannel("DisplayService",
"Show overlay screen",
NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
Notification notification =
new NotificationCompat.Builder(this, "DisplayService")
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("DisplayService")
.setContentText("Show overlay screen")
.setContentIntent(pendingIntent).build();
startForeground(FOREGROUND_SERVICE_ID, notification);
applyDisplayOverlay();
}
/**
* Creates a view overlay on top of a new window. The overlay gravity is set to left and
* bottom. If the width and height is not provided then the default is to take up the entire
* screen. Overlay will show bounds around the view and we can still click through the window.
*/
private void applyDisplayOverlay() {
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
int screenHeight = displayMetrics.heightPixels;
int screenWidth = displayMetrics.widthPixels;
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
// WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY is a hidden api, so
// use its value here so we can still compile on gradle / google3
WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + 26,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSLUCENT);
params.packageName = this.getPackageName();
params.gravity = Gravity.BOTTOM | Gravity.LEFT;
Display display = mWindowManager.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int height = size.y;
params.x = 0;
// If the sysUI is showing and nav bar is taking up some space at the bottom we want to
// offset the height of the navBar so that the overlay starts from the bottom left.
params.y = -(screenHeight - height);
float overlayWidth = getApplicationContext().getResources().getDimension(
R.dimen.screen_shape_container_width);
float overlayHeight = getApplicationContext().getResources().getDimension(
R.dimen.screen_shape_container_height);
params.width = (int) (overlayWidth == 0 ? screenWidth : overlayHeight);
params.height = (int) (overlayHeight == 0 ? screenHeight : overlayHeight);
params.setTitle("Simulated display bound");
mContainer = inflater.inflate(R.layout.simulated_screen_shape_container, null);
mContainer.setLayoutParams(params);
mWindowManager.addView(mContainer, params);
}
@Override
public void onDestroy() {
super.onDestroy();
mWindowManager.removeView(mContainer);
stopSelf();
}
}