zoukankan      html  css  js  c++  java
  • android4.2 RemoteDisplay远程显示修改为保存文件

    RemoteDisplay其是具体Display的业务实现,其包含JAVA层与JNI,library三个层。

    在android 4.2当中主要是WifiDisplayAdapter使用了RemoteDisplay。

    也就是RemoteDisplay其是基础,WifiDisplayAdapter只是使用了其的功能!!!

    pizzaframeworksasemediajavaandroidmediaRemoteDisplay.java

    private native int nativeListen(String iface);
    private native int nativeStartRecord(String iface);
    private native int nativePauseRecord(int ptr);
    private native int nativeResumeRecord(int ptr);
    private native int nativeStopRecord(int ptr);
    private native void nativeDispose(int ptr);

    public static RemoteDisplay recordScreen(String outfile, Listener listener, Handler handler) {
         if (outfile == null) {
             throw new IllegalArgumentException("iface must not be null");
         }
         if (listener == null) {
             throw new IllegalArgumentException("listener must not be null");
         }
         if (handler == null) {
             throw new IllegalArgumentException("handler must not be null");
         }

         RemoteDisplay display = new RemoteDisplay(listener, handler);
         display.startRecording(outfile);
         return display;
    }

        private void startListening(String iface) {
            mPtr = nativeListen(iface);
            if (mPtr == 0) {
                throw new IllegalStateException("Could not start listening for "
                        + "remote display connection on "" + iface + """);
            }
            mGuard.open("dispose");
            mGuard.open("stopRecording");
        }
       public void startRecording(String outfile) {
            Log.e(TAG, "### startRecording ###");
                    mPtr = nativeStartRecord(outfile);
            if (mPtr == 0) {
                throw new IllegalStateException("Could not start listening for "
                        + "remote display connection on "" + outfile + """);
            }
        }

        public void pauseRecording() {
            Log.e(TAG, "### pauseRecording  ###");
            if(mPtr != 0)
                {      
                    nativePauseRecord(mPtr);
                }
        }
        public void resumeRecording() {
            Log.e(TAG, "### resumeRecording  ###");
            if(mPtr != 0)
                {
                    nativeResumeRecord(mPtr);
                }
        }

        public void stopRecording() {
            Log.e(TAG, "### stopRecording  ###");
         stopRecording(false);
        }

        private void stopRecording(boolean finalized) {
            if(mPtr != 0)
            {
                if (mGuardRecScr != null) {
                    if (finalized) {
                        mGuardRecScr.warnIfOpen();
                    } else {
                        mGuardRecScr.close();
                    }
                }
                  nativeStopRecord(mPtr);
            mPtr = 0;
            }
        }

    // Called from native.
    private void notifyRecordScreen(final byte[] buffer, final int len) {
            Log.e(TAG, "### notifyRecordScreen  ###");           
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                mListener.onRecordScreen(buffer, len);
            }
        });
    }

        /**
         * Listener invoked when the remote display connection changes state.
         */
        public interface Listener {
            void onDisplayConnected(Surface surface, int width, int height, int flags);
            void onDisplayDisconnected();
            void onDisplayError(int error);
           void onRecordScreen(byte[] buffer, int len);    
    }

    pizzaframeworksasecorejniandroid_media_RemoteDisplay.cpp

    namespace android {

    static struct {
        jmethodID notifyDisplayConnected;
        jmethodID notifyDisplayDisconnected;
        jmethodID notifyDisplayError;
        jmethodID notifyRecordScreen;
    } gRemoteDisplayClassInfo;

    // ----------------------------------------------------------------------------

    class NativeRemoteDisplayClient : public BnRemoteDisplayClient {
    public:
        NativeRemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj) :
                mRemoteDisplayObjGlobal(env->NewGlobalRef(remoteDisplayObj)) {
        }

    protected:
        ~NativeRemoteDisplayClient() {
            JNIEnv* env = AndroidRuntime::getJNIEnv();
            env->DeleteGlobalRef(mRemoteDisplayObjGlobal);
        }

    public:
        virtual void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture,
                uint32_t width, uint32_t height, uint32_t flags) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();

            jobject surfaceObj = android_view_Surface_createFromISurfaceTexture(env, surfaceTexture);
            if (surfaceObj == NULL) {
                ALOGE("Could not create Surface from surface texture %p provided by media server.",
                        surfaceTexture.get());
                return;
            }

            env->CallVoidMethod(mRemoteDisplayObjGlobal,
                    gRemoteDisplayClassInfo.notifyDisplayConnected,
                    surfaceObj, width, height, flags);
            env->DeleteLocalRef(surfaceObj);
            checkAndClearExceptionFromCallback(env, "notifyDisplayConnected");
        }

        virtual void onDisplayDisconnected() {
            JNIEnv* env = AndroidRuntime::getJNIEnv();

            env->CallVoidMethod(mRemoteDisplayObjGlobal,
                    gRemoteDisplayClassInfo.notifyDisplayDisconnected);
            checkAndClearExceptionFromCallback(env, "notifyDisplayDisconnected");
        }

        virtual void onDisplayError(int32_t error) {
            JNIEnv* env = AndroidRuntime::getJNIEnv();

            env->CallVoidMethod(mRemoteDisplayObjGlobal,
                    gRemoteDisplayClassInfo.notifyDisplayError, error);
            checkAndClearExceptionFromCallback(env, "notifyDisplayError");
        }

      virtual void onRecordScreen(char *buffer, int len) {
        }

    private:
        jobject mRemoteDisplayObjGlobal;

        static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
            if (env->ExceptionCheck()) {
                ALOGE("An exception was thrown by callback '%s'.", methodName);
                LOGE_EX(env);
                env->ExceptionClear();
            }
        }
    };

    class NativeRemoteDisplay {
    public:
        NativeRemoteDisplay(const sp<IRemoteDisplay>& display,
                const sp<NativeRemoteDisplayClient>& client) :
                mDisplay(display), mClient(client) {
        }

        ~NativeRemoteDisplay() {
            mDisplay->dispose();
        }

    private:
        sp<IRemoteDisplay> mDisplay;
        sp<NativeRemoteDisplayClient> mClient;
    };

    // ----------------------------------------------------------------------------

    struct RemoteDisplayClient : public BnRemoteDisplayClient {
        RemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj);

        virtual void onDisplayConnected(
                const sp<ISurfaceTexture> &surfaceTexture,
                uint32_t width,
                uint32_t height,
                uint32_t flags);

        virtual void onDisplayDisconnected();
        virtual void onDisplayError(int32_t error);
        virtual void onRecordScreen(char *buffer, int len);

        void waitUntilDone();

    protected:
        virtual ~RemoteDisplayClient();

    private:
        JNIEnv* mEnv;

        Mutex mLock;
        Condition mCondition;

        bool mDone;

    // 有了这个几个Display才能够真正的镜像显示数据

        sp<SurfaceComposerClient> mComposerClient;

        sp<ISurfaceTexture> mSurfaceTexture;

        sp<IBinder> mDisplayBinder;

        jobject mRemoteDisplayObjGlobal;
        static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
            if (env->ExceptionCheck()) {
                ALOGE("An exception was thrown by callback '%s'.", methodName);
                LOGE_EX(env);
                env->ExceptionClear();
            }
        }

        DISALLOW_EVIL_CONSTRUCTORS(RemoteDisplayClient);
    };

    static status_t enableAudioSubmix(bool enable) {
        status_t err = AudioSystem::setDeviceConnectionState(
                AUDIO_DEVICE_IN_REMOTE_SUBMIX,
                enable
                    ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE
                    : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                NULL /* device_address */);

        if (err != OK) {
        return err;
    }

        err = AudioSystem::setDeviceConnectionState(
                AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
                enable
                    ? AUDIO_POLICY_DEVICE_STATE_AVAILABLE
                    : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
                NULL /* device_address */);

        return err;
    }

    RemoteDisplayClient::RemoteDisplayClient(JNIEnv* env, jobject remoteDisplayObj) :
             mEnv(env),
                mRemoteDisplayObjGlobal(env->NewGlobalRef(remoteDisplayObj)),
             mDone(false) {
        mComposerClient = new SurfaceComposerClient;
        mComposerClient->initCheck();
        //CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
    }

    RemoteDisplayClient::~RemoteDisplayClient() {
                JNIEnv* env = AndroidRuntime::getJNIEnv();
            env->DeleteGlobalRef(mRemoteDisplayObjGlobal);
    }

    void RemoteDisplayClient::onDisplayConnected(
            const sp<ISurfaceTexture> &surfaceTexture,
            uint32_t width,
            uint32_t height,
            uint32_t flags) {
        ALOGI("#### onDisplayConnected width=%u, height=%u, flags = 0x%08x",
              width, height, flags);
        if(999 == flags)
        {
            onRecordScreen((char *)width, (int)height);
        return;
        }   
        mSurfaceTexture = surfaceTexture;

    // 内部通过SurfaceComposerClient,最终调用SurfaceFlinger来创建一个DisplayDeviceState,添加到

    // DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL); –> 所有createDisplay均是DISPLAY_VIRTUAL类型

    //mCurrentState.displays.add(token,info); 在SurfaceFlinger当中添加了一个显示设备,SurfaceFlinger就会将这些数据

    // 写到这些显示设备上面
        mDisplayBinder = mComposerClient->createDisplay(
                String8("foo"), false /* secure */);

        SurfaceComposerClient::openGlobalTransaction();

    // 修改内部DisplayState  定义在LayerState.h当中

    // DisplayState &s(getDisplayStateLocked(token));

    //s.surface = bufferProducer;

    //s.what |= DisplayState::eSurfaceChanged;


        mComposerClient->setDisplaySurface(mDisplayBinder, mSurfaceTexture);

        //Rect layerStackRect(1280, 720);  // XXX fix this.
        Rect layerStackRect(width, height);  // XXX fix this.
        //Rect displayRect(1280, 720);
        Rect displayRect(width, height);

        mComposerClient->setDisplayProjection(
                mDisplayBinder, 0 /* 0 degree rotation */,
                layerStackRect,
                displayRect);

        SurfaceComposerClient::closeGlobalTransaction();
    }

    void RemoteDisplayClient::onDisplayDisconnected() {

        enableAudioSubmix(false /* enable */);
        //Mutex::Autolock autoLock(mLock);
        //mDone = true;
        ALOGD("onDisplayDisconnected");
        //mCondition.broadcast();
    }

    void RemoteDisplayClient::onDisplayError(int32_t error) {
        ALOGI("onDisplayError error=%d", error);

        Mutex::Autolock autoLock(mLock);
        mDone = true;
        mCondition.broadcast();
    }

    void RemoteDisplayClient::onRecordScreen(char *buffer, int len) {
        //JNIEnv* env = AndroidRuntime::getJNIEnv();
        JNIEnv* env = mEnv;
           jbyteArray data =  env->NewByteArray(len);
           env->SetByteArrayRegion(data, 0, len,
               reinterpret_cast<const jbyte*>(buffer));

        ALOGE("### onRecordScreen in android_media_RemoteDisplay.cpp ###");
           env->CallVoidMethod(mRemoteDisplayObjGlobal,
                    gRemoteDisplayClassInfo.notifyRecordScreen, data, len);
           checkAndClearExceptionFromCallback(env, "notifyRecordScreen");
    }

    void RemoteDisplayClient::waitUntilDone() {
        Mutex::Autolock autoLock(mLock);
        while (!mDone) {
            mCondition.wait(mLock);
        }
    }

    class NativeRemoteDisplayEx {
    public:
        NativeRemoteDisplayEx(const sp<IRemoteDisplay>& display,
                const sp<RemoteDisplayClient>& client) :
                mDisplay(display), mClient(client) {
        }

        ~NativeRemoteDisplayEx()
        {
        ALOGI("### ~NativeRemoteDisplayEx 01 ###");
            if(mDisplay != NULL)
            {
        ALOGI("### ~NativeRemoteDisplayEx 02 ###");
                   mDisplay->dispose();
            }
            }

         void pauseRecord()
        {
        ALOGI("### pauseRecord 01 ###");
            if(mDisplay != NULL)
            {
        ALOGI("### pauseRecord 02 ###");
                mDisplay->pause();
            }
            }

         void resumeRecord()
        {
        ALOGI("### resumeRecord 01 ###");   
            if(mDisplay != NULL)
            {
        ALOGI("### resumeRecord 02 ###");   
                    mDisplay->resume();
            }
            }

         void stopRecord()
        {
        ALOGI("### stopRecord 01 ###");   
            if(mDisplay != NULL)
            {
        ALOGI("### stopRecord 02 ###");   
                    mDisplay->dispose();
            }
            }

    private:
        sp<IRemoteDisplay> mDisplay;
        sp<RemoteDisplayClient> mClient;
    };

    static jint nativeStartRecord(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) {
        ScopedUtfChars iface(env, ifaceStr);
        ALOGI("### nativeStartRecord ###");
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("media.player"));
        sp<IMediaPlayerService> service =
            interface_cast<IMediaPlayerService>(binder);

        CHECK(service.get() != NULL);

        enableAudioSubmix(true /* enable */);

        sp<RemoteDisplayClient> client = new RemoteDisplayClient(env, remoteDisplayObj);
        sp<IRemoteDisplay> display = service->listenForRemoteDisplay(client, String8(iface.c_str()));

    #if 0 //{
        if(wrapper != NULL)
        {
            //delete wrapper;
            //wrapper = NULL;
        }
    #endif //}   
          NativeRemoteDisplayEx* wrapper = new NativeRemoteDisplayEx(display, client);

        return reinterpret_cast<jint>(wrapper);
    }

    static jint nativePauseRecord(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
        ALOGI("### nativePauseRecord ###");
      NativeRemoteDisplayEx* wrapper = reinterpret_cast<NativeRemoteDisplayEx*>(ptr);
      wrapper->pauseRecord();
        return 0;
    }

    static jint nativeResumeRecord(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
        ALOGI("### nativeResumeRecord ###");
      NativeRemoteDisplayEx* wrapper = reinterpret_cast<NativeRemoteDisplayEx*>(ptr);
      wrapper->resumeRecord(); 
        return 0;
    }

    static jint nativeStopRecord(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
        ALOGI("### nativeStopRecord ###");
      NativeRemoteDisplayEx* wrapper = reinterpret_cast<NativeRemoteDisplayEx*>(ptr);  
        delete wrapper;
        //wrapper->stopRecord();
        return 0;
    }

    static jint nativeListen(JNIEnv* env, jobject remoteDisplayObj, jstring ifaceStr) {
        ScopedUtfChars iface(env, ifaceStr);

        sp<IServiceManager> sm = defaultServiceManager();
        sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(
                sm->getService(String16("media.player")));
        if (service == NULL) {
            ALOGE("Could not obtain IMediaPlayerService from service manager");
            return 0;
        }

        sp<NativeRemoteDisplayClient> client(new NativeRemoteDisplayClient(env, remoteDisplayObj));
        sp<IRemoteDisplay> display = service->listenForRemoteDisplay(
                client, String8(iface.c_str()));
        if (display == NULL) {
            ALOGE("Media player service rejected request to listen for remote display '%s'.",
                    iface.c_str());
            return 0;
        }

        NativeRemoteDisplay* wrapper = new NativeRemoteDisplay(display, client);
        return reinterpret_cast<jint>(wrapper);
    }

    static void nativeDispose(JNIEnv* env, jobject remoteDisplayObj, jint ptr) {
        NativeRemoteDisplay* wrapper = reinterpret_cast<NativeRemoteDisplay*>(ptr);
        delete wrapper;
    }

    // ----------------------------------------------------------------------------

    static JNINativeMethod gMethods[] = {
        {"nativeListen", "(Ljava/lang/String;)I",
                (void*)nativeListen },
        {"nativeStartRecord", "(Ljava/lang/String;)I",
                (void*)nativeStartRecord },
        {"nativePauseRecord", "(I)I",
                (void*)nativePauseRecord },
        {"nativeResumeRecord", "(I)I",
                (void*)nativeResumeRecord },
        {"nativeStopRecord", "(I)I",
                (void*)nativeStopRecord },           
        {"nativeDispose", "(I)V",
                (void*)nativeDispose },
    };

    int register_android_media_RemoteDisplay(JNIEnv* env)
    {
        int err = AndroidRuntime::registerNativeMethods(env, "android/media/RemoteDisplay",
                gMethods, NELEM(gMethods));

        jclass clazz = env->FindClass("android/media/RemoteDisplay");
        gRemoteDisplayClassInfo.notifyDisplayConnected =
                env->GetMethodID(clazz, "notifyDisplayConnected",
                        "(Landroid/view/Surface;III)V");
        gRemoteDisplayClassInfo.notifyDisplayDisconnected =
                env->GetMethodID(clazz, "notifyDisplayDisconnected", "()V");
        gRemoteDisplayClassInfo.notifyDisplayError =
                env->GetMethodID(clazz, "notifyDisplayError", "(I)V");
        gRemoteDisplayClassInfo.notifyRecordScreen =
                env->GetMethodID(clazz, "notifyRecordScreen", "([BI)V");   
        return err;
    }

    pizzaframeworksasecorejavaandroidhardwaredisplayIDisplayManager.aidl

      DisplayManager负责管理所有的Display对象,给JAVA用户负责使用的接口

    // No permissions required.
    void startScreenRecord(String outfile);

    // No permissions required.
    void pauseScreenRecord();

    // No permissions required.
    void resumeScreenRecord();

    // No permissions required.
    void stopScreenRecord();

    // No permissions required.
    boolean canRecordScreen();

    // No permissions required.
    boolean canUseWfd();

     

    pizzaframeworksaseservicesjavacomandroidserverdisplayDisplayManagerService.java

       public void startScreenRecord(String outfile) {
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mSyncRoot) {
                    if (mWifiDisplayAdapter != null) {
                        mWifiDisplayAdapter.requestStartRecordScreenLocked(outfile);
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override // Binder call
        public void pauseScreenRecord() {
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mSyncRoot) {
                    if (mWifiDisplayAdapter != null) {
                        mWifiDisplayAdapter.requestPauseRecordScreenLocked();
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
        @Override // Binder call
        public void resumeScreenRecord() {
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mSyncRoot) {
                    if (mWifiDisplayAdapter != null) {
                        mWifiDisplayAdapter.requestResumeRecordScreenLocked();
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override // Binder call
        public void stopScreenRecord() {
            final long token = Binder.clearCallingIdentity();
            try {
                synchronized (mSyncRoot) {
                    if (mWifiDisplayAdapter != null) {
                        mWifiDisplayAdapter.requestStopRecordScreenLocked();
                    }
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override // Binder call
        public boolean canRecordScreen() {
            if (mWifiDisplayAdapter != null) {
                return mWifiDisplayAdapter.requestCanRecordScreenLocked();
            }
         return false;
        }

        @Override // Binder call
        public boolean canUseWfd() {
            if (mWifiDisplayAdapter != null) {
                return mWifiDisplayAdapter.requestCanUseWfdLocked();
            }
         return false;
        }

        @Override // Binder call

     

    RemoteDisplay 其被有三个部分WifiDisplayAdapter,WifiDisplayController.java, WifiDisplayDevice集成起来使用。

    pizzaframeworksaseservicesjavacomandroidserverdisplayWifiDisplayAdapter.java

           public void requestStartRecordScreenLocked(final String outfile) {
            if (DEBUG) {
                Slog.d(TAG, "requestStartRecordScreenLocked");
            }

            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    if (mDisplayController != null) {
                        mDisplayController.requestStartRecordScreen(outfile);
                    }
                }
            });
        }

           public void requestPauseRecordScreenLocked() {
            if (DEBUG) {
                Slog.d(TAG, "requestPauseRecordScreenLocked");
            }

            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    if (mDisplayController != null) {
                        mDisplayController.requestPauseRecordScreen();
                    }
                }
            });
        }

           public void requestResumeRecordScreenLocked() {
            if (DEBUG) {
                Slog.d(TAG, "requestResumeRecordScreenLocked");
            }

            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    if (mDisplayController != null) {
                        mDisplayController.requestResumeRecordScreen();
                    }
                }
            });
        }

           public void requestStopRecordScreenLocked() {
            if (DEBUG) {
                Slog.d(TAG, "requestStopRecordScreenLocked");
            }

            getHandler().post(new Runnable() {
                @Override
                public void run() {
                    if (mDisplayController != null) {
                        mDisplayController.requestStopRecordScreen();
                    }
                }
            });
        }

           public boolean requestCanRecordScreenLocked() {
                    if (mDisplayController != null) {
                        return mDisplayController.requestCanRecordScreen();
                    }
              return false;
        }

           public boolean requestCanUseWfdLocked() {
                    if (mDisplayController != null) {
                        return mDisplayController.requestCanUseWfd();
                    }
              return false;
        }

    pizzaframeworksaseservicesjavacomandroidserverdisplayWifiDisplayController.java

    private static final int RECSCR_STATUS_UNKNOWN = -1;
    private static final int RECSCR_STATUS_RECORDING = 1;
    private static final int RECSCR_STATUS_PAUSED = 2;
    private static final int RECSCR_STATUS_STOPPED = 3;   

    private RemoteDisplay mRecordScreen;

        public void requestStartRecordScreen(String outfile) {
            if(RECSCR_STATUS_UNKNOWN == mRecordStatus || RECSCR_STATUS_STOPPED == mRecordStatus)
            {
                if(mRemoteDisplay != null)
                {
                    Slog.e(TAG, "### requestStartRecordScreen mRemoteDisplay != null ###");
                    return;
                }
                Slog.d(TAG, "### requestStartRecordScreen outfile: " + outfile + " ###");
                    mRecordScreen = RemoteDisplay.recordScreen(outfile, new RemoteDisplay.Listener() {
                            @Override
                            public void onDisplayConnected(Surface surface,
                                    int width, int height, int flags) {
                                Slog.d(TAG, "### onDisplayConnected ###");
                            }

                            @Override
                            public void onDisplayDisconnected() {
                                   Slog.d(TAG, "### onDisplayDisconnected ###");
                            }

                            @Override
                            public void onDisplayError(int error) {
                                Slog.d(TAG, "### onDisplayError ###");                       
                            }

                            @Override
                            public void onRecordScreen(byte[] buffer, int len) {
                                Slog.d(TAG, "### onRecordScreen ###");
                            }
                        }, mHandler);
                    mHandler.postDelayed(mRtspTimeout, RTSP_TIMEOUT_SECONDS * 1000  * 1000);
            mRecordStatus = RECSCR_STATUS_RECORDING;
            }
        }

        public void requestPauseRecordScreen() {
            if(RECSCR_STATUS_RECORDING == mRecordStatus && mRecordScreen != null)
            {
                Slog.d(TAG, "### requestPauseRecordScreen ###");
                mRecordScreen.pauseRecording();
                mRecordStatus = RECSCR_STATUS_PAUSED;
            }
        }

        public void requestResumeRecordScreen() {
            if(RECSCR_STATUS_PAUSED == mRecordStatus && mRecordScreen != null)
            {
                Slog.d(TAG, "### requestResumeRecordScreen ###");
                mRecordScreen.resumeRecording();
                mRecordStatus = RECSCR_STATUS_RECORDING;
            }
        }

        public void requestStopRecordScreen() {
            if(RECSCR_STATUS_RECORDING == mRecordStatus && mRecordScreen != null)
            {
                Slog.d(TAG, "### requestStopRecordScreen ###");
                mRecordScreen.stopRecording();
                mRecordStatus = RECSCR_STATUS_STOPPED;
                mRecordScreen = null;
            }       
        }

        public boolean requestCanRecordScreen() {
            Slog.d(TAG, "### requestCanRecordScreen ###");
            if(mRemoteDisplay == null)
            {
                Slog.d(TAG, "### requestCanRecordScreen true ###");
                return true;
            }
            return false;
        }

        public boolean requestCanUseWfd() {
            Slog.d(TAG, "### requestCanUseWfd ###");
            if(mRecordScreen == null)
            {
                Slog.d(TAG, "### requestCanUseWfd true ###");
                return true;
            }
            return false;
        }

  • 相关阅读:
    mysql 使用 insert ignore into和unique实现不插入重复数据功能
    mysql 判断指定条件数据存不存在,不存在则插入
    Unity3D之如何将包大小减少到极致
    Unity3D–Texture图片空间和内存占用分析
    使用Unity3D的50个技巧:Unity3D最佳实践!
    Unity中的Path对应各平台中的Path
    unity 在移动平台中,文件操作路径详解
    unity Mathf 数学运算汇总
    解决ngui在3d场景中 点透的情况
    【整理】unity3d优化总结篇
  • 原文地址:https://www.cnblogs.com/pengxinglove/p/5550933.html
Copyright © 2011-2022 走看看