Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.cts;
     18 
     19 import android.app.Presentation;
     20 import android.app.Service;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.graphics.drawable.ColorDrawable;
     24 import android.hardware.display.DisplayManager;
     25 import android.hardware.display.VirtualDisplay;
     26 import android.os.Binder;
     27 import android.os.Bundle;
     28 import android.os.Handler;
     29 import android.os.IBinder;
     30 import android.os.Looper;
     31 import android.os.Parcel;
     32 import android.os.RemoteException;
     33 import android.util.Log;
     34 import android.view.Display;
     35 import android.view.Surface;
     36 import android.view.ViewGroup.LayoutParams;
     37 import android.view.WindowManager;
     38 import android.widget.ImageView;
     39 
     40 public class RemoteVirtualDisplayService extends Service {
     41     private static final String TAG = "RemoteVirtualDisplayService";
     42     private static final boolean DBG = false;
     43     /** argument: Surface, int w, int h, return none */
     44     private static final int BINDER_CMD_START = IBinder.FIRST_CALL_TRANSACTION;
     45     /** argument: int color, return none */
     46     private static final int BINDER_CMD_RENDER = IBinder.FIRST_CALL_TRANSACTION + 1;
     47     private final Handler mHandlerForRunOnMain = new Handler(Looper.getMainLooper());;
     48     private IBinder mBinder;
     49     private VirtualDisplayPresentation mPresentation;
     50 
     51     @Override
     52     public void onCreate() {
     53         Log.i(TAG, "onCreate");
     54         mBinder = new Binder() {
     55             @Override
     56             protected boolean onTransact(int code, Parcel data, Parcel reply,
     57                     int flags) throws RemoteException {
     58                 switch(code) {
     59                     case BINDER_CMD_START: {
     60                         Surface surface = Surface.CREATOR.createFromParcel(data);
     61                         int w = data.readInt();
     62                         int h = data.readInt();
     63                         start(surface, w, h);
     64                         break;
     65                     }
     66                     case BINDER_CMD_RENDER: {
     67                         int color = data.readInt();
     68                         render(color);
     69                         break;
     70                     }
     71                     default:
     72                         Log.e(TAG, "unrecognized binder command " + code);
     73                         return false;
     74                 }
     75                 return true;
     76             }
     77         };
     78     }
     79 
     80     @Override
     81     public IBinder onBind(Intent intent) {
     82         Log.i(TAG, "onBind");
     83         return mBinder;
     84     }
     85 
     86     @Override
     87     public void onDestroy() {
     88         Log.i(TAG, "onDestroy");
     89         if (mPresentation != null) {
     90             mPresentation.dismissPresentation();
     91             mPresentation.destroyVirtualDisplay();
     92             mPresentation = null;
     93         }
     94     }
     95 
     96     private void start(Surface surface, int w, int h) {
     97         Log.i(TAG, "start");
     98         mPresentation = new VirtualDisplayPresentation(this, surface, w, h);
     99         mPresentation.createVirtualDisplay();
    100         mPresentation.createPresentation();
    101     }
    102 
    103     private void render(int color) {
    104         if (DBG) {
    105             Log.i(TAG, "render " + Integer.toHexString(color));
    106         }
    107         mPresentation.doRendering(color);
    108     }
    109 
    110     private class VirtualDisplayPresentation {
    111         private Context mContext;
    112         private Surface mSurface;
    113         private int mWidth;
    114         private int mHeight;
    115         private final DisplayManager mDisplayManager;
    116         private VirtualDisplay mVirtualDisplay;
    117         private TestPresentation mPresentation;
    118 
    119         VirtualDisplayPresentation(Context context, Surface surface, int w, int h) {
    120             mContext = context;
    121             mSurface = surface;
    122             mWidth = w;
    123             mHeight = h;
    124             mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
    125         }
    126 
    127         void createVirtualDisplay() {
    128             runOnMainSync(new Runnable() {
    129                 @Override
    130                 public void run() {
    131                     mVirtualDisplay = mDisplayManager.createVirtualDisplay(
    132                             TAG, mWidth, mHeight, 200, mSurface, 0);
    133                 }
    134             });
    135         }
    136 
    137         void destroyVirtualDisplay() {
    138             if (mVirtualDisplay != null) {
    139                 mVirtualDisplay.release();
    140             }
    141         }
    142 
    143         void createPresentation() {
    144             runOnMainSync(new Runnable() {
    145                 @Override
    146                 public void run() {
    147                     mPresentation = new TestPresentation(RemoteVirtualDisplayService.this,
    148                             mVirtualDisplay.getDisplay());
    149                     mPresentation.show();
    150                 }
    151             });
    152         }
    153 
    154         void dismissPresentation() {
    155             if (mPresentation != null) {
    156                 mPresentation.dismiss();
    157             }
    158         }
    159 
    160         public void doRendering(final int color) {
    161             runOnMainSync(new Runnable() {
    162                 @Override
    163                 public void run() {
    164                     mPresentation.doRendering(color);
    165                 }
    166             });
    167         }
    168 
    169         private class TestPresentation extends Presentation {
    170             private ImageView mImageView;
    171 
    172             public TestPresentation(Context outerContext, Display display) {
    173                 // This theme is required to prevent an extra view from obscuring the presentation
    174                 super(outerContext, display,
    175                         android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
    176                 getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
    177                 getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
    178             }
    179 
    180             @Override
    181             protected void onCreate(Bundle savedInstanceState) {
    182                 super.onCreate(savedInstanceState);
    183                 mImageView = new ImageView(getContext());
    184                 mImageView.setImageDrawable(new ColorDrawable(0));
    185                 mImageView.setLayoutParams(new LayoutParams(
    186                         LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    187                 setContentView(mImageView);
    188             }
    189 
    190             public void doRendering(int color) {
    191                 mImageView.setImageDrawable(new ColorDrawable(color));
    192             }
    193         }
    194     }
    195 
    196     private void runOnMainSync(Runnable runner) {
    197         SyncRunnable sr = new SyncRunnable(runner);
    198         mHandlerForRunOnMain.post(sr);
    199         sr.waitForComplete();
    200     }
    201 
    202     private static final class SyncRunnable implements Runnable {
    203         private final Runnable mTarget;
    204         private boolean mComplete;
    205 
    206         public SyncRunnable(Runnable target) {
    207             mTarget = target;
    208         }
    209 
    210         public void run() {
    211             mTarget.run();
    212             synchronized (this) {
    213                 mComplete = true;
    214                 notifyAll();
    215             }
    216         }
    217 
    218         public void waitForComplete() {
    219             synchronized (this) {
    220                 while (!mComplete) {
    221                     try {
    222                         wait();
    223                     } catch (InterruptedException e) {
    224                         //ignore
    225                     }
    226                 }
    227             }
    228         }
    229     }
    230 }
    231