blob: 9c611eaf0ae0b073a428d0445b53a4123f37e342 [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.app;
import static android.server.wm.app.Components.RenderService.BROADCAST_EMBED_CONTENT;
import static android.server.wm.app.Components.RenderService.EXTRAS_BUNDLE;
import static android.server.wm.app.Components.RenderService.EXTRAS_DISPLAY_ID;
import static android.server.wm.app.Components.RenderService.EXTRAS_HOST_TOKEN;
import static android.server.wm.app.Components.RenderService.EXTRAS_SURFACE_PACKAGE;
import static android.server.wm.app.Components.UnresponsiveActivity.EXTRA_ON_MOTIONEVENT_DELAY_MS;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceControlViewHost;
import android.view.View;
import android.widget.Button;
import java.util.concurrent.CountDownLatch;
public class RenderService extends Service {
private int mOnMotionEventDelayMs;
CountDownLatch mViewDrawnCallbackLatch = new CountDownLatch(1);
private boolean onTouch(View v, MotionEvent event) {
SystemClock.sleep(mOnMotionEventDelayMs);
// Don't consume the event.
return false;
}
@Override
public IBinder onBind(Intent intent) {
Bundle b = intent.getBundleExtra(EXTRAS_BUNDLE);
IBinder hostToken = b.getBinder(EXTRAS_HOST_TOKEN);
int hostDisplayId = b.getInt(EXTRAS_DISPLAY_ID);
mOnMotionEventDelayMs = b.getInt(EXTRA_ON_MOTIONEVENT_DELAY_MS);
SurfaceControlViewHost surfaceControlViewHost = getSurfaceControlViewHost(hostToken,
hostDisplayId);
new Thread(()-> sendSurfacePackage(surfaceControlViewHost.getSurfacePackage())).start();
return null;
}
private SurfaceControlViewHost getSurfaceControlViewHost(IBinder hostToken, int hostDisplayId) {
final Context displayContext = getDisplayContext(hostDisplayId);
SurfaceControlViewHost surfaceControlViewHost =
new SurfaceControlViewHost(displayContext, displayContext.getDisplay(), hostToken);
View embeddedView = new Button(this);
embeddedView.setOnTouchListener(this::onTouch);
embeddedView.getViewTreeObserver().registerFrameCommitCallback(
mViewDrawnCallbackLatch::countDown);
DisplayMetrics metrics = new DisplayMetrics();
displayContext.getDisplay().getMetrics(metrics);
surfaceControlViewHost.setView(embeddedView, metrics.widthPixels, metrics.heightPixels);
return surfaceControlViewHost;
}
private Context getDisplayContext(int hostDisplayId) {
final DisplayManager displayManager = getSystemService(DisplayManager.class);
final Display targetDisplay = displayManager.getDisplay(hostDisplayId);
return createDisplayContext(targetDisplay);
}
private void sendSurfacePackage(SurfaceControlViewHost.SurfacePackage surfacePackage) {
try {
// wait until we commit a frame from the embedded viewrootimpl
mViewDrawnCallbackLatch.await();
} catch (InterruptedException ignored) {
}
Intent broadcast = new Intent(BROADCAST_EMBED_CONTENT);
broadcast.putExtra(EXTRAS_SURFACE_PACKAGE, surfacePackage);
sendBroadcast(broadcast);
}
}