blob: 25737f7f57e58a0f378482ed7920298791c99a1c [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 android.server.wm.overlay;
import static android.view.Display.DEFAULT_DISPLAY;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.server.wm.shared.IUntrustedTouchTestService;
import android.util.ArrayMap;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;
import androidx.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
public class UntrustedTouchTestService extends Service {
public static final int BACKGROUND_COLOR = 0xFF00FF00;
/** Map from view to the service manager that manages it. */
private final Map<View, WindowManager> mViewManagers = Collections.synchronizedMap(
new ArrayMap<>());
/** Can only be accessed from the main thread. */
private Toast mToast;
private final IUntrustedTouchTestService mBinder = new Binder();
private volatile Handler mMainHandler;
private volatile Context mSawContext;
private volatile WindowManager mWindowManager;
private volatile WindowManager mSawWindowManager;
@Override
public void onCreate() {
mMainHandler = new Handler(Looper.getMainLooper());
mWindowManager = getSystemService(WindowManager.class);
mSawContext = getContextForSaw(this);
mSawWindowManager = mSawContext.getSystemService(WindowManager.class);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder.asBinder();
}
@Override
public void onDestroy() {
removeOverlays();
}
private class Binder extends IUntrustedTouchTestService.Stub {
private final UntrustedTouchTestService mService = UntrustedTouchTestService.this;
@Override
public void showToast() {
mMainHandler.post(() -> {
mToast = Toast.makeText(mService, "Toast " + getPackageName(), Toast.LENGTH_LONG);
mToast.show();
});
}
@Override
public void showSystemAlertWindow(String name, float opacity) {
View view = getView(mSawContext);
LayoutParams params = newOverlayLayoutParams(name,
LayoutParams.TYPE_APPLICATION_OVERLAY);
params.setTitle(name);
params.alpha = opacity;
mMainHandler.post(() -> mSawWindowManager.addView(view, params));
mViewManagers.put(view, mSawWindowManager);
}
@Override
public void showActivityChildWindow(String name, IBinder token) throws RemoteException {
View view = getView(mService);
LayoutParams params = newOverlayLayoutParams(name, LayoutParams.TYPE_APPLICATION);
params.token = token;
mMainHandler.post(() -> mWindowManager.addView(view, params));
mViewManagers.put(view, mWindowManager);
}
public void removeOverlays() {
mService.removeOverlays();
}
}
private void removeOverlays() {
synchronized (mViewManagers) {
for (View view : mViewManagers.keySet()) {
mViewManagers.get(view).removeView(view);
}
mViewManagers.clear();
}
mMainHandler.post(() -> {
if (mToast != null) {
mToast.cancel();
}
});
}
private static Context getContextForSaw(Context context) {
DisplayManager displayManager = context.getSystemService(DisplayManager.class);
Display display = displayManager.getDisplay(DEFAULT_DISPLAY);
Context displayContext = context.createDisplayContext(display);
return displayContext.createWindowContext(LayoutParams.TYPE_APPLICATION_OVERLAY, null);
}
private static View getView(Context context) {
View view = new View(context);
view.setBackgroundColor(BACKGROUND_COLOR);
return view;
}
private static LayoutParams newOverlayLayoutParams(String windowName, int type) {
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT,
type,
LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
params.setTitle(windowName);
return params;
}
}