| /* |
| * Copyright (C) 2014 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.media.cts; |
| |
| import android.app.Presentation; |
| import android.app.Service; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.graphics.drawable.ColorDrawable; |
| import android.hardware.display.DisplayManager; |
| import android.hardware.display.VirtualDisplay; |
| import android.os.Binder; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.Looper; |
| import android.os.Parcel; |
| import android.os.RemoteException; |
| import android.util.Log; |
| import android.view.Display; |
| import android.view.Surface; |
| import android.view.ViewGroup.LayoutParams; |
| import android.view.WindowManager; |
| import android.widget.ImageView; |
| |
| public class RemoteVirtualDisplayService extends Service { |
| private static final String TAG = "RemoteVirtualDisplayService"; |
| |
| /** argument: Surface, int w, int h, return none */ |
| private static final int BINDER_CMD_START = IBinder.FIRST_CALL_TRANSACTION; |
| /** argument: int color, return none */ |
| private static final int BINDER_CMD_RENDER = IBinder.FIRST_CALL_TRANSACTION + 1; |
| private final Handler mHandlerForRunOnMain = new Handler(Looper.getMainLooper());; |
| private IBinder mBinder; |
| private VirtualDisplayPresentation mPresentation; |
| |
| @Override |
| public void onCreate() { |
| Log.i(TAG, "onCreate"); |
| mBinder = new Binder() { |
| @Override |
| protected boolean onTransact(int code, Parcel data, Parcel reply, |
| int flags) throws RemoteException { |
| switch(code) { |
| case BINDER_CMD_START: { |
| Surface surface = Surface.CREATOR.createFromParcel(data); |
| int w = data.readInt(); |
| int h = data.readInt(); |
| start(surface, w, h); |
| break; |
| } |
| case BINDER_CMD_RENDER: { |
| int color = data.readInt(); |
| render(color); |
| break; |
| } |
| default: |
| Log.e(TAG, "unrecognized binder command " + code); |
| return false; |
| } |
| return true; |
| } |
| }; |
| } |
| |
| @Override |
| public IBinder onBind(Intent intent) { |
| Log.i(TAG, "onBind"); |
| return mBinder; |
| } |
| |
| @Override |
| public void onDestroy() { |
| Log.i(TAG, "onDestroy"); |
| if (mPresentation != null) { |
| mPresentation.dismissPresentation(); |
| mPresentation.destroyVirtualDisplay(); |
| mPresentation = null; |
| } |
| } |
| |
| private void start(Surface surface, int w, int h) { |
| Log.i(TAG, "start"); |
| mPresentation = new VirtualDisplayPresentation(this, surface, w, h); |
| mPresentation.createVirtualDisplay(); |
| mPresentation.createPresentation(); |
| } |
| |
| private void render(int color) { |
| Log.i(TAG, "render"); |
| mPresentation.doRendering(color); |
| } |
| |
| private class VirtualDisplayPresentation { |
| private Context mContext; |
| private Surface mSurface; |
| private int mWidth; |
| private int mHeight; |
| private final DisplayManager mDisplayManager; |
| private VirtualDisplay mVirtualDisplay; |
| private TestPresentation mPresentation; |
| |
| VirtualDisplayPresentation(Context context, Surface surface, int w, int h) { |
| mContext = context; |
| mSurface = surface; |
| mWidth = w; |
| mHeight = h; |
| mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE); |
| } |
| |
| void createVirtualDisplay() { |
| runOnMainSync(new Runnable() { |
| @Override |
| public void run() { |
| mVirtualDisplay = mDisplayManager.createVirtualDisplay( |
| TAG, mWidth, mHeight, 200, mSurface, 0); |
| } |
| }); |
| } |
| |
| void destroyVirtualDisplay() { |
| if (mVirtualDisplay != null) { |
| mVirtualDisplay.release(); |
| } |
| } |
| |
| void createPresentation() { |
| runOnMainSync(new Runnable() { |
| @Override |
| public void run() { |
| mPresentation = new TestPresentation(RemoteVirtualDisplayService.this, |
| mVirtualDisplay.getDisplay()); |
| mPresentation.show(); |
| } |
| }); |
| } |
| |
| void dismissPresentation() { |
| if (mPresentation != null) { |
| mPresentation.dismiss(); |
| } |
| } |
| |
| public void doRendering(final int color) { |
| runOnMainSync(new Runnable() { |
| @Override |
| public void run() { |
| mPresentation.doRendering(color); |
| } |
| }); |
| } |
| |
| private class TestPresentation extends Presentation { |
| private ImageView mImageView; |
| |
| public TestPresentation(Context outerContext, Display display) { |
| super(outerContext, display); |
| getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION); |
| getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); |
| } |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| mImageView = new ImageView(getContext()); |
| mImageView.setImageDrawable(new ColorDrawable(0)); |
| mImageView.setLayoutParams(new LayoutParams( |
| LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); |
| setContentView(mImageView); |
| } |
| |
| public void doRendering(int color) { |
| mImageView.setImageDrawable(new ColorDrawable(color)); |
| } |
| } |
| } |
| |
| private void runOnMainSync(Runnable runner) { |
| SyncRunnable sr = new SyncRunnable(runner); |
| mHandlerForRunOnMain.post(sr); |
| sr.waitForComplete(); |
| } |
| |
| private static final class SyncRunnable implements Runnable { |
| private final Runnable mTarget; |
| private boolean mComplete; |
| |
| public SyncRunnable(Runnable target) { |
| mTarget = target; |
| } |
| |
| public void run() { |
| mTarget.run(); |
| synchronized (this) { |
| mComplete = true; |
| notifyAll(); |
| } |
| } |
| |
| public void waitForComplete() { |
| synchronized (this) { |
| while (!mComplete) { |
| try { |
| wait(); |
| } catch (InterruptedException e) { |
| //ignore |
| } |
| } |
| } |
| } |
| } |
| } |