ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Files at this revision

API Documentation at this revision

Comitter:
TMBOY
Date:
Tue Jul 18 16:34:48 2017 +0800
Parent:
44:c1d8923072ba
Child:
46:183cfc59d4e4
Commit message:
?

Changed in this revision

dcs-sdk-java-master/.gitignore Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/LICENSE.txt Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/README.md Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/.gitignore Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/build.gradle Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/libs/commons-fileupload-1.3.2.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/libs/commons-io-2.5.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/libs/commons-lang3-3.4.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/libs/jackson-core-asl-1.9.13.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/libs/jackson-mapper-asl-1.9.13.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/proguard-rules.pro Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/AndroidManifest.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/assets/alarm.mp3 Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/cpp/Interface.h Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/cpp/wakeup.cpp Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleApplication.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleBaseActivity.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleMainActivity.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleOAuthActivity.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleScreenHtmlActivity.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/AudioRecordThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/HandlerImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/PlatformFactoryImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/alert/AlertsFileDataStoreImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/playbackcontroller/IPlaybackControllerImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStoreThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStreamStoreImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/IAudioStreamStore.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerPreferenceUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpDecodeThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpNative.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/webview/BaseWebView.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertHandler.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertScheduler.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertsDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/Alert.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertsStatePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/DeleteAlertPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/SetAlertPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/AudioPlayerDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/AudioPlayerPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/ClearQueuePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlayPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackFailedPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStatePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStutterFinishedPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/StopPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayStateReport.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerProgressReporter.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerTimer.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/PlaybackControllerDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ScreenDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/HtmlPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/LinkClickedPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/SpeakerControllerDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/AdjustVolumePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/MuteChangedPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetMutePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetVolumePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/VolumeStatePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/HandleDirectiveException.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/SystemDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ExceptionEncounteredPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/SetEndPointPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ThrowExceptionPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/UserInactivityReportPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/VoiceInputDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenStartedPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/ApiConstants.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/VoiceOutputDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeakPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeechLifecyclePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/VoiceOutputStatePayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseDeviceModule.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseMultiChannelMediaPlayer.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsClient.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsFramework.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsResponseDispatcher.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DeviceModuleFactory.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DialogRequestIdHandler.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IMessageSender.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IResponseListener.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/PauseStrategyMultiChannelMediaPlayer.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/AudioData.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/BaseBlockResponseThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsJsonProcessingException.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsResponseBodyEnqueue.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/MultipartParser.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/Parser.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithDialogIdBlockThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithoutDialogIdBlockThread.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/heartbeat/HeartBeat.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/AttachedContentPayload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/BaseMessage.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/ClientContext.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsRequestBody.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsResponseBody.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsStreamRequestBody.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DialogRequestIdHeader.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Directive.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Event.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Header.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/MessageIdHeader.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Payload.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/PayloadConfig.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/DcsHttpManager.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpConfig.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpRequestInterface.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpMediaType.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpRequestImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/GetBuilder.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/HasParamInterface.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/OkHttpRequestBuilder.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostMultipartBuilder.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostStringBuilder.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/DcsCallback.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/ResponseCallback.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StreamDcsCallback.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StringDcsCallback.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/exceptions/Exceptions.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/LoggingInterceptor.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/RetryInterceptor.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/GetRequest.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/OkHttpRequest.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostMultipartRequest.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostStringRequest.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/RequestCall.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/utils/Platform.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/AccessTokenManager.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialog.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialogError.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduException.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduOauthImplicitGrant.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/IOauth.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthConfig.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthImpl.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthNetUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthPreferenceUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAlertsDataStore.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioInput.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioRecord.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IHandler.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IMediaPlayer.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlatformFactory.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlaybackController.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWakeUp.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWebView.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/CommonUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/DateFormatterUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/FileUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/LogUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/NetWorkUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/ObjectMapperUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/PreferenceUtil.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/wakeup/WakeUp.java Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEASRAndroid.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEasrS1MergeNormal.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEASRAndroid.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEasrS1MergeNormal.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEASRAndroid.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEasrS1MergeNormal.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEASRAndroid.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEasrS1MergeNormal.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEASRAndroid.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEasrS1MergeNormal.so Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/drawable/btn_bg.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_main.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth_login.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_screen_html.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/mipmap-hdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/mipmap-mdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/mipmap-xhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/values/colors.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/values/strings.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/app/src/main/res/values/styles.xml Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/build.gradle Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/gradle.properties Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.jar Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.properties Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/gradlew Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/gradlew.bat Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/access-architecture.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/client-id-secret.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/login1.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/login2.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/modify-client-id.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/project.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/sdk-architecture.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/images/wakeup.png Show annotated file Show diff for this revision Revisions of this file
dcs-sdk-java-master/settings.gradle Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/.gitignore	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,55 @@
+# Built application files
+*.apk
+*.ap_
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# Intellij
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/dictionaries
+.idea/libraries
+
+# Keystore files
+*.jks
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+
+# Google Services (e.g. APIs or Firebase)
+google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/LICENSE.txt	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/README.md	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+# DCS SDK(Java)开发者指南
+
+## DCS协议
+
+DCS协议是DuerOS服务端与设备端之间的通讯协议,是一套把DuerOS的智能语音交互能力向所有设备开放的API,了解详情请看[DCS协议文档](http://developer.dueros.baidu.com/doc/dueros-conversational-service/introduction_markdown)。
+
+## 摘要
+
+DCS SDK提供DCS协议在设备端的实现,旨在降低设备接入DuerOS的开发成本。DCS SDK是完整的Sample App,可以直接在目标设备运行,并且源代码全部开源,开发者可以基于源码进行二次开发。
+
+本文档介绍的DCS SDK(Java)是Java版本的实现,该版本目前支持Android系统。
+
+## 1-前置条件
+
+a.完成注册百度账号、开发者认证和产品创建(选择手机场景和Android平台)后,请保存client_id和client_secret
+
+![](images/client-id-secret.png)
+
+具体参考[控制台接入流程](http://developer.dueros.baidu.com/doc/overall/console-guide_markdown)。
+
+b.在百度开发者中心配置OAuth的授权回调页
+  1. 到DuerOS开放平台控制台: http://developer.dueros.baidu.com/openduer/product/getproduct
+  2. 点击所创建产品的“编辑”按钮,按钮在右侧
+  3. 点击OAUTH CONFIG URL,到百度开发者平台控制台
+  4. 在开发者平台控制台,点击左侧“安全设置”
+  5. 在“授权回调页”输入框中输入"bdconnect://cancel,bdconnect://success"(不带双引号)
+  6. 点击页面下方“确定”按钮
+
+c.开发环境
+  - Android Studio 2.2+
+  - Gradle 2.2+
+  - Android SDK 5.0+ (支持http/2)
+  - JDK 1.6+
+
+## 2-克隆项目
+
+```shell
+git clone https://github.com/dueros/dcs-sdk-java.git
+```
+
+## 3-运行
+
+a.通过Android Studio找到DcsSampleOAuthActivity.java,利用上述client_id进行替换
+
+![](images/modify-client-id.png)  
+
+b.运行(Android真机)
+
+![](images/login1.png)
+
+c.百度账号登录
+
+![](images/login2.png)
+
+## 4-唤醒
+
+说“小度小度”,成功唤醒后进入“录音中”状态,如下图:
+
+![](images/wakeup.png)
+
+## 5-和小度对话
+
+a.通过唤醒或者单击“点击说话”进入录音状态, 问“北京天气怎么样”,DuerOS后端将发送stopListen指令,同时返回speak指令,播报北京天气。
+
+b.问“播放刘若英的歌”, 返回play指令播放歌,可以从界面上进行“播放”、“暂停”、“上一首”和“下一首”操作。
+
+## 6 SDK结构
+
+![](images/sdk-architecture.png)
+
+![](images/access-architecture.png)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/.gitignore	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,44 @@
+# Built application files
+*.apk
+*.ap_
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
+.gradle/
+build
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# Intellij
+*.iml
+.idea/*
+
+# Keystore files
+*.jks
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.idea/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/CMakeLists.txt	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,30 @@
+#指定CMake的最小版本
+cmake_minimum_required(VERSION 3.4.1)
+
+set(libs_DIR src/main/jniLibs/${ANDROID_ABI})
+
+set(libs_include_DIR src/main/cpp)
+
+#确保 CMake 可以在编译时定位您的标头文件以及源文件
+include_directories(${lib_include_DIR})
+
+link_directories(${libs_DIR})
+
+#添加我们自己的模块,名字是wakeup,SHARED可分享的,以及配置源文件或者头文件的路径
+add_library( wakeup
+             SHARED
+             src/main/cpp/wakeup.cpp
+             src/main/cpp/Interface.h
+           )
+#找到log这个模块
+find_library(log-lib
+              log
+            )
+#把我们自己的模块和动态库bdEASRAndroid模块,找到log这个模块,关联起来
+target_link_libraries(wakeup
+                      bdEASRAndroid
+                      ${log-lib}
+                      )
+
+# 注意:bdEASRAndroid so库不要带版本号 比如:bdEASRAndroid.v1.10.10
+# jniLibs 里面也不要带版本号
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/build.gradle	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,73 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 25
+    buildToolsVersion "25.0.2"
+    defaultConfig {
+        applicationId "com.baidu.duer.dcs"
+        minSdkVersion 21
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        externalNativeBuild {
+            cmake {
+                cppFlags "-std=c++11 -frtti -fexceptions -I/src/main/cpp"
+            }
+        }
+        ndk {
+            // 平台
+            abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a'
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "CMakeLists.txt"
+        }
+    }
+    sourceSets {
+        main {
+            jniLibs.srcDirs = ['src/main/jniLibs']
+        }
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    packagingOptions {
+        exclude 'META-INF/DEPENDENCIES.txt'
+        exclude 'META-INF/LICENSE.txt'
+        exclude 'META-INF/NOTICE.txt'
+        exclude 'META-INF/NOTICE'
+        exclude 'META-INF/LICENSE'
+        exclude 'META-INF/DEPENDENCIES'
+        exclude 'META-INF/notice.txt'
+        exclude 'META-INF/license.txt'
+        exclude 'META-INF/dependencies.txt'
+        exclude 'META-INF/LGPL2.1'
+        exclude 'META-INF/ASL2.0'
+    }
+}
+
+dependencies {
+    compile fileTree(include: ['*.jar'], dir: 'libs')
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    compile 'com.android.support:appcompat-v7:25.3.0'
+    compile 'com.android.support:design:25.3.0'
+    testCompile 'junit:junit:4.12'
+    compile files('libs/jackson-core-asl-1.9.13.jar')
+    compile files('libs/jackson-mapper-asl-1.9.13.jar')
+    compile files('libs/commons-fileupload-1.3.2.jar')
+    compile files('libs/commons-lang3-3.4.jar')
+    compile files('libs/commons-io-2.5.jar')
+    def okHttp3Version = '3.8.1'
+    compile('com.squareup.okhttp3:okhttp:' + okHttp3Version)
+    compile('com.squareup.okhttp3:logging-interceptor:' + okHttp3Version)
+
+    // debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
+}
Binary file dcs-sdk-java-master/app/libs/commons-fileupload-1.3.2.jar has changed
Binary file dcs-sdk-java-master/app/libs/commons-io-2.5.jar has changed
Binary file dcs-sdk-java-master/app/libs/commons-lang3-3.4.jar has changed
Binary file dcs-sdk-java-master/app/libs/jackson-core-asl-1.9.13.jar has changed
Binary file dcs-sdk-java-master/app/libs/jackson-mapper-asl-1.9.13.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/proguard-rules.pro	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in D:\AppData\android-sdk-windows/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/AndroidManifest.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.baidu.duer.dcs">
+
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <application
+        android:name="com.baidu.duer.dcs.androidapp.DcsSampleApplication"
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+
+        <activity
+            android:name="com.baidu.duer.dcs.androidapp.DcsSampleOAuthActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name="com.baidu.duer.dcs.androidapp.DcsSampleMainActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme.NoActionBar" />
+        <activity
+            android:name="com.baidu.duer.dcs.androidapp.DcsSampleScreenHtmlActivity"
+            android:label="@string/app_name"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppTheme.NoActionBar" />
+    </application>
+
+</manifest>
Binary file dcs-sdk-java-master/app/src/main/assets/alarm.mp3 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/cpp/Interface.h	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,107 @@
+
+#ifndef _EASR_INTERFACE_
+#define _EASR_INTERFACE_
+
+int GetEngineVersion();
+int SetLogLevel(int level);
+int SetTimeLogFile(const char* fn);
+int SetSampleRateMode(int mode);
+bool ExistFile(const char* file);
+int GetDataDate(const char* fn);
+int GetResLine(const char* fn);
+int GetResVersion(const char* fn);
+bool CheckDataMD5(const char* fn);
+int DisableSSE4();
+
+int ClearRes();
+int Free();
+int Initial();
+int Initial(const char* dictFile, const char* userFile, const char* mmfFile, const char* hmmMapFile,
+            short acoustic_model_mode=1,bool fastMode=false);
+int BuildNet(int netTreeID,const char* synFile);
+int WriteWdNonPron(const char* outFile);
+
+int BuildSlot(char* buffer,long len);
+int ReadSlot(const char* slotFile);
+int ReadSlotLink(const char* slotLinkFile);
+int ReadLM(const char* lmFn,const char* slotName,bool needBuildSlot);
+int LoadRes(const char* lmFn,const char* lmSlotName,const char* slotFile,const char* slotLinkFile);
+
+int SetVADEndCut(int id,bool vadEdForCut);
+int InitialDecoder(int id,int vadID,int nBeam,double prunThres);
+int ResetDecoder(int id);
+int SetCurrNetTreeID(int id,int treeID,int mode=0);
+int Fep(int id,short* data, int dataLen, bool bEd);
+int Rec(int id, char** senArr, int expectNum);
+char* GetImmeSentence(int id,int& frame);
+
+char* DecodeAlways(int id,short* data, int dataLen, bool bEd);
+
+int InitialMem();
+int InitialVAD(int id,float max_speech_len,float max_speech_pause_len);
+int ResetVAD(int id);
+int VADDetect(int id,short* data, int dataLen, bool bEd);
+int GetVadSt(int id);
+int GetVadEd(int id);
+long int get_dect_end_point_time(int id);
+
+int KWSSetParam(int type,float value);
+int KWSInitial(const char* kwdSynStr,const char* sFile,const char* resDir,int mode = 0);
+int KWSReset(int* sceneArr,int n);
+int KWSDecode(short* data, int dataLen, char** kwdArr, int expectNum, bool bEd);
+int KWSDecode(short* data, int dataLen, char* outJsonStr, bool bEd);
+int KWSFree();
+
+int AudioSegReset();
+int AudioSegFree();
+int AudioSegInitial(const char* sFile,int mode=0);
+int AudioSegDetect(short* data, int dataLen, bool bEd, int& spSt, int& spEd);
+int AudioSegDetect(short* data, int dataLen, bool bEd, int& spSt, int& spEd, int *pauseEd);
+float AudioSeggetSilConfidence(int contextLen);
+int setParam(int function, int type, float value); //function: 1 = audioSeg
+int AudioSegGetDelayFrameNum(); 
+
+int WakeUpInitial(const char* wakeUpWd,const char* sFile,int mode=0);
+int WakeUpReset();
+int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, bool bEd);
+int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, int &wakeword_frame_len, bool bEd);
+int WakeUpDecode(short* data, int dataLen, char** senArr, int expectNum, int &wakeword_frame_len,
+        bool &is_confidence, int &voice_offset, bool bEd);
+int WakeUpFree();
+int WakeUpSetEnvironment(int status);//0 is quiet,else is noise
+
+int AECInit();
+int AECReset();
+short* AECProcess(short* data_in,short* wav_ref,long len_in);
+int AECExit();
+
+int GetPyED(const char* str1,const char* str2);
+int GetStateED(const char* str1,const char* str2);
+
+extern char* ChnNameSegPreProcess(const char* aNameArr,const char* aResFileName);
+extern char* EngNamePronPreProcess(const char* aNameArr);
+
+int SetLicenseFlag(bool lic_flag);
+bool GetLicenseFlag();
+
+#ifdef _ANDROID_
+#include <jni.h>
+int GetLicense(JNIEnv *env, jclass obj,jobject context,jstring appCode,jstring cuid,jstring stat,jstring license_file);
+int VerifyLicense(JNIEnv *env,jobject context,jstring appCode,jstring cuid,jbyteArray license,jint len,jbyteArray appIDSeq,jstring logDir);
+#else
+#ifdef _IOS_
+int GetLicense(const char* appCode,const char* stat,const char* license_file);
+int VerifyLicense(const char* appCode,const char* license,int len,unsigned int& appID,const char* logDir);
+#else //x86
+int GetLicense(const char* appName,const char* appCode,const char* stat,const char* license_file);
+int VerifyLicense(const char* appName,const char* appCode,const char* license,int len,unsigned int& appID,const char* logDir);
+#endif
+#endif
+int OpenPVUpload();
+int ClosePVUpload();
+int GetTestAuthorize();
+int GetLongAuthorize();
+bool GetAuthorize();
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/cpp/wakeup.cpp	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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.
+ */
+/**
+ * 唤醒调用底层so库实现-jni
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+#include <jni.h>
+#include "Interface.h"
+#include <android/log.h>
+
+#define LOG_TAG "wakeup"
+#define LOG_D(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpInitial(JNIEnv *env,
+                                                                            jobject instance,
+                                                                            jstring wakeUpWd_,
+                                                                            jstring sFile_,
+                                                                            jint mode) {
+    const char *wakeUpWd = env->GetStringUTFChars(wakeUpWd_, 0);
+    const char *sFile = env->GetStringUTFChars(sFile_, 0);
+
+    int _mode = mode;
+    // 打开log
+    // SetLogLevel(5);
+    LOG_D("WakeUpInitial wakeUpWd=%s", wakeUpWd);
+    LOG_D("WakeUpInitial sFile_=%s", sFile);
+    int ret = WakeUpInitial(wakeUpWd, sFile, _mode);
+    LOG_D("WakeUpInitial ret=%d", ret);
+
+    env->ReleaseStringUTFChars(wakeUpWd_, wakeUpWd);
+    env->ReleaseStringUTFChars(sFile_, sFile);
+
+    return ret;
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpReset(JNIEnv *env,
+                                                                          jobject instance) {
+    return WakeUpReset();
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpDecode(JNIEnv *env,
+                                                                           jobject instance,
+                                                                           jshortArray data_,
+                                                                           jint dataLen,
+                                                                           jstring senArr_,
+                                                                           jint expectNum,
+                                                                           jint wakeWord_frame_len,
+                                                                           jboolean is_confidence,
+                                                                           jint voice_offset,
+                                                                           jboolean bEd) {
+
+
+    jboolean isCopy = 0;
+    short *data_invoke = env->GetShortArrayElements(data_, &isCopy);
+
+    // 写入文件
+    // FILE *file = fopen("/storage/emulated/0/222.pcm", "ab+");
+    // fwrite(data_invoke, sizeof(short) * dataLen, 1, file);
+    // fclose(file);
+
+    LOG_D("WakeUpDecode data_ GetArrayLength=%d", env->GetArrayLength(data_));
+
+    int dataLen_invoke = dataLen;
+    // 因为so库里面最大为2560
+    char *senArr = new char[2560];
+    int expectNum_invoke = expectNum;
+    int wakeWord_frame_len_invoke = wakeWord_frame_len;
+    bool is_confidence_invoke = is_confidence;
+    int voice_offset_invoke = voice_offset;
+    bool bEd_invoke = bEd;
+
+    LOG_D("WakeUpDecode dataLen_invoke=%d", dataLen_invoke);
+    LOG_D("WakeUpDecode expectNum_invoke=%d", expectNum_invoke);
+    LOG_D("WakeUpDecode wakeWord_frame_len_invoke=%d", wakeWord_frame_len_invoke);
+    LOG_D("WakeUpDecode is_confidence_invoke=%d", is_confidence_invoke);
+    LOG_D("WakeUpDecode bEd_invoke=%d", bEd_invoke);
+
+
+    int ret = WakeUpDecode(data_invoke,
+                           dataLen_invoke,
+                           &senArr,
+                           expectNum_invoke,
+                           wakeWord_frame_len_invoke,
+                           is_confidence_invoke,
+                           voice_offset_invoke,
+                           bEd_invoke
+    );
+
+    LOG_D("WakeUpDecode ret=%d", ret);
+    LOG_D("WakeUpDecode senArr=%s", senArr);
+    LOG_D("WakeUpDecode wakeWord_frame_len_invoke=%d", wakeWord_frame_len_invoke);
+    LOG_D("WakeUpDecode is_confidence_invoke=%d", is_confidence_invoke);
+    LOG_D("WakeUpDecode voice_offset_invoke=%d", voice_offset_invoke);
+
+    // 释放内存资源
+    env->ReleaseShortArrayElements(data_, data_invoke, 0);
+    env->ReleaseStringUTFChars(senArr_, senArr);
+    return ret;
+}
+
+extern "C"
+JNIEXPORT jint JNICALL
+Java_com_baidu_duer_dcs_androidsystemimpl_wakeup_WakeUpNative_wakeUpFree(JNIEnv *env,
+                                                                         jobject instance) {
+    LOG_D("WakeUpFree");
+    return WakeUpFree();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleApplication.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidapp;
+
+import android.app.Application;
+
+/**
+ * DcsSample application
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/11.
+ */
+public class DcsSampleApplication extends Application {
+    private static volatile DcsSampleApplication instance = null;
+
+    public void onCreate() {
+        super.onCreate();
+        instance = this;
+        // LeakCanary.install(this);
+    }
+
+    public static DcsSampleApplication getInstance() {
+        return instance;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleBaseActivity.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidapp;
+
+import android.app.Activity;
+
+/**
+ * 基础base activity
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleBaseActivity extends Activity {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleMainActivity.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidapp;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.webkit.WebView;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.androidsystemimpl.PlatformFactoryImpl;
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.devicemodule.voiceinput.VoiceInputDeviceModule;
+import com.baidu.duer.dcs.framework.DcsFramework;
+import com.baidu.duer.dcs.framework.DeviceModuleFactory;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.oauth.api.IOauth;
+import com.baidu.duer.dcs.oauth.api.OauthImpl;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.NetWorkUtil;
+import com.baidu.duer.dcs.wakeup.WakeUp;
+
+import java.io.File;
+
+/**
+ * 主界面 activity
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleMainActivity extends DcsSampleBaseActivity implements View.OnClickListener {
+    public static final String TAG = "DcsDemoActivity";
+    private Button voiceButton;
+    private TextView textViewTimeStopListen;
+    private Button pauseOrPlayButton;
+    private BaseWebView webView;
+    private LinearLayout mTopLinearLayout;
+    private DcsFramework dcsFramework;
+    private DeviceModuleFactory deviceModuleFactory;
+    private IPlatformFactory platformFactory;
+    private boolean isPause = true;
+    private long startTimeStopListen;
+    private boolean isStopListenReceiving;
+    private String mHtmlUrl;
+    // 唤醒
+    private WakeUp wakeUp;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.dcs_sample_activity_main);
+        initView();
+        initOauth();
+        initFramework();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        initOauth();
+    }
+
+    private void initView() {
+        Button openLogBtn = (Button) findViewById(R.id.openLogBtn);
+        openLogBtn.setOnClickListener(this);
+        voiceButton = (Button) findViewById(R.id.voiceBtn);
+        voiceButton.setOnClickListener(this);
+
+        textViewTimeStopListen = (TextView) findViewById(R.id.id_tv_time_0);
+        mTopLinearLayout = (LinearLayout) findViewById(R.id.topLinearLayout);
+
+        webView = new BaseWebView(DcsSampleMainActivity.this.getApplicationContext());
+        webView.setWebViewClientListen(new BaseWebView.WebViewClientListener() {
+            @Override
+            public BaseWebView.LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url) {
+                // 拦截处理不让其点击
+                return BaseWebView.LoadingWebStatus.STATUS_TRUE;
+            }
+
+            @Override
+            public void onPageStarted(WebView view, String url, Bitmap favicon) {
+
+            }
+
+            @Override
+            public void onPageFinished(WebView view, String url) {
+                if (!url.equals(mHtmlUrl) && !"about:blank".equals(mHtmlUrl)) {
+                    platformFactory.getWebView().linkClicked(url);
+                }
+
+                mHtmlUrl = url;
+            }
+
+            @Override
+            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+
+            }
+        });
+        mTopLinearLayout.addView(webView);
+        webView.loadUrl("about:blank");
+
+        Button mPreviousSongBtn = (Button) findViewById(R.id.previousSongBtn);
+        pauseOrPlayButton = (Button) findViewById(R.id.pauseOrPlayBtn);
+        Button mNextSongBtn = (Button) findViewById(R.id.nextSongBtn);
+        mPreviousSongBtn.setOnClickListener(this);
+        pauseOrPlayButton.setOnClickListener(this);
+        mNextSongBtn.setOnClickListener(this);
+    }
+
+    private void initFramework() {
+        platformFactory = new PlatformFactoryImpl(this);
+        platformFactory.setWebView(webView);
+        dcsFramework = new DcsFramework(platformFactory);
+        deviceModuleFactory = dcsFramework.getDeviceModuleFactory();
+
+        deviceModuleFactory.createVoiceOutputDeviceModule();
+        deviceModuleFactory.createVoiceInputDeviceModule();
+        deviceModuleFactory.getVoiceInputDeviceModule().addVoiceInputListener(
+                new VoiceInputDeviceModule.IVoiceInputListener() {
+                    @Override
+                    public void onStartRecord() {
+                        LogUtil.d(TAG, "onStartRecord");
+                        startRecording();
+                    }
+
+                    @Override
+                    public void onFinishRecord() {
+                        LogUtil.d(TAG, "onFinishRecord");
+                        stopRecording();
+                    }
+
+                    public void onSucceed(int statusCode) {
+                        LogUtil.d(TAG, "onSucceed-statusCode:" + statusCode);
+                        if (statusCode != 200) {
+                            stopRecording();
+                            Toast.makeText(DcsSampleMainActivity.this,
+                                    getResources().getString(R.string.voice_err_msg),
+                                    Toast.LENGTH_SHORT)
+                                    .show();
+                        }
+                    }
+
+                    @Override
+                    public void onFailed(String errorMessage) {
+                        LogUtil.d(TAG, "onFailed-errorMessage:" + errorMessage);
+                        stopRecording();
+                        Toast.makeText(DcsSampleMainActivity.this,
+                                getResources().getString(R.string.voice_err_msg),
+                                Toast.LENGTH_SHORT)
+                                .show();
+                    }
+                });
+
+        deviceModuleFactory.createAlertsDeviceModule();
+
+        deviceModuleFactory.createAudioPlayerDeviceModule();
+        deviceModuleFactory.getAudioPlayerDeviceModule().addAudioPlayListener(
+                new IMediaPlayer.SimpleMediaPlayerListener() {
+                    @Override
+                    public void onPaused() {
+                        super.onPaused();
+                        pauseOrPlayButton.setText(getResources().getString(R.string.audio_paused));
+                        isPause = true;
+                    }
+
+                    @Override
+                    public void onPlaying() {
+                        super.onPlaying();
+                        pauseOrPlayButton.setText(getResources().getString(R.string.audio_playing));
+                        isPause = false;
+                    }
+
+                    @Override
+                    public void onCompletion() {
+                        super.onCompletion();
+                        pauseOrPlayButton.setText(getResources().getString(R.string.audio_default));
+                        isPause = false;
+                    }
+
+                    @Override
+                    public void onStopped() {
+                        super.onStopped();
+                        pauseOrPlayButton.setText(getResources().getString(R.string.audio_default));
+                        isPause = true;
+                    }
+                });
+
+        deviceModuleFactory.createSystemDeviceModule();
+        deviceModuleFactory.createSpeakControllerDeviceModule();
+        deviceModuleFactory.createPlaybackControllerDeviceModule();
+        deviceModuleFactory.createScreenDeviceModule();
+
+        // init唤醒
+        wakeUp = new WakeUp(platformFactory.getWakeUp(),
+                platformFactory.getAudioRecord());
+        wakeUp.addWakeUpListener(wakeUpListener);
+        // 开始录音,监听是否说了唤醒词
+        wakeUp.startWakeUp();
+    }
+
+    private IWakeUp.IWakeUpListener wakeUpListener = new IWakeUp.IWakeUpListener() {
+        @Override
+        public void onWakeUpSucceed() {
+            Toast.makeText(DcsSampleMainActivity.this,
+                    getResources().getString(R.string.wakeup_succeed),
+                    Toast.LENGTH_SHORT)
+                    .show();
+            voiceButton.performClick();
+        }
+    };
+
+    private void doUserActivity() {
+        deviceModuleFactory.getSystemProvider().userActivity();
+    }
+
+    private void initOauth() {
+        IOauth baiduOauth = new OauthImpl();
+        if (baiduOauth.isSessionValid()) {
+            HttpConfig.setAccessToken(baiduOauth.getAccessToken());
+        } else {
+            baiduOauth.authorize();
+        }
+    }
+
+    private void stopRecording() {
+        wakeUp.startWakeUp();
+        isStopListenReceiving = false;
+        voiceButton.setText(getResources().getString(R.string.stop_record));
+        long t = System.currentTimeMillis() - startTimeStopListen;
+        textViewTimeStopListen.setText(getResources().getString(R.string.time_record, t));
+    }
+
+    private void startRecording() {
+        wakeUp.stopWakeUp();
+        isStopListenReceiving = true;
+        deviceModuleFactory.getSystemProvider().userActivity();
+        voiceButton.setText(getResources().getString(R.string.start_record));
+        textViewTimeStopListen.setText("");
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.voiceBtn:
+                if (!NetWorkUtil.isNetworkConnected(this)) {
+                    Toast.makeText(this,
+                            getResources().getString(R.string.err_net_msg),
+                            Toast.LENGTH_SHORT).show();
+                    return;
+                }
+                if (CommonUtil.isFastDoubleClick()) {
+                    return;
+                }
+                if (isStopListenReceiving) {
+                    platformFactory.getVoiceInput().stopRecord();
+                    isStopListenReceiving = false;
+                    return;
+                }
+                isStopListenReceiving = true;
+                startTimeStopListen = System.currentTimeMillis();
+                platformFactory.getVoiceInput().startRecord();
+                doUserActivity();
+                break;
+            case R.id.openLogBtn:
+                openAssignFolder(FileUtil.getLogFilePath());
+                break;
+            case R.id.previousSongBtn:
+                platformFactory.getPlayback().previous(nextPreResponseListener);
+                doUserActivity();
+                break;
+            case R.id.nextSongBtn:
+                platformFactory.getPlayback().next(nextPreResponseListener);
+                doUserActivity();
+                break;
+            case R.id.pauseOrPlayBtn:
+                if (isPause) {
+                    platformFactory.getPlayback().play(playPauseResponseListener);
+                } else {
+                    platformFactory.getPlayback().pause(playPauseResponseListener);
+                }
+                doUserActivity();
+                break;
+            default:
+                break;
+        }
+    }
+
+    private IResponseListener playPauseResponseListener = new IResponseListener() {
+        @Override
+        public void onSucceed(int statusCode) {
+            if (statusCode == 204) {
+                Toast.makeText(DcsSampleMainActivity.this,
+                        getResources().getString(R.string.no_directive),
+                        Toast.LENGTH_SHORT)
+                        .show();
+            }
+        }
+
+        @Override
+        public void onFailed(String errorMessage) {
+            Toast.makeText(DcsSampleMainActivity.this,
+                    getResources().getString(R.string.request_error),
+                    Toast.LENGTH_SHORT)
+                    .show();
+        }
+    };
+
+    private IResponseListener nextPreResponseListener = new IResponseListener() {
+        @Override
+        public void onSucceed(int statusCode) {
+            if (statusCode == 204) {
+                Toast.makeText(DcsSampleMainActivity.this,
+                        getResources().getString(R.string.no_audio),
+                        Toast.LENGTH_SHORT)
+                        .show();
+            }
+        }
+
+        @Override
+        public void onFailed(String errorMessage) {
+            Toast.makeText(DcsSampleMainActivity.this,
+                    getResources().getString(R.string.request_error),
+                    Toast.LENGTH_SHORT)
+                    .show();
+        }
+    };
+
+    /**
+     * 打开日志
+     *
+     * @param path 文件的绝对路径
+     */
+    private void openAssignFolder(String path) {
+        File file = new File(path);
+        if (!file.exists()) {
+            Toast.makeText(DcsSampleMainActivity.this,
+                    getResources().getString(R.string.no_log),
+                    Toast.LENGTH_SHORT)
+                    .show();
+            return;
+        }
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setDataAndType(Uri.fromFile(file), "text/plain");
+        try {
+            startActivity(Intent.createChooser(intent,
+                    getResources().getString(R.string.open_file_title)));
+        } catch (ActivityNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        // 先remove listener  停止唤醒,释放资源
+        wakeUp.removeWakeUpListener(wakeUpListener);
+        wakeUp.stopWakeUp();
+        wakeUp.releaseWakeUp();
+
+        if (dcsFramework != null) {
+            dcsFramework.release();
+        }
+        webView.setWebViewClientListen(null);
+        mTopLinearLayout.removeView(webView);
+        webView.removeAllViews();
+        webView.destroy();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleOAuthActivity.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidapp;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.oauth.api.BaiduDialog;
+import com.baidu.duer.dcs.oauth.api.BaiduDialogError;
+import com.baidu.duer.dcs.oauth.api.BaiduException;
+import com.baidu.duer.dcs.oauth.api.BaiduOauthImplicitGrant;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 用户认证界面
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/18.
+ */
+public class DcsSampleOAuthActivity extends DcsSampleBaseActivity implements View.OnClickListener {
+    // 需要开发者自己申请client_id
+    // client_id,就是oauth的client_id
+    private static final String CLIENT_ID = "{{nc72pRBp2VbSBZk0LSvqHGjFrbjOvQNH}}";
+    // 是否每次授权都强制登陆
+    private boolean isForceLogin = false;
+    // 是否每次都确认登陆
+    private boolean isConfirmLogin = true;
+    private EditText editTextClientId;
+    private Button oauthLoginButton;
+    private BaiduOauthImplicitGrant baiduOauthImplicitGrant;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.dcs_sample_activity_oauth);
+        initView();
+        setOnClickListener();
+    }
+
+    private void setOnClickListener() {
+        oauthLoginButton.setOnClickListener(this);
+    }
+
+    private void initView() {
+        editTextClientId = (EditText) findViewById(R.id.edit_client_id);
+        oauthLoginButton = (Button) findViewById(R.id.btn_login);
+
+        editTextClientId.setText(CLIENT_ID);
+    }
+
+    @Override
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.btn_login:
+                String clientId = editTextClientId.getText().toString();
+                if (!TextUtils.isEmpty(clientId) && !TextUtils.isEmpty(clientId)) {
+                    baiduOauthImplicitGrant = new BaiduOauthImplicitGrant(clientId, DcsSampleOAuthActivity.this.getApplication());
+                    baiduOauthImplicitGrant.authorize(DcsSampleOAuthActivity.this, isForceLogin, isConfirmLogin, new BaiduDialog
+                            .BaiduDialogListener() {
+                        @Override
+                        public void onComplete(Bundle values) {
+                            Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(),
+                                    getResources().getString(R.string.login_succeed),
+                                    Toast.LENGTH_SHORT).show();
+                            startMainActivity();
+                        }
+
+                        @Override
+                        public void onBaiduException(BaiduException e) {
+
+                        }
+
+                        @Override
+                        public void onError(BaiduDialogError e) {
+                            if (null != e) {
+                                String toastString = TextUtils.isEmpty(e.getMessage())
+                                        ? DcsSampleOAuthActivity.this.getResources()
+                                        .getString(R.string.err_net_msg) : e.getMessage();
+                                Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(), toastString,
+                                        Toast.LENGTH_SHORT).show();
+                            }
+                        }
+
+                        @Override
+                        public void onCancel() {
+                            LogUtil.d("cancle", "I am back");
+                        }
+                    });
+                } else {
+                    Toast.makeText(DcsSampleOAuthActivity.this.getApplicationContext(),
+                            getResources().getString(R.string.client_id_empty),
+                            Toast.LENGTH_SHORT).show();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    private void startMainActivity() {
+        Intent intent = new Intent(DcsSampleOAuthActivity.this, DcsSampleMainActivity.class);
+        intent.putExtra("baidu", baiduOauthImplicitGrant);
+        startActivity(intent);
+        finish();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidapp/DcsSampleScreenHtmlActivity.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidapp;
+
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.webkit.WebView;
+import android.widget.RelativeLayout;
+
+import com.baidu.duer.dcs.R;
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+
+/**
+ * show html UI.
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/31.
+ */
+public class DcsSampleScreenHtmlActivity extends DcsSampleBaseActivity {
+    private HtmlPayload htmlPayLoad;
+    private RelativeLayout relativeLayout;
+    private BaseWebView webView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.dcs_sample_activity_screen_html);
+        htmlPayLoad = (HtmlPayload) this.getIntent().getSerializableExtra("HTML_PLAY_LOAD");
+        initView();
+        addView();
+    }
+
+    private void initView() {
+        relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
+    }
+
+    private void addView() {
+        webView = new BaseWebView(DcsSampleScreenHtmlActivity.this.getApplicationContext());
+        webView.setWebViewClientListen(new BaseWebView.WebViewClientListener() {
+            @Override
+            public BaseWebView.LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url) {
+                return BaseWebView.LoadingWebStatus.STATUS_UNKNOW;
+            }
+
+            @Override
+            public void onPageStarted(WebView view, String url, Bitmap favicon) {
+
+            }
+
+            @Override
+            public void onPageFinished(WebView view, String url) {
+
+            }
+
+            @Override
+            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+
+            }
+        });
+        relativeLayout.addView(webView);
+        if (null != htmlPayLoad) {
+            webView.loadUrl(htmlPayLoad.getUrl());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/AudioRecordThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,84 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl;
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 录音采集线程-音频数据生产者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioRecordThread extends Thread implements IAudioRecord {
+    private static final String TAG = AudioRecordThread.class.getSimpleName();
+    // 采样率
+    private static final int SAMPLE_RATE_HZ = 16000;
+    private int bufferSize;
+    private AudioRecord audioRecord;
+    private volatile boolean isStartRecord = false;
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+
+    public AudioRecordThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+        this.linkedBlockingDeque = linkedBlockingDeque;
+        bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE_HZ, AudioFormat.CHANNEL_IN_MONO,
+                AudioFormat.ENCODING_PCM_16BIT);
+        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_HZ, AudioFormat.CHANNEL_IN_MONO,
+                AudioFormat.ENCODING_PCM_16BIT, bufferSize);
+    }
+
+    @Override
+    public void startRecord() {
+        if (isStartRecord) {
+            return;
+        }
+        isStartRecord = true;
+        this.start();
+    }
+
+    @Override
+    public void stopRecord() {
+        isStartRecord = false;
+    }
+
+    @Override
+    public void run() {
+        super.run();
+        LogUtil.i(TAG, "audioRecord startRecording ");
+        audioRecord.startRecording();
+        byte[] buffer = new byte[bufferSize];
+        while (isStartRecord) {
+            int readBytes = audioRecord.read(buffer, 0, bufferSize);
+            if (readBytes > 0) {
+                linkedBlockingDeque.add(buffer);
+            }
+        }
+        // 清空数据
+        linkedBlockingDeque.clear();
+        // 释放资源
+        audioRecord.stop();
+        audioRecord.release();
+        audioRecord = null;
+        LogUtil.i(TAG, "audioRecord release ");
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/HandlerImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import com.baidu.duer.dcs.systeminterface.IHandler;
+
+/**
+ * Created by wuruisheng on 2017/6/7.
+ */
+public class HandlerImpl implements IHandler {
+    private final Handler handler;
+
+    public HandlerImpl() {
+        handler = new Handler();
+    }
+
+    public HandlerImpl(Looper looper) {
+        handler = new Handler(looper);
+    }
+
+    @Override
+    public boolean post(Runnable runnable) {
+        return handler.post(runnable);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/PlatformFactoryImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.baidu.duer.dcs.androidsystemimpl.alert.AlertsFileDataStoreImpl;
+import com.baidu.duer.dcs.androidsystemimpl.audioinput.AudioVoiceInputImpl;
+import com.baidu.duer.dcs.androidsystemimpl.playbackcontroller.IPlaybackControllerImpl;
+import com.baidu.duer.dcs.androidsystemimpl.player.MediaPlayerImpl;
+import com.baidu.duer.dcs.androidsystemimpl.wakeup.WakeUpImpl;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.systeminterface.IHandler;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * Created by wuruisheng on 2017/6/7.
+ */
+public class PlatformFactoryImpl implements IPlatformFactory {
+    private IHandler mainHandler;
+    private IAudioInput voiceInput;
+    private IWebView webView;
+    private IPlaybackController playback;
+    private Context context;
+    private IAudioRecord audioRecord;
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque = new LinkedBlockingDeque<>();
+
+    public PlatformFactoryImpl(Context context) {
+        this.context = context.getApplicationContext();
+    }
+
+    @Override
+    public IHandler createHandler() {
+        return new HandlerImpl();
+    }
+
+    @Override
+    public IHandler getMainHandler() {
+        if (mainHandler == null) {
+            mainHandler = new HandlerImpl(Looper.getMainLooper());
+        }
+
+        return mainHandler;
+    }
+
+    @Override
+    public IAudioRecord getAudioRecord() {
+        if (audioRecord == null) {
+            audioRecord = new AudioRecordThread(linkedBlockingDeque);
+        }
+        return audioRecord;
+    }
+
+    @Override
+    public IWakeUp getWakeUp() {
+        return new WakeUpImpl(context, linkedBlockingDeque);
+    }
+
+    @Override
+    public IAudioInput getVoiceInput() {
+        if (voiceInput == null) {
+            voiceInput = new AudioVoiceInputImpl(linkedBlockingDeque);
+        }
+
+        return voiceInput;
+    }
+
+    @Override
+    public IMediaPlayer createMediaPlayer() {
+        return new MediaPlayerImpl();
+    }
+
+    public IAlertsDataStore createAlertsDataStore() {
+        return new AlertsFileDataStoreImpl();
+    }
+
+    @Override
+    public IWebView getWebView() {
+        return webView;
+    }
+
+    @Override
+    public IPlaybackController getPlayback() {
+        if (playback == null) {
+            playback = new IPlaybackControllerImpl();
+        }
+
+        return playback;
+    }
+
+    public void setWebView(IWebView webView) {
+        this.webView = webView;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/alert/AlertsFileDataStoreImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.alert;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.type.TypeReference;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * 持久化alert数据到文件-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class AlertsFileDataStoreImpl implements IAlertsDataStore {
+    private static final String TAG = AlertsFileDataStoreImpl.class.getSimpleName();
+    private static final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+    private Handler mHandler = new Handler();
+
+    public AlertsFileDataStoreImpl() {
+    }
+
+    @Override
+    public void readFromDisk(final IAlertsDataStore.ReadResultListener listener) {
+        mExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                FileReader fis;
+                BufferedReader br = null;
+                ObjectReader reader = ObjectMapperUtil.instance()
+                        .getObjectReader()
+                        .withType(new TypeReference<List<Alert>>() {
+                        });
+                try {
+                    File file = FileUtil.getAlarmFile();
+                    if (file == null) {
+                        postReadFailed(listener, "create file failed file is null");
+                        return;
+                    }
+                    fis = new FileReader(file);
+                    br = new BufferedReader(fis);
+                    List<Alert> alerts = reader.readValue(br);
+                    postReadSucceed(listener, alerts);
+                } catch (final FileNotFoundException e) {
+                    postReadFailed(listener, "Failed to load alerts from disk.");
+                } catch (IOException e) {
+                    postReadFailed(listener, e.getMessage());
+                } finally {
+                    CommonUtil.closeQuietly(br);
+                }
+            }
+        });
+    }
+
+    private void postReadFailed(final IAlertsDataStore.ReadResultListener listener, final String errorMessage) {
+        if (listener != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    listener.onFailed(errorMessage);
+                }
+            });
+        }
+    }
+
+    private void postReadSucceed(final IAlertsDataStore.ReadResultListener listener, final List<Alert> alerts) {
+        if (listener != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    listener.onSucceed(alerts);
+                }
+            });
+        }
+    }
+
+    @Override
+    public void writeToDisk(final List<Alert> alerts, final IAlertsDataStore.WriteResultListener listener) {
+        mExecutor.execute(new Runnable() {
+
+            @Override
+            public void run() {
+                ObjectWriter writer = ObjectMapperUtil.instance().getObjectWriter();
+                PrintWriter out = null;
+                try {
+                    File file = FileUtil.getAlarmFile();
+                    if (file == null) {
+                        postWriteFailed(listener, "create file failed file is null ");
+                        return;
+                    }
+                    out = new PrintWriter(file);
+                    out.print(writer.writeValueAsString(alerts));
+                    out.flush();
+                    LogUtil.e(TAG, "start postWriteSucceed");
+                    postWriteSucceed(listener);
+                } catch (IOException e) {
+                    LogUtil.e(TAG, "Failed to write to disk", e);
+                    postWriteFailed(listener, "Failed to write to disk,error:" + e.getMessage());
+                } finally {
+                    CommonUtil.closeQuietly(out);
+                }
+            }
+        });
+    }
+
+    private void postWriteFailed(final IAlertsDataStore.WriteResultListener listener, final String errorMessage) {
+        if (listener != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    listener.onFailed(errorMessage);
+                }
+            });
+        }
+    }
+
+    private void postWriteSucceed(final IAlertsDataStore.WriteResultListener listener) {
+        if (listener != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    listener.onSucceed();
+                }
+            });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl.audioinput;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * AudioInput实现,控制麦克风获取语音数据流
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioVoiceInputImpl implements IAudioInput {
+    // 消费线程
+    private AudioVoiceInputThread audioVoiceInputThread;
+    // 音频数据
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+    private IAudioInputListener audioInputListener;
+    private Handler handler = new Handler();
+
+    public AudioVoiceInputImpl(LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+        this.linkedBlockingDeque = linkedBlockingDeque;
+    }
+
+    @Override
+    public void startRecord() {
+        DcsStreamRequestBody dcsStreamRequestBody = new DcsStreamRequestBody();
+        audioInputListener.onStartRecord(dcsStreamRequestBody);
+        audioVoiceInputThread = new AudioVoiceInputThread(
+                linkedBlockingDeque,
+                dcsStreamRequestBody.sink(),
+                handler);
+        audioVoiceInputThread.setAudioInputListener(new AudioVoiceInputThread.IAudioInputListener() {
+            @Override
+            public void onWriteFinished() {
+                if (audioInputListener != null) {
+                    audioInputListener.onStopRecord();
+                }
+            }
+        });
+        audioVoiceInputThread.startWriteStream();
+    }
+
+    @Override
+    public void stopRecord() {
+        audioVoiceInputThread.stopWriteStream();
+    }
+
+    @Override
+    public void registerAudioInputListener(IAudioInputListener audioInputListener) {
+        this.audioInputListener = audioInputListener;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/audioinput/AudioVoiceInputThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,131 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl.audioinput;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import okio.BufferedSink;
+
+/**
+ * 将语音发送到服务器的线程-发送消费者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public class AudioVoiceInputThread extends Thread {
+    private static final String TAG = AudioVoiceInputThread.class.getSimpleName();
+    private volatile boolean isStart = false;
+    private BufferedSink bufferedSink;
+    // 音频数据
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+    private Handler handler;
+
+    public AudioVoiceInputThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque,
+                                 BufferedSink bufferedSink,
+                                 Handler handler) {
+        this.linkedBlockingDeque = linkedBlockingDeque;
+        this.bufferedSink = bufferedSink;
+        this.handler = handler;
+    }
+
+    /**
+     * 开始写入数据
+     */
+    public void startWriteStream() {
+        if (isStart) {
+            return;
+        }
+        isStart = true;
+        this.start();
+    }
+
+    /**
+     * 停止写入数据
+     */
+    public void stopWriteStream() {
+        isStart = false;
+    }
+
+    @Override
+    public void run() {
+        super.run();
+        while (isStart) {
+            try {
+                byte[] recordAudioData = linkedBlockingDeque.pollFirst();
+                if (null != recordAudioData) {
+                    bufferedSink.write(recordAudioData);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+                LogUtil.d(TAG, "writeTo IOException", e);
+            } catch (Exception e) {
+                e.printStackTrace();
+                LogUtil.d(TAG, "writeTo Exception", e);
+            }
+        }
+        if (linkedBlockingDeque.size() > 0) {
+            byte[] recordAudioData = linkedBlockingDeque.pollFirst();
+            if (null != recordAudioData) {
+                LogUtil.d(TAG, "finally writeTo size:" + recordAudioData.length);
+                try {
+                    bufferedSink.write(recordAudioData);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    LogUtil.d(TAG, " >0 writeTo IOException", e);
+                }
+            }
+        }
+        try {
+            bufferedSink.flush();
+            bufferedSink.close();
+            LogUtil.d(TAG, "closed");
+        } catch (IOException e) {
+            e.printStackTrace();
+            LogUtil.d(TAG, "IOException ", e);
+        }
+        LogUtil.d(TAG, "onWriteFinished ");
+        // 写入完成
+        if (listener != null) {
+            handler.post(new Runnable() {
+                @Override
+                public void run() {
+                    listener.onWriteFinished();
+                }
+            });
+        }
+    }
+
+    private IAudioInputListener listener;
+
+    public void setAudioInputListener(IAudioInputListener listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * 写入完成的回调接口,比如当接收到StopListen指令后回触发
+     */
+    public interface IAudioInputListener {
+        /**
+         * 写入完成后回调此方法
+         */
+        void onWriteFinished();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/playbackcontroller/IPlaybackControllerImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.playbackcontroller;
+
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+
+/**
+ * 播放控制
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/17.
+ */
+public class IPlaybackControllerImpl implements IPlaybackController {
+    private IPlaybackListener playbackListener;
+
+    @Override
+    public void play(IResponseListener responseListener) {
+        if (playbackListener == null) {
+            return;
+        }
+        playbackListener.onPlay(responseListener);
+    }
+
+    @Override
+    public void pause(IResponseListener responseListener) {
+        if (playbackListener == null) {
+            return;
+        }
+        playbackListener.onPause(responseListener);
+    }
+
+    @Override
+    public void previous(IResponseListener responseListener) {
+        if (playbackListener == null) {
+            return;
+        }
+        playbackListener.onPrevious(responseListener);
+    }
+
+    @Override
+    public void next(IResponseListener responseListener) {
+        if (playbackListener == null) {
+            return;
+        }
+        playbackListener.onNext(responseListener);
+    }
+
+    @Override
+    public void registerPlaybackListener(IPlaybackListener listener) {
+        this.playbackListener = listener;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStoreThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.FileUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * 将stream的mp3流保存到文件中
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class AudioStoreThread extends Thread {
+    private static final String TAG = AudioStoreThread.class.getSimpleName();
+    private static final int BUFFER_SIZE = 8192;
+    private volatile boolean mThreadExitFlag;
+    private InputStream mInputStream;
+    private Handler mHandler = new Handler();
+
+    private File file;
+    private File completedFile;
+    private FileOutputStream mOutputStream;
+
+    public AudioStoreThread(InputStream is) {
+        this.mInputStream = is;
+    }
+
+    @Override
+    public void run() {
+        super.run();
+        try {
+            file = FileUtil.getSpeakFile();
+            if (file != null) {
+                LogUtil.d(TAG, "AudioStoreThread  file: " + file.getAbsolutePath());
+                this.mOutputStream = new FileOutputStream(file);
+            } else {
+                if (mOnDownListener != null) {
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                mOnDownListener.onDownError(
+                                        new JSONObject("AudioStoreThread  create temp file failed!"));
+                            } catch (JSONException e1) {
+                                e1.printStackTrace();
+                            }
+                        }
+                    });
+                }
+            }
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            LogUtil.d(TAG, "AudioStoreThread  FileNotFoundException ");
+        }
+        if (mOnDownListener != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mOnDownListener.onDownStart();
+                }
+            });
+        }
+        byte[] audioData = new byte[BUFFER_SIZE];
+        int readBytes;
+        try {
+            while (!mThreadExitFlag && (readBytes = mInputStream.read(audioData)) != -1) {
+                LogUtil.d(TAG, "readBytes=" + readBytes);
+                mOutputStream.write(audioData, 0, readBytes);
+            }
+            mOutputStream.flush();
+            LogUtil.d(TAG, "AudioStoreThread  ok ");
+        } catch (final IOException e) {
+            e.printStackTrace();
+            LogUtil.d(TAG, "AudioStoreThread  write error ", e);
+            if (mOnDownListener != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            mOnDownListener.onDownError(new JSONObject("AudioStoreThread  write error :"
+                                    + e.getMessage()));
+                        } catch (JSONException e1) {
+                            e1.printStackTrace();
+                        }
+                    }
+                });
+            }
+        } finally {
+            try {
+                String fileName = file.getName().substring(0, file.getName().length()
+                        - FileUtil.TEMP_POSTFIX.length());
+                LogUtil.d(TAG, "AudioStoreThread  fileName : " + fileName);
+                completedFile = new File(file.getParentFile(), fileName);
+                boolean renamed = file.renameTo(completedFile);
+                if (!renamed) {
+                    if (mOnDownListener != null) {
+                        mHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                try {
+                                    mOnDownListener.onDownError(new JSONObject("Error renaming file "
+                                            + file
+                                            + "to"
+                                            + completedFile
+                                            + " for completion!"));
+                                } catch (JSONException e) {
+                                    e.printStackTrace();
+                                }
+                            }
+                        });
+                    }
+                }
+                mOutputStream.close();
+                mInputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            if (mOnDownListener != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        LogUtil.d(TAG, "completedFile  path: " + completedFile.getAbsolutePath());
+                        mOnDownListener.onDownComplete(completedFile.getAbsolutePath());
+                    }
+                });
+            }
+        }
+    }
+
+    /**
+     * 停止保存/下载
+     */
+    public void stopDown() {
+        LogUtil.d(TAG, "stopDown");
+        mThreadExitFlag = true;
+        mHandler.removeCallbacksAndMessages(null);
+    }
+
+    /**
+     * 删除文件
+     *
+     * @return 是否删除成功
+     */
+    public boolean delDownFile() {
+        LogUtil.d(TAG, "delDownFile");
+        if (completedFile != null && completedFile.exists()) {
+            return completedFile.delete();
+        }
+        return false;
+    }
+
+    public static class SimpleOnDownListener implements OnDownListener {
+        @Override
+        public void onDownStart() {
+        }
+
+        @Override
+        public void onDownComplete(String path) {
+        }
+
+        @Override
+        public void onDownError(JSONObject jsonObject) {
+        }
+    }
+
+    public OnDownListener mOnDownListener;
+
+    public void setOnDownListener(OnDownListener listener) {
+        this.mOnDownListener = listener;
+    }
+
+    /**
+     * 流保存回调接口
+     */
+    public interface OnDownListener {
+        void onDownStart();
+
+        void onDownComplete(String path);
+
+        void onDownError(JSONObject jsonObject);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/AudioStreamStoreImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.player;
+
+import org.json.JSONObject;
+
+import java.io.InputStream;
+
+/**
+ * 保存音频mp3流到文件中-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class AudioStreamStoreImpl implements IAudioStreamStore {
+    private AudioStoreThread mAudioStoreThread;
+    private OnStoreListener onStoreListener;
+
+    @Override
+    public void save(InputStream inputStream) {
+        mAudioStoreThread = new AudioStoreThread(inputStream);
+        mAudioStoreThread.setOnDownListener(simpleOnDownListener);
+        mAudioStoreThread.start();
+    }
+
+    @Override
+    public void cancel() {
+        if (mAudioStoreThread != null) {
+            mAudioStoreThread.stopDown();
+        }
+    }
+
+    @Override
+    public void speakAfter() {
+        if (mAudioStoreThread != null) {
+            mAudioStoreThread.delDownFile();
+        }
+    }
+
+    @Override
+    public void setOnStoreListener(OnStoreListener listener) {
+        onStoreListener = listener;
+    }
+
+    private AudioStoreThread.SimpleOnDownListener simpleOnDownListener = new AudioStoreThread.SimpleOnDownListener() {
+        @Override
+        public void onDownComplete(String path) {
+            super.onDownComplete(path);
+            if (onStoreListener != null) {
+                onStoreListener.onComplete(path);
+            }
+        }
+
+        @Override
+        public void onDownError(JSONObject jsonObject) {
+            super.onDownError(jsonObject);
+            if (onStoreListener != null) {
+                onStoreListener.onError(jsonObject.toString());
+            }
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/IAudioStreamStore.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.player;
+
+import java.io.InputStream;
+
+/**
+ * mp3流保存接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public interface IAudioStreamStore {
+    /**
+     * 保存mp3流到文件中(存储设备中)
+     */
+    void save(InputStream inputStream);
+
+    /**
+     * 取消保存
+     */
+    void cancel();
+
+    /**
+     * 播报完成后处理的操作,比如删除保存的文件
+     */
+    void speakAfter();
+
+    /**
+     * 保存回调监听
+     *
+     * @param listener listener
+     */
+    void setOnStoreListener(OnStoreListener listener);
+
+    /**
+     * 保存回调接口
+     */
+    interface OnStoreListener {
+        void onStart();
+
+        void onComplete(String path);
+
+        void onError(String errorMessage);
+    }
+
+    class SimpleOnStoreListener implements OnStoreListener {
+        @Override
+        public void onStart() {
+        }
+
+        @Override
+        public void onComplete(String path) {
+        }
+
+        @Override
+        public void onError(String errorMessage) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.app.Service;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.AssetManager;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.baidu.duer.dcs.androidapp.DcsSampleApplication;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * android MediaPlayer -android平台中实现音频的播放逻辑
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class MediaPlayerImpl implements IMediaPlayer {
+    private static final String TAG = MediaPlayerImpl.class.getSimpleName();
+    public static final String ASSERT_PREFIX = "assets://";
+    private static final String KEY_SP_VOLUME = "currentVolume";
+    private static final String KEY_SP_MUTE = "isMute";
+    private IMediaPlayer.PlayState mCurrentState = IMediaPlayer.PlayState.IDLE;
+    private MediaPlayer mMediaPlayer;
+    private float currentVolume = 0.8f;                 // 默认音量80%
+    private boolean isMute;
+    private boolean isError38;
+    private float currentPercent;
+    private int currentSeekMilliseconds;
+    private IAudioStreamStore audioStreamStore;         // stream流数据保存
+    private List<IMediaPlayer.IMediaPlayerListener> mediaPlayerListeners;
+    private boolean isActive;
+    private TelephonyManager telephonyManager;
+
+    public MediaPlayerImpl() {
+        mMediaPlayer = new MediaPlayer();
+        // set audio stream type
+        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+        mMediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
+        mMediaPlayer.setOnErrorListener(errorListener);
+        mMediaPlayer.setOnPreparedListener(preparedListener);
+        mMediaPlayer.setOnCompletionListener(completionListener);
+        mMediaPlayer.setOnSeekCompleteListener(seekCompleteListener);
+        // 不同的音频源,此回调有的不回调!!!
+        // mMediaPlayer.setOnInfoListener(infoListener);
+
+        // 读取音量和静音的数据
+        currentVolume = (float) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
+                KEY_SP_VOLUME, 0.8f);
+        isMute = (boolean) MediaPlayerPreferenceUtil.get(DcsSampleApplication.getInstance(),
+                KEY_SP_MUTE, false);
+        // LinkedList
+        mediaPlayerListeners = Collections.synchronizedList(new LinkedList<IMediaPlayer.IMediaPlayerListener>());
+
+        // 来电监听
+        telephonyManager = (TelephonyManager)
+                DcsSampleApplication.getInstance().getSystemService(Service.TELEPHONY_SERVICE);
+        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+    }
+
+    private PhoneStateListener phoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onCallStateChanged(int state, String incomingNumber) {
+            super.onCallStateChanged(state, incomingNumber);
+            switch (state) {
+                // 电话挂断
+                case TelephonyManager.CALL_STATE_IDLE:
+                    resume();
+                    break;
+                // 等待接电话
+                case TelephonyManager.CALL_STATE_RINGING:
+                    pause();
+                    break;
+                // 通话中
+                case TelephonyManager.CALL_STATE_OFFHOOK:
+                    break;
+                default:
+                    break;
+            }
+        }
+    };
+
+    private IAudioStreamStore.OnStoreListener onStoreListener = new IAudioStreamStore.SimpleOnStoreListener() {
+        @Override
+        public void onComplete(String path) {
+            LogUtil.e(TAG, "onStoreListener,path:" + path);
+            // after down star play
+            File file = new File(path);
+            if (file.exists() && file.length() > 0) {
+                play(path);
+            } else {
+                mCurrentState = IMediaPlayer.PlayState.ERROR;
+                fireOnError("play path not exists or length<0 ",
+                        IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+            }
+        }
+    };
+
+    @Override
+    public void play(MediaResource mediaResource) {
+        if (mediaResource.isStream) {
+            play(mediaResource.stream);
+        } else {
+            play(mediaResource.url);
+        }
+    }
+
+    private void play(InputStream stream) {
+        LogUtil.e(TAG, "play stream");
+        if (audioStreamStore == null) {
+            audioStreamStore = new AudioStreamStoreImpl();
+        }
+        audioStreamStore.setOnStoreListener(onStoreListener);
+        audioStreamStore.save(stream);
+    }
+
+    private void play(String url) {
+        if (TextUtils.isEmpty(url)) {
+            LogUtil.d(TAG, "play-url is empty");
+            fireOnError("play-url is empty.",
+                    IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+            mCurrentState = IMediaPlayer.PlayState.ERROR;
+            return;
+        }
+        fireOnInit();
+        LogUtil.d(TAG, "play-url:" + url);
+        if (url.startsWith(ASSERT_PREFIX) && url.length() > ASSERT_PREFIX.length()) {
+            playAsset(url.substring(ASSERT_PREFIX.length()));
+        } else {
+            try {
+                mMediaPlayer.reset();
+                mMediaPlayer.setDataSource(url);
+                // Async
+                mMediaPlayer.prepareAsync();
+                mCurrentState = IMediaPlayer.PlayState.PREPARING;
+            } catch (IOException e) {
+                e.printStackTrace();
+                LogUtil.d(TAG, "playPath", e);
+                mCurrentState = IMediaPlayer.PlayState.ERROR;
+                fireOnError("IOException play url :"
+                        + url, IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+            }
+        }
+    }
+
+    private void playAsset(String resName) {
+        LogUtil.d(TAG, "playAsset:" + resName);
+        try {
+            AssetManager am = DcsSampleApplication.getInstance().getAssets();
+            AssetFileDescriptor afd = am.openFd(resName);
+            mMediaPlayer.reset();
+            mMediaPlayer.setDataSource(afd.getFileDescriptor(),
+                    afd.getStartOffset(), afd.getLength());
+            mMediaPlayer.prepareAsync();
+            mCurrentState = IMediaPlayer.PlayState.PREPARING;
+        } catch (IOException e) {
+            e.printStackTrace();
+            LogUtil.d(TAG, "playAsset", e);
+            mCurrentState = IMediaPlayer.PlayState.ERROR;
+            fireOnError("IOException play playAsset",
+                    IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR);
+        }
+    }
+
+    @Override
+    public void pause() {
+        if (mCurrentState == IMediaPlayer.PlayState.PLAYING
+                || mCurrentState == IMediaPlayer.PlayState.PREPARED
+                || mCurrentState == IMediaPlayer.PlayState.PREPARING) {
+            mMediaPlayer.pause();
+            mCurrentState = IMediaPlayer.PlayState.PAUSED;
+            fireOnPaused();
+        }
+    }
+
+    @Override
+    public void stop() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.stop();
+            mCurrentState = IMediaPlayer.PlayState.STOPPED;
+            // delete audio file
+            if (audioStreamStore != null) {
+                audioStreamStore.cancel();
+                audioStreamStore.speakAfter();
+            }
+            fireStopped();
+        }
+    }
+
+
+    @Override
+    public void resume() {
+        if (mCurrentState == IMediaPlayer.PlayState.PAUSED) {
+            mMediaPlayer.start();
+            mCurrentState = IMediaPlayer.PlayState.PLAYING;
+            firePlaying();
+        }
+    }
+
+    @Override
+    public void release() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.stop();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            mCurrentState = IMediaPlayer.PlayState.IDLE;
+            fireOnRelease();
+        }
+        if (audioStreamStore != null) {
+            audioStreamStore.cancel();
+            audioStreamStore.speakAfter();
+        }
+        mediaPlayerListeners.clear();
+    }
+
+    @Override
+    public PlayState getPlayState() {
+        return mCurrentState;
+    }
+
+    @Override
+    public void seekTo(int pos) {
+        currentSeekMilliseconds = pos;
+        LogUtil.d(TAG, "seekTo,currentSeekMilliseconds:" + currentSeekMilliseconds);
+        if (mMediaPlayer != null && mCurrentState == IMediaPlayer.PlayState.PREPARED) {
+            mMediaPlayer.seekTo(pos);
+        }
+    }
+
+    /**
+     * 设置音量
+     *
+     * @param volume 0.0 -1.0
+     */
+    @Override
+    public void setVolume(float volume) {
+        // 设置音量就不再静音了,比如:说了调衡音量等操作
+        isMute = false;
+        currentVolume = volume;
+        if (mMediaPlayer != null) {
+            mMediaPlayer.setVolume(volume, volume);
+        }
+        //  保存数据
+        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+                KEY_SP_VOLUME, currentVolume);
+        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+                KEY_SP_MUTE, isMute);
+    }
+
+    @Override
+    public float getVolume() {
+        return currentVolume;
+    }
+
+    @Override
+    public void setMute(boolean mute) {
+        isMute = mute;
+        if (mMediaPlayer != null) {
+            if (mute) {
+                mMediaPlayer.setVolume(0, 0);
+            } else {
+                mMediaPlayer.setVolume(currentVolume, currentVolume);
+            }
+        }
+        //  保存数据
+        MediaPlayerPreferenceUtil.put(DcsSampleApplication.getInstance(),
+                KEY_SP_MUTE, isMute);
+    }
+
+    @Override
+    public boolean getMute() {
+        return isMute;
+    }
+
+    @Override
+    public long getCurrentPosition() {
+        if (mMediaPlayer == null) {
+            return 0;
+        }
+        if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
+            return 0;
+        }
+        return mMediaPlayer.getCurrentPosition();
+    }
+
+    @Override
+    public long getDuration() {
+        if (mMediaPlayer == null) {
+            return 0;
+        }
+        if (mCurrentState == IMediaPlayer.PlayState.IDLE || mCurrentState == IMediaPlayer.PlayState.ERROR) {
+            return 0;
+        }
+        return mMediaPlayer.getDuration();
+    }
+
+    @Override
+    public float getBufferPercentage() {
+        return currentPercent;
+    }
+
+
+    @Override
+    public void addMediaPlayerListener(IMediaPlayerListener listener) {
+        if (!mediaPlayerListeners.contains(listener)) {
+            mediaPlayerListeners.add(listener);
+        }
+    }
+
+    @Override
+    public void removeMediaPlayerListener(IMediaPlayerListener listener) {
+        if (mediaPlayerListeners.contains(listener)) {
+            mediaPlayerListeners.remove(listener);
+        }
+    }
+
+    @Override
+    public void setActive(boolean isActive) {
+        this.isActive = isActive;
+    }
+
+    @Override
+    public boolean isActive() {
+        return isActive;
+    }
+
+    private void fireOnError(String error, ErrorType errorType) {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onError(error, errorType);
+            }
+        }
+    }
+
+    private void fireOnInit() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onInit();
+            }
+        }
+    }
+
+    private void fireOnPaused() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onPaused();
+            }
+        }
+    }
+
+    private void fireStopped() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onStopped();
+            }
+        }
+    }
+
+    private void firePlaying() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onPlaying();
+            }
+        }
+    }
+
+    private void fireOnRelease() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onRelease();
+            }
+        }
+    }
+
+    private void fireOnPrepared() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onPrepared();
+            }
+        }
+    }
+
+    private void fireOonBufferingUpdate(int percent) {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onBufferingUpdate(percent);
+            }
+        }
+    }
+
+    private void fireOnCompletion() {
+        for (IMediaPlayer.IMediaPlayerListener listener : mediaPlayerListeners) {
+            if (listener != null) {
+                listener.onCompletion();
+            }
+        }
+    }
+
+    private MediaPlayer.OnPreparedListener preparedListener = new MediaPlayer.OnPreparedListener() {
+        @Override
+        public void onPrepared(MediaPlayer mp) {
+            LogUtil.d(TAG, "onPrepared");
+            mCurrentState = IMediaPlayer.PlayState.PREPARED;
+            isError38 = false;
+            fireOnPrepared();
+            // must be called  after  prepareAsync or prepare
+            LogUtil.d(TAG, "currentVolume:" + currentVolume);
+            LogUtil.d(TAG, "currentSeekMilliseconds:" + currentSeekMilliseconds);
+            //  一开始就说话让它静音了
+            if (isMute) {
+                mMediaPlayer.setVolume(0, 0);
+            } else {
+                setVolume(currentVolume);
+            }
+            seekTo(currentSeekMilliseconds);
+        }
+    };
+
+    private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener =
+            new MediaPlayer.OnBufferingUpdateListener() {
+                @Override
+                public void onBufferingUpdate(MediaPlayer mp, int percent) {
+                    currentPercent = percent * 1.0f;
+                    fireOonBufferingUpdate(percent);
+                }
+            };
+    private MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
+        @Override
+        public boolean onError(MediaPlayer mp, int what, int extra) {
+            LogUtil.d(TAG, "onError:" + what + ", extra:" + extra);
+            if (what == -38) {
+                isError38 = true;
+                return false;
+            }
+            isError38 = false;
+            mCurrentState = IMediaPlayer.PlayState.ERROR;
+            JSONObject jsonObject = new JSONObject();
+            try {
+                jsonObject.put("msg", "what: " + what + "; extra:" + extra);
+            } catch (JSONException e) {
+                e.printStackTrace();
+            }
+            IMediaPlayer.ErrorType errorType;
+            switch (what) {
+                case MediaPlayer.MEDIA_ERROR_IO:
+                    // Stream服务端返回错误 (bad request, unauthorized, forbidden, not found etc)
+                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INVALID_REQUEST;
+                    break;
+                case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
+                    // 端无法连接stream服务端
+                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_SERVICE_UNAVAILABLE;
+                    break;
+                case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
+                    // 端内部错误
+                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_DEVICE_ERROR;
+                    break;
+                case MediaPlayer.MEDIA_ERROR_MALFORMED:
+                    // stream服务端接受请求,但未能正确处理 ?????
+                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_INTERNAL_SERVER_ERROR;
+                    break;
+                default:
+                    // 未知错误
+                    errorType = IMediaPlayer.ErrorType.MEDIA_ERROR_UNKNOWN;
+                    break;
+            }
+            fireOnError(jsonObject.toString(), errorType);
+            return false;
+        }
+    };
+
+    private MediaPlayer.OnSeekCompleteListener seekCompleteListener = new MediaPlayer.OnSeekCompleteListener() {
+        @Override
+        public void onSeekComplete(MediaPlayer mp) {
+            LogUtil.d(TAG, "onSeekComplete");
+            if (mCurrentState == IMediaPlayer.PlayState.PREPARED) {
+                mp.start();
+                mCurrentState = IMediaPlayer.PlayState.PLAYING;
+                firePlaying();
+            }
+        }
+    };
+
+    private MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
+        @Override
+        public void onCompletion(MediaPlayer mp) {
+            if (isError38) {
+                return;
+            }
+            LogUtil.d(TAG, "onCompletion");
+            // delete audio file
+            if (audioStreamStore != null) {
+                audioStreamStore.cancel();
+                audioStreamStore.speakAfter();
+            }
+            mCurrentState = IMediaPlayer.PlayState.COMPLETED;
+            fireOnCompletion();
+        }
+    };
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/player/MediaPlayerPreferenceUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.player;
+
+import android.content.Context;
+
+import com.baidu.duer.dcs.util.PreferenceUtil;
+
+/**
+ * Media Player 保存音量和静音的状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/17.
+ */
+public class MediaPlayerPreferenceUtil extends PreferenceUtil {
+    // 保存到的文件名字
+    private static final String BAIDU_MEDIA_CONFIG = "baidu_media_config";
+
+    /**
+     * 保存音量或者静音的数据状态
+     *
+     * @param context 上下文
+     * @param key     键
+     * @param object  值
+     */
+    public static void put(Context context, String key, Object object) {
+        put(context, BAIDU_MEDIA_CONFIG, key, object);
+    }
+
+    /**
+     * 读取音量或者静音的数据状态
+     *
+     * @param context       上下文
+     * @param key           键
+     * @param defaultObject 默认值
+     */
+    public static Object get(Context context, String key, Object defaultObject) {
+        return get(context, BAIDU_MEDIA_CONFIG, key, defaultObject);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpDecodeThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,225 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+import android.os.Handler;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 唤醒声音处理-唤醒消费者
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+public class WakeUpDecodeThread extends Thread {
+    private static final String TAG = WakeUpDecodeThread.class.getSimpleName();
+    // 唤醒成功
+    private static final int WAKEUP_SUCCEED = 1;
+    // 唤醒词位置
+    private int voiceOffset;
+    private boolean isWakeUp;
+    private WakeUpNative wakeUpNative;
+    private Handler handler;
+    private volatile boolean isStart = false;
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+
+    public WakeUpDecodeThread(LinkedBlockingDeque<byte[]> linkedBlockingDeque,
+                              WakeUpNative wakeUpNative,
+                              Handler handler) {
+        this.linkedBlockingDeque = linkedBlockingDeque;
+        this.wakeUpNative = wakeUpNative;
+        this.handler = handler;
+    }
+
+    /**
+     * 开始唤醒
+     */
+    public void startWakeUp() {
+        if (isStart) {
+            return;
+        }
+        isStart = true;
+        this.start();
+    }
+
+    public boolean isStart() {
+        return isStart;
+    }
+
+    /**
+     * 停止唤醒
+     */
+    public void stopWakeUp() {
+        isStart = false;
+    }
+
+    @Override
+    public void run() {
+        super.run();
+        LogUtil.i(TAG, "wakeup wakeUpDecode start" );
+        while (isStart) {
+            try {
+                byte[] data = linkedBlockingDeque.take();
+
+                // 暂时不检测vad
+                // int volume = calculateVolume(data, 16);
+                // LogUtil.i(TAG, "wakeup audioRecord Volume:" + volume);
+                // if (volume <= 0) {
+                //  continue;
+                // }
+
+                if (data.length > 0) {
+                    // 是否为最后一帧数据
+                    boolean isEnd = false;
+                    short[] arr = byteArray2ShortArray(data, data.length / 2);
+                    int ret = wakeUpNative.wakeUpDecode(
+                            arr,
+                            arr.length,
+                            "",
+                            1,
+                            -1,
+                            true,
+                            voiceOffset++,
+                            isEnd
+                    );
+                    // 唤醒成功
+                    if (ret == WAKEUP_SUCCEED) {
+                        LogUtil.i(TAG, "wakeup wakeUpDecode ret:" + ret);
+                        isWakeUp = true;
+                        stopWakeUp();
+                        LogUtil.i(TAG, "wakeup wakeUpDecode succeed !!");
+                        break;
+                    }
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        LogUtil.i(TAG, "wakeup after wakeUpDecode over !!");
+        LogUtil.i(TAG, "wakeup after linkedBlockingDeque size:" + linkedBlockingDeque.size());
+
+        if (isWakeUp) {
+            if (listener != null) {
+                handler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        listener.onWakeUpSucceed();
+                    }
+                });
+            }
+        }
+        // 重置
+        voiceOffset = 0;
+        isWakeUp = false;
+    }
+
+    /**
+     * 将byte数组转为short数组
+     *
+     * @param data  byte数组的音频数据
+     * @param items short数组的大小
+     * @return 转换后的short数组
+     */
+    private short[] byteArray2ShortArray(byte[] data, int items) {
+        short[] retVal = new short[items];
+        for (int i = 0; i < retVal.length; i++) {
+            retVal[i] = (short) ((data[i * 2] & 0xff) | (data[i * 2 + 1] & 0xff) << 8);
+        }
+        return retVal;
+    }
+
+    /**
+     * 根据输入的音量大小来判断用户是否有语音输入
+     *
+     * @param var0 原始音频数据
+     * @param var1 音频数据格式位PCM,16位每个样本,比如如果音频数据格式设为AudioFormat.ENCODING_PCM_16BIT,则参数传16
+     * @return >0 代表有音频输入
+     */
+    private int calculateVolume(byte[] var0, int var1) {
+        int[] var3 = null;
+        int var4 = var0.length;
+        int var2;
+        if (var1 == 8) {
+            var3 = new int[var4];
+            for (var2 = 0; var2 < var4; ++var2) {
+                var3[var2] = var0[var2];
+            }
+        } else if (var1 == 16) {
+            var3 = new int[var4 / 2];
+            for (var2 = 0; var2 < var4 / 2; ++var2) {
+                byte var5 = var0[var2 * 2];
+                byte var6 = var0[var2 * 2 + 1];
+                int var13;
+                if (var5 < 0) {
+                    var13 = var5 + 256;
+                } else {
+                    var13 = var5;
+                }
+                short var7 = (short) (var13 + 0);
+                if (var6 < 0) {
+                    var13 = var6 + 256;
+                } else {
+                    var13 = var6;
+                }
+                var3[var2] = (short) (var7 + (var13 << 8));
+            }
+        }
+        int[] var8 = var3;
+        if (var3 != null && var3.length != 0) {
+            float var10 = 0.0F;
+            for (int var11 = 0; var11 < var8.length; ++var11) {
+                var10 += (float) (var8[var11] * var8[var11]);
+            }
+            var10 /= (float) var8.length;
+            float var12 = 0.0F;
+            for (var4 = 0; var4 < var8.length; ++var4) {
+                var12 += (float) var8[var4];
+            }
+            var12 /= (float) var8.length;
+            var4 = (int) (Math.pow(2.0D, (double) (var1 - 1)) - 1.0D);
+            double var14 = Math.sqrt((double) (var10 - var12 * var12));
+            int var9;
+            if ((var9 = (int) (10.0D * Math.log10(var14 * 10.0D * Math.sqrt(2.0D) / (double) var4 + 1.0D))) < 0) {
+                var9 = 0;
+            }
+            if (var9 > 10) {
+                var9 = 10;
+            }
+            return var9;
+        } else {
+            return 0;
+        }
+    }
+
+    private IWakeUpListener listener;
+
+    public void setWakeUpListener(IWakeUpListener listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * 唤醒成功回调接口
+     */
+    public interface IWakeUpListener {
+        /**
+         * 唤醒成功后回调
+         */
+        void onWakeUpSucceed();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,132 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * 唤醒模块-android中实现
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/25.
+ */
+public class WakeUpImpl implements IWakeUp {
+    private static final String TAG = WakeUpImpl.class.getSimpleName();
+    // 初始化唤醒词成功
+    private static final int WAKEUP_INIT_SUCCEED = 0;
+    // 唤醒词
+    private static final String WAKEUP_WORD = "小度小度";
+    // 唤醒词声学模型模型文件
+    private static final String WAKEUP_FILENAME = "libbdEasrS1MergeNormal.so";
+    // jni
+    private WakeUpNative wakeUpNative;
+    // Decode消费线程
+    private WakeUpDecodeThread wakeUpDecodeThread;
+    // callback
+    private List<IWakeUpListener> wakeUpListeners;
+    private Handler handler = new Handler();
+    // 音频数据
+    private LinkedBlockingDeque<byte[]> linkedBlockingDeque;
+    // 初始化唤醒词的返回值
+    private int wakeUpInitialRet;
+    private Context context;
+
+    public WakeUpImpl(Context context, LinkedBlockingDeque<byte[]> linkedBlockingDeque) {
+        this.linkedBlockingDeque = linkedBlockingDeque;
+        this.context = context.getApplicationContext();
+        this.wakeUpNative = new WakeUpNative();
+        this.wakeUpListeners = Collections.synchronizedList(new LinkedList<IWakeUpListener>());
+        this.initWakeUp();
+    }
+
+    private void initWakeUp() {
+        // 方法1:加载声学模型文件,当作so库进行加载到nativeLibraryDir目录中
+        // 方法2:当然你也可以放到assets目录或者raw下,然后进行拷贝到应用的私有目录或者sd卡
+        // 方法2需要处理声学模型文件覆盖安装问题,以及不可预料的拷贝失败问题!
+        String path = this.context.getApplicationInfo().nativeLibraryDir
+                + File.separatorChar + WAKEUP_FILENAME;
+        LogUtil.d(TAG, "wakeup path:" + path);
+        LogUtil.d(TAG, "wakeup exists:" + new File(path).exists());
+        // 1.初始化唤醒词,0 是初始化成功
+        wakeUpInitialRet = wakeUpNative.wakeUpInitial(WAKEUP_WORD, path, 0);
+        LogUtil.d(TAG, "wakeUpInitialRet:" + wakeUpInitialRet);
+    }
+
+    @Override
+    public void startWakeUp() {
+        if (wakeUpDecodeThread != null && wakeUpDecodeThread.isStart()) {
+            LogUtil.d(TAG, "wakeup wakeUpDecodeThread  is Started !");
+            return;
+        }
+        // 2.开始唤醒
+        if (wakeUpInitialRet == WAKEUP_INIT_SUCCEED) {
+            wakeUp();
+        } else {
+            LogUtil.d(TAG, "wakeup wakeUpInitialRet failed, not startWakeUp ");
+        }
+    }
+
+    @Override
+    public void stopWakeUp() {
+        if (wakeUpDecodeThread != null) {
+            wakeUpDecodeThread.stopWakeUp();
+        }
+        handler.removeCallbacksAndMessages(null);
+    }
+
+    @Override
+    public void releaseWakeUp() {
+        // 3.释放资源
+        int ret = wakeUpNative.wakeUpFree();
+        LogUtil.d(TAG, "wakeUpFree-ret:" + ret);
+    }
+
+    @Override
+    public void addWakeUpListener(IWakeUpListener listener) {
+        wakeUpListeners.add(listener);
+    }
+
+    /**
+     * 开始音频解码进行唤醒操作
+     */
+    private void wakeUp() {
+        wakeUpDecodeThread = new WakeUpDecodeThread(linkedBlockingDeque, wakeUpNative, handler);
+        wakeUpDecodeThread.setWakeUpListener(new WakeUpDecodeThread.IWakeUpListener() {
+            @Override
+            public void onWakeUpSucceed() {
+                // 唤醒成功
+                fireOnWakeUpSucceed();
+            }
+        });
+        wakeUpDecodeThread.startWakeUp();
+    }
+
+    private void fireOnWakeUpSucceed() {
+        for (IWakeUpListener listener : wakeUpListeners) {
+            listener.onWakeUpSucceed();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/wakeup/WakeUpNative.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,79 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.androidsystemimpl.wakeup;
+
+/**
+ * 唤醒服务-native-声明
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/21.
+ */
+public class WakeUpNative {
+
+    // 加载动态库.so文件
+    static {
+        System.loadLibrary("wakeup");
+        // 唤醒词解码so库
+        System.loadLibrary("bdEASRAndroid");
+    }
+
+    /**
+     * 初始化唤醒词成功
+     *
+     * @param wakeUpWd 唤醒词,例如“小度小度”
+     * @param sFile    附件中的资源文件, 唤醒词模型数据的文件绝对路径
+     * @param mode     缺省0即可
+     * @return 返回0表示初始化唤醒词成功
+     */
+    public native int wakeUpInitial(String wakeUpWd, String sFile, int mode);
+
+    /**
+     * 重制唤醒词
+     *
+     * @return 返回0表示成功
+     */
+    public native int wakeUpReset();
+
+    /**
+     * 唤醒解码
+     *
+     * @param data               音频数据
+     * @param dataLen            数据长度
+     * @param senArr             返回结果,如果唤醒词是小度小度”,唤醒成功后会赋值
+     * @param expectNum          传1
+     * @param wakeWord_frame_len 唤醒成功返回唤醒词长度
+     * @param is_confidence      true表示置信,false表示疑似唤醒
+     * @param voice_offset       唤醒词位置,需要用户传入,同时内部处理后传出
+     * @param bEd                是否为最后一帧数据
+     * @return 返回1表示唤醒,其他表示未唤醒
+     */
+    public native int wakeUpDecode(short[] data,
+                                   int dataLen,
+                                   String senArr,
+                                   int expectNum,
+                                   int wakeWord_frame_len,
+                                   boolean is_confidence,
+                                   int voice_offset,
+                                   boolean bEd
+    );
+
+    /**
+     * 释放资源
+     *
+     * @return 返回0表示成功
+     */
+    public native int wakeUpFree();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/androidsystemimpl/webview/BaseWebView.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.androidsystemimpl.webview;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.net.http.SslError;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.DownloadListener;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebSettings;
+import android.webkit.WebSettings.PluginState;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * common webView
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/19.
+ */
+@SuppressLint("SetJavaScriptEnabled")
+public class BaseWebView extends WebView implements IWebView {
+    private final List<IWebViewListener> webViewListeners =
+            Collections.synchronizedList(new ArrayList<IWebViewListener>());
+
+    public BaseWebView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public BaseWebView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    public BaseWebView(Context context) {
+        super(context);
+        init(context);
+    }
+
+    @SuppressWarnings("deprecation")
+    @SuppressLint("NewApi")
+    private void init(Context context) {
+        this.setVerticalScrollBarEnabled(false);
+        this.setHorizontalScrollBarEnabled(false);
+        if (Build.VERSION.SDK_INT < 19) {
+            removeJavascriptInterface("searchBoxJavaBridge_");
+        }
+
+        WebSettings localWebSettings = this.getSettings();
+        try {
+            // 禁用file协议,http://www.tuicool.com/articles/Q36ZfuF, 防止Android WebView File域攻击
+            localWebSettings.setAllowFileAccess(false);
+            localWebSettings.setSupportZoom(false);
+            localWebSettings.setBuiltInZoomControls(false);
+            localWebSettings.setUseWideViewPort(true);
+            localWebSettings.setDomStorageEnabled(true);
+            localWebSettings.setLoadWithOverviewMode(true);
+            localWebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
+            localWebSettings.setPluginState(PluginState.ON);
+            // 启用数据库
+            localWebSettings.setDatabaseEnabled(true);
+            // 设置定位的数据库路径
+            String dir = context.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
+            localWebSettings.setGeolocationDatabasePath(dir);
+            localWebSettings.setGeolocationEnabled(true);
+            localWebSettings.setJavaScriptEnabled(true);
+            localWebSettings.setSavePassword(false);
+            String agent = localWebSettings.getUserAgentString();
+
+            localWebSettings.setUserAgentString(agent);
+            // setCookie(context, ".baidu.com", bdussCookie);
+
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+        this.setWebViewClient(new BridgeWebViewClient());
+    }
+
+    private void setCookie(Context context, String domain, String sessionCookie) {
+        CookieSyncManager.createInstance(context);
+        CookieManager cookieManager = CookieManager.getInstance();
+        cookieManager.setAcceptCookie(true);
+        if (sessionCookie != null) {
+            // delete old cookies
+            cookieManager.removeSessionCookie();
+        }
+        try {
+            Thread.sleep(200);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        cookieManager.setCookie(domain, sessionCookie);
+
+        CookieSyncManager.createInstance(context);
+        CookieSyncManager.getInstance().sync();
+    }
+
+    public void setDownloadListener(DownloadListener listener) {
+        super.setDownloadListener(listener);
+    }
+
+    private WebViewClientListener webViewClientListen;
+
+    public void setWebViewClientListen(WebViewClientListener webViewClientListen) {
+        this.webViewClientListen = webViewClientListen;
+    }
+
+    /**
+     * 枚举网络加载返回状态 STATUS_FALSE:false
+     * STATUS_TRUE:true
+     * STATUS_UNKNOW:不知道
+     * NET_UNKNOWN:未知网络
+     */
+    public enum LoadingWebStatus {
+        STATUS_FALSE, STATUS_TRUE, STATUS_UNKNOW
+    }
+
+    @Override
+    public void linkClicked(String url) {
+        fireLinkClicked(url);
+    }
+
+    @Override
+    public void addWebViewListener(IWebViewListener listener) {
+        this.webViewListeners.add(listener);
+    }
+
+    void fireLinkClicked(String url) {
+        for (IWebViewListener listener : webViewListeners) {
+            listener.onLinkClicked(url);
+        }
+    }
+
+    public interface WebViewClientListener {
+        LoadingWebStatus shouldOverrideUrlLoading(WebView view, String url);
+
+        void onPageStarted(WebView view, String url, Bitmap favicon);
+
+        void onPageFinished(WebView view, String url);
+
+        void onReceivedError(WebView view, int errorCode, String description, String failingUrl);
+    }
+
+    public class BridgeWebViewClient extends WebViewClient {
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            LoadingWebStatus loadWebStatus = LoadingWebStatus.STATUS_UNKNOW;
+            String mUrl = url;
+            try {
+                mUrl = URLDecoder.decode(url, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            }
+            if (null != webViewClientListen) {
+                loadWebStatus = webViewClientListen.shouldOverrideUrlLoading(view, url);
+            }
+            if (LoadingWebStatus.STATUS_FALSE == loadWebStatus) {
+                return false;
+            } else if (LoadingWebStatus.STATUS_TRUE == loadWebStatus) {
+                return true;
+            } else {
+                return super.shouldOverrideUrlLoading(view, url);
+            }
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            if (null != webViewClientListen) {
+                webViewClientListen.onPageStarted(view, url, favicon);
+            }
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            if (null != webViewClientListen) {
+                webViewClientListen.onPageFinished(view, url);
+            }
+        }
+
+        @Override
+        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+            super.onReceivedError(view, errorCode, description, failingUrl);
+            if (null != webViewClientListen) {
+                webViewClientListen.onReceivedError(view, errorCode, description, failingUrl);
+            }
+        }
+
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+            // 当发生证书认证错误时,采用默认的处理方法handler.cancel(),停止加载问题页面
+            handler.cancel();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertHandler.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts;
+
+/**
+ * 定义Alerts模块的基础能力接口:开启与停止闹钟
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/5.
+ */
+public interface AlertHandler {
+    void startAlert(String alertToken);
+
+    void stopAlert(String alertToken);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertScheduler.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.util.DateFormatterUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * 单个的闹铃/提醒计时器
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/5.
+ */
+public class AlertScheduler extends Timer {
+    private static final String TAG = "AlertScheduler";
+    private final Alert alert;
+    private final AlertHandler handler;
+    private boolean active = false;
+
+    public AlertScheduler(final Alert alert, final AlertHandler handler) {
+        super();
+        String scheduledTimeStr = alert.getScheduledTime();
+        if (scheduledTimeStr != null && scheduledTimeStr.length() > 0) {
+            try {
+                Date date = DateFormatterUtil.toDate(alert.getScheduledTime());
+                long scheduledTime = date.getTime();
+                long delay = scheduledTime - System.currentTimeMillis();
+                LogUtil.d(TAG, "alert-delay start:" + delay);
+                if (delay > 0) {
+                    this.schedule(new TimerTask() {
+                        @Override
+                        public void run() {
+                            // 时间到了,开始闹铃
+                            setActive(true);
+                            handler.startAlert(alert.getToken());
+                        }
+                    }, delay);
+                }
+            } catch (ParseException e) {
+                e.printStackTrace();
+            }
+
+        }
+        this.alert = alert;
+        this.handler = handler;
+    }
+
+    public synchronized boolean isActive() {
+        return active;
+    }
+
+    public synchronized void setActive(boolean active) {
+        this.active = active;
+    }
+
+    @Override
+    public void cancel() {
+        super.cancel();
+        if (isActive()) {
+            handler.stopAlert(alert.getToken());
+            setActive(false);
+        }
+    }
+
+    public Alert getAlert() {
+        return alert;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/AlertsDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+import com.baidu.duer.dcs.devicemodule.alerts.message.AlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.AlertsStatePayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.DeleteAlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.SetAlertPayload;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
+import com.baidu.duer.dcs.systeminterface.IHandler;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.DateFormatterUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Alerts模块的核心处理逻辑,如执行SetAlert、DeleteAlert指令,上传SetAlertSucceeded、DeleteAlertSucceeded等事件,
+ * 以及维护自身的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class AlertsDeviceModule extends BaseDeviceModule implements AlertHandler {
+    private static final String TAG = AlertsDeviceModule.class.getSimpleName();
+    // 闹铃开始是播放的音频文件
+    private static final String ALARM_NAME = "assets://alarm.mp3";
+    // 已经离alert时间点超过30分钟了
+    private static final int MINUTES_AFTER_PAST_ALERT_EXPIRES = 30;
+    // 当前的闹钟/提醒
+    private final Map<String, AlertScheduler> schedulers;
+    // 当前处于播放的
+    private final Set<String> activeAlerts;
+    private final IAlertsDataStore dataStore;
+    // 播放闹铃/提醒的mediaPlayer
+    private IMediaPlayer mediaPlayer;
+    private IHandler handler;
+    private List<IAlertListener> alertListeners;
+
+    // 提醒的状态
+    private enum AlertState {
+        PLAYING,
+        INTERRUPTED,
+        FINISHED
+    }
+
+    private AlertState alertState = AlertState.FINISHED;
+
+    public AlertsDeviceModule(IMediaPlayer mediaPlayer, IAlertsDataStore dataStore,
+                              IMessageSender messageSender, IHandler handler) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.schedulers = new ConcurrentHashMap<>();
+        this.activeAlerts = new HashSet<>();
+        this.mediaPlayer = mediaPlayer;
+        this.dataStore = dataStore;
+        this.handler = handler;
+        this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+        this.alertListeners = Collections.synchronizedList(new ArrayList<IAlertListener>());
+        // 先读取历史保存到文件中的提醒
+        this.loadFromDisk();
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        String namespace = ApiConstants.NAMESPACE;
+        String name = ApiConstants.Events.AlertsState.NAME;
+        Header header = new Header(namespace, name);
+        Payload payload = getState();
+        return new ClientContext(header, payload);
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        String directiveName = directive.getName();
+        if (directiveName.equals(ApiConstants.Directives.SetAlert.NAME)) {
+            // 设置一个闹铃/提醒的指令处理逻辑
+            LogUtil.d(TAG, "alert-SetAlertPayload");
+            SetAlertPayload payload = (SetAlertPayload) directive.payload;
+
+            String alertToken = payload.getToken();
+            String scheduledTime = payload.getScheduledTime();
+            LogUtil.d(TAG, "alert-scheduledTime:" + scheduledTime);
+
+            // scheduledTime 时间为ISO8601格式转换为Date
+            try {
+                Date date = DateFormatterUtil.toDate(scheduledTime);
+                LogUtil.d(TAG, "alert-ms:" + date.getTime());
+                LogUtil.d(TAG, "alert-format:" + CommonUtil.formatToDataTime(date.getTime()));
+            } catch (ParseException e) {
+                e.printStackTrace();
+            }
+
+            SetAlertPayload.AlertType type = payload.getType();
+            // 如果存在一样的闹铃/提醒 就cancel掉
+            if (hasAlert(alertToken)) {
+                AlertScheduler scheduler = getScheduler(alertToken);
+                if (scheduler.getAlert().getScheduledTime().equals(scheduledTime)) {
+                    return;
+                } else {
+                    scheduler.cancel();
+                }
+            }
+            // 设置一个闹铃/提醒
+            Alert alert = new Alert(alertToken, type, scheduledTime);
+            add(alert, false);
+        } else if (ApiConstants.Directives.DeleteAlert.NAME.equals(directiveName)) {
+            // 删除一个闹铃/提醒的指令处理
+            LogUtil.d(TAG, "alert-DeleteAlertPayload");
+            DeleteAlertPayload payload = (DeleteAlertPayload) directive.getPayload();
+            delete(payload.getToken());
+        } else {
+            String message = "Alert cannot handle the directive";
+            throw (new HandleDirectiveException(
+                    HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+        }
+    }
+
+    @Override
+    public void startAlert(final String alertToken) {
+        LogUtil.d(TAG, "alert-startAlert");
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                activeAlerts.add(alertToken);
+                sendAlertsRequest(ApiConstants.Events.AlertStarted.NAME, alertToken);
+                fireOnAlertStarted(alertToken);
+                if (!isAlarming()) {
+                    alertState = AlertState.PLAYING;
+                    if (mediaPlayer != null) {
+                        mediaPlayer.play(new IMediaPlayer.MediaResource(ALARM_NAME));
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public void stopAlert(final String alertToken) {
+        LogUtil.d(TAG, "alert-stopAlert");
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                activeAlerts.remove(alertToken);
+                schedulers.remove(alertToken);
+                alertStopped(alertToken);
+                if (!hasActiveAlerts()) {
+                    alertState = AlertState.FINISHED;
+                    if (mediaPlayer != null) {
+                        mediaPlayer.pause();
+                    }
+                }
+            }
+        });
+    }
+
+    private void sendAlertEnteredBackgroundEvent(String alertToken) {
+        sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
+    }
+
+    private void sendAlertEnteredBackgroundEvent() {
+        if (hasActiveAlerts()) {
+            for (String alertToken : getActiveAlerts()) {
+                sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
+            }
+        }
+    }
+
+    private void sendAlertEnteredForegroundEvent(String alertToken) {
+        sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
+    }
+
+    public void sendAlertEnteredForegroundEvent() {
+        if (hasActiveAlerts()) {
+            for (String alertToken : getActiveAlerts()) {
+                sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
+            }
+        }
+    }
+
+    public void sendAlertStartedEvent(boolean isSpeaking, String alertToken) {
+        if (isSpeaking) {
+            sendAlertEnteredBackgroundEvent(alertToken);
+        } else {
+            sendAlertEnteredForegroundEvent(alertToken);
+        }
+    }
+
+    private void sendAlertsRequest(String eventName, String alertToken) {
+        Header header = new MessageIdHeader(ApiConstants.NAMESPACE, eventName);
+        Payload payload = new AlertPayload(alertToken);
+        Event event = new Event(header, payload);
+        messageSender.sendEvent(event);
+    }
+
+    /**
+     * 设置提醒/闹钟成功或者失败的上报
+     *
+     * @param alertToken alertToken
+     * @param success    success
+     */
+    private void setAlert(String alertToken, boolean success) {
+        String eventName = success ? ApiConstants.Events.SetAlertSucceeded.NAME :
+                ApiConstants.Events.SetAlertFailed.NAME;
+        sendAlertsRequest(eventName, alertToken);
+    }
+
+    /**
+     * 删除提醒/闹钟成功或者失败的上报
+     *
+     * @param alertToken alertToken
+     * @param success    success
+     */
+    private void deleteAlert(String alertToken, boolean success) {
+        String eventName = success ? ApiConstants.Events.DeleteAlertSucceeded.NAME :
+                ApiConstants.Events.DeleteAlertFailed.NAME;
+        sendAlertsRequest(eventName, alertToken);
+    }
+
+    /**
+     * 到了定点时间,触发了提醒/闹钟 时上报
+     *
+     * @param alertToken alertToken
+     */
+    private void fireOnAlertStarted(String alertToken) {
+        for (IAlertListener listener : alertListeners) {
+            listener.onAlertStarted(alertToken);
+        }
+    }
+
+    /**
+     * 上报AlertStopped事件
+     *
+     * @param alertToken alertToken 闹钟/提醒 唯一的标识
+     */
+    private void alertStopped(String alertToken) {
+        sendAlertsRequest(ApiConstants.Events.AlertStopped.NAME, alertToken);
+    }
+
+    /**
+     * 从文件里读取之前设置的闹铃/提醒
+     */
+    private void loadFromDisk() {
+        dataStore.readFromDisk(new IAlertsDataStore.ReadResultListener() {
+
+            @Override
+            public void onSucceed(List<Alert> alerts) {
+                if (alerts == null || alerts.size() <= 0) {
+                    return;
+                }
+                List<Alert> droppedAlerts = new LinkedList<>();
+                for (final Alert alert : alerts) {
+                    String scheduledTime = alert.getScheduledTime();
+                    if (scheduledTime != null && scheduledTime.length() > 0) {
+                        try {
+                            Date date = DateFormatterUtil.toDate(alert.getScheduledTime());
+                            long scheduledTimeLong = date.getTime();
+                            // 已经离alert时间点超过30分钟了
+                            long cur = System.currentTimeMillis();
+                            if (scheduledTimeLong + MINUTES_AFTER_PAST_ALERT_EXPIRES * 60 * 1000 < cur) {
+                                droppedAlerts.add(alert);
+                            } else {
+                                add(alert, true);
+                            }
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+                for (Alert alert : droppedAlerts) {
+                    drop(alert);
+                }
+            }
+
+            @Override
+            public void onFailed(String errMsg) {
+
+            }
+        });
+    }
+
+    public boolean isAlarming() {
+        return alertState == AlertState.PLAYING;
+    }
+
+    private synchronized boolean hasAlert(String alertToken) {
+        return schedulers.containsKey(alertToken);
+    }
+
+    public synchronized boolean hasActiveAlerts() {
+        return activeAlerts != null && activeAlerts.size() > 0;
+    }
+
+    private synchronized Set<String> getActiveAlerts() {
+        return activeAlerts;
+    }
+
+    private synchronized AlertScheduler getScheduler(String alertToken) {
+        return schedulers.get(alertToken);
+    }
+
+    /**
+     * 设置一个闹钟/提醒
+     *
+     * @param alert         alert
+     * @param suppressEvent suppressEvent 是否需要上报事件
+     */
+    private synchronized void add(final Alert alert, final boolean suppressEvent) {
+        LogUtil.d(TAG, "add alertToken: " + alert.getToken());
+        final AlertScheduler scheduler = new AlertScheduler(alert, this);
+        schedulers.put(alert.getToken(), scheduler);
+        dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
+
+            @Override
+            public void onSucceed() {
+                if (!suppressEvent) {
+                    setAlert(alert.getToken(), true);
+                }
+            }
+
+            @Override
+            public void onFailed(String errMsg) {
+                if (!suppressEvent) {
+                    setAlert(alert.getToken(), false);
+                }
+                schedulers.remove(alert.getToken());
+                scheduler.cancel();
+            }
+        });
+    }
+
+    /**
+     * 删除一个闹钟
+     *
+     * @param alertToken alertToken
+     */
+    private synchronized void delete(final String alertToken) {
+        LogUtil.d(TAG, "delete alertToken: " + alertToken);
+        final AlertScheduler scheduler = schedulers.remove(alertToken);
+        if (scheduler != null) {
+            final Alert alert = scheduler.getAlert();
+            dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
+                @Override
+                public void onSucceed() {
+                    LogUtil.d(TAG, "delete  onSucceed");
+                    scheduler.cancel();
+                    deleteAlert(alert.getToken(), true);
+                }
+
+                @Override
+                public void onFailed(String errMsg) {
+                    LogUtil.d(TAG, "delete  onFailed");
+                    deleteAlert(alert.getToken(), false);
+                }
+            });
+        } else {
+            //  本地没有查询到就上报删除失败的事件
+            LogUtil.d(TAG, "delete  scheduler is  null");
+            deleteAlert(alertToken, false);
+        }
+    }
+
+    private synchronized List<Alert> getAllAlerts() {
+        List<Alert> list = new ArrayList<>(schedulers.size());
+        for (AlertScheduler scheduler : schedulers.values()) {
+            list.add(scheduler.getAlert());
+        }
+        return list;
+    }
+
+    /**
+     * 如果有正在播放的闹铃/提醒,就停止播放并删除该闹铃/提醒
+     */
+    public synchronized void stopActiveAlert() {
+        for (String alertToken : activeAlerts) {
+            stopAlert(alertToken);
+            return;
+        }
+    }
+
+    private void drop(final Alert alert) {
+        alertStopped(alert.getToken());
+    }
+
+    private synchronized AlertsStatePayload getState() {
+        List<Alert> all = new ArrayList<>(schedulers.size());
+        List<Alert> active = new ArrayList<>(activeAlerts.size());
+        for (AlertScheduler scheduler : schedulers.values()) {
+            Alert alert = scheduler.getAlert();
+            all.add(alert);
+
+            if (activeAlerts.contains(alert.getToken())) {
+                active.add(alert);
+            }
+        }
+        return new AlertsStatePayload(all, active);
+    }
+
+    @Override
+    public void release() {
+        if (mediaPlayer != null) {
+            mediaPlayer.release();
+            mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+            mediaPlayer = null;
+        }
+        for (AlertScheduler scheduler : schedulers.values()) {
+            scheduler.cancel();
+        }
+        alertListeners.clear();
+    }
+
+    private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+        @Override
+        public void onPrepared() {
+            super.onPrepared();
+            mediaPlayer.setActive(true);
+        }
+
+        @Override
+        public void onCompletion() {
+            alertState = AlertState.FINISHED;
+            mediaPlayer.setActive(false);
+        }
+
+        @Override
+        public void onError(String error, IMediaPlayer.ErrorType errorType) {
+            super.onError(error, errorType);
+            alertState = AlertState.FINISHED;
+            mediaPlayer.setActive(false);
+        }
+    };
+
+
+    /**
+     * 闹铃/提醒回调
+     */
+    public interface IAlertListener {
+        /**
+         * 到了定点时间,触发了提醒/闹钟 时上报
+         *
+         * @param alertToken alertToken
+         */
+        void onAlertStarted(String alertToken);
+    }
+
+    public void addAlertListener(IAlertListener listener) {
+        this.alertListeners.add(listener);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts;
+
+/**
+ * 定义了表示Alerts模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.alerts";
+    public static final String NAME = "AlertsInterface";
+
+    public static final class Events {
+        public static final class SetAlertSucceeded {
+            public static final String NAME = SetAlertSucceeded.class.getSimpleName();
+        }
+
+        public static final class SetAlertFailed {
+            public static final String NAME = SetAlertFailed.class.getSimpleName();
+        }
+
+        public static final class DeleteAlertSucceeded {
+            public static final String NAME = DeleteAlertSucceeded.class.getSimpleName();
+        }
+
+        public static final class DeleteAlertFailed {
+            public static final String NAME = DeleteAlertFailed.class.getSimpleName();
+        }
+
+        public static final class AlertStarted {
+            public static final String NAME = AlertStarted.class.getSimpleName();
+        }
+
+        public static final class AlertStopped {
+            public static final String NAME = AlertStopped.class.getSimpleName();
+        }
+
+        public static final class AlertsState {
+            public static final String NAME = AlertsState.class.getSimpleName();
+        }
+
+        public static final class AlertEnteredForeground {
+            public static final String NAME = AlertEnteredForeground.class.getSimpleName();
+        }
+
+        public static final class AlertEnteredBackground {
+            public static final String NAME = AlertEnteredBackground.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class SetAlert {
+            public static final String NAME = SetAlert.class.getSimpleName();
+        }
+
+        public static final class DeleteAlert {
+            public static final String NAME = DeleteAlert.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/Alert.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Alert 数据对象(model)
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class Alert {
+    private final String token;
+    private final SetAlertPayload.AlertType type;
+    // 触发时间,ISO 8601格式
+    private final String scheduledTime;
+
+    @JsonCreator
+    public Alert(@JsonProperty("token") String token, @JsonProperty("type") SetAlertPayload.AlertType type,
+                 @JsonProperty("scheduledTime") String scheduledTime) {
+        this.token = token;
+        this.type = type;
+        this.scheduledTime = scheduledTime;
+    }
+
+    public String getToken() {
+        return this.token;
+    }
+
+    public SetAlertPayload.AlertType getType() {
+        return this.type;
+    }
+
+    public String getScheduledTime() {
+        return scheduledTime;
+    }
+
+    @Override
+    public int hashCode() {
+        return ((token == null) ? 0 : token.hashCode());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Alert other = (Alert) obj;
+        if (token == null) {
+            if (other.token != null) {
+                return false;
+            }
+        } else if (!token.equals(other.token)) {
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Alerts模块上报各种事件的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class AlertPayload extends Payload {
+    // 本闹钟的唯一token
+    public String token;
+
+    public AlertPayload(String token) {
+        this.token = token;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/AlertsStatePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.util.List;
+
+/**
+ * Alerts模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public class AlertsStatePayload extends Payload {
+    public List<Alert> allAlerts;
+    public List<Alert> activeAlerts;
+
+    public AlertsStatePayload(List<Alert> all, List<Alert> active) {
+        this.allAlerts = all;
+        this.activeAlerts = active;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/DeleteAlertPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.io.Serializable;
+
+/**
+ * DeleteAlert指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com  on 2017/5/17.
+ */
+public class DeleteAlertPayload extends Payload implements Serializable {
+    public String token;
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/alerts/message/SetAlertPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.alerts.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.io.Serializable;
+
+/**
+ * SetAlert指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class SetAlertPayload extends Payload implements Serializable {
+    public enum AlertType {
+        ALARM,
+        TIMER
+    }
+
+    // alert唯一token
+    private String token;
+    private AlertType type;
+    // 格式:2017-05-17T03:00:00+0000
+    private String scheduledTime;
+    private String content;
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public void setType(String type) {
+        this.type = AlertType.valueOf(type.toUpperCase());
+    }
+
+    public AlertType getType() {
+        return type;
+    }
+
+    @JsonProperty("scheduledTime")
+    public void setScheduledTime(String dateTime) {
+        scheduledTime = dateTime;
+    }
+
+    public String getScheduledTime() {
+        return scheduledTime;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    @Override
+    public String toString() {
+        return "SetAlertPayload{"
+                + "token='"
+                + token
+                + '\''
+                + ", type="
+                + type
+                + ", scheduledTime='"
+                + scheduledTime
+                + '\''
+                + '}';
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer;
+
+/**
+ * 定义了表示Audio Player模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.audio_player";
+    public static final String NAME = "AudioPlayerInterface";
+
+    public static final class Events {
+        public static final class PlaybackStarted {
+            public static final String NAME = PlaybackStarted.class.getSimpleName();
+        }
+
+        public static final class PlaybackNearlyFinished {
+            public static final String NAME = PlaybackNearlyFinished.class.getSimpleName();
+        }
+
+        public static final class PlaybackStutterStarted {
+            public static final String NAME = PlaybackStutterStarted.class.getSimpleName();
+        }
+
+        public static final class PlaybackStutterFinished {
+            public static final String NAME = PlaybackStutterFinished.class.getSimpleName();
+        }
+
+        public static final class PlaybackFinished {
+            public static final String NAME = PlaybackFinished.class.getSimpleName();
+        }
+
+        public static final class PlaybackFailed {
+            public static final String NAME = PlaybackFailed.class.getSimpleName();
+        }
+
+        public static final class PlaybackStopped {
+            public static final String NAME = PlaybackStopped.class.getSimpleName();
+        }
+
+        public static final class PlaybackPaused {
+            public static final String NAME = PlaybackPaused.class.getSimpleName();
+        }
+
+        public static final class PlaybackResumed {
+            public static final String NAME = PlaybackResumed.class.getSimpleName();
+        }
+
+        public static final class PlaybackQueueCleared {
+            public static final String NAME = PlaybackQueueCleared.class.getSimpleName();
+        }
+
+        public static final class ProgressReportDelayElapsed {
+            public static final String NAME = ProgressReportDelayElapsed.class.getSimpleName();
+        }
+
+        public static final class ProgressReportIntervalElapsed {
+            public static final String NAME = ProgressReportIntervalElapsed.class
+                    .getSimpleName();
+        }
+
+        public static final class PlaybackState {
+            public static final String NAME = PlaybackState.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class Play {
+            public static final String NAME = Play.class.getSimpleName();
+        }
+
+        public static final class Stop {
+            public static final String NAME = Stop.class.getSimpleName();
+        }
+
+        public static final class ClearQueue {
+            public static final String NAME = ClearQueue.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/AudioPlayerDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.ClearQueuePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStatePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.StopPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayStateReport;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerProgressReporter;
+import com.baidu.duer.dcs.devicemodule.audioplayer.report.AudioPlayerTimer;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 音乐播放的端能力实现,处理指令:Play,Stop,ClearQueue
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class AudioPlayerDeviceModule extends BaseDeviceModule {
+    private static final String TAG = AudioPlayerDeviceModule.class.getSimpleName();
+    // 播放列表,先进先出
+    private LinkedList<PlayPayload.Stream> playQueue = new LinkedList<>();
+    // 当前stream的token
+    private String latestStreamToken = "";
+    // 当前manager的播放器
+    private IMediaPlayer mediaPlayer;
+    // 播放上报
+    private AudioPlayStateReport audioPlayStateReport;
+    // 开始时的缓冲时间
+    private long bufferingStartMilliseconds;
+    // 结束时的缓冲时间
+    private long bufferingEndMilliseconds;
+    // 用来统计状态的时间间隔offsetInMilliseconds
+    private AudioPlayerTimer timer;
+    // 播放状态的上报eg:暂停,完成等
+    private AudioPlayerProgressReporter progressReporter;
+    // 回调接口
+    private List<IMediaPlayer.IMediaPlayerListener> audioPlayerListeners;
+
+    public AudioPlayerDeviceModule(IMediaPlayer mediaPlayer,
+                                   IMessageSender messageSender) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.mediaPlayer = mediaPlayer;
+        this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+        this.audioPlayStateReport = new AudioPlayStateReport(getNameSpace(),
+                messageSender,
+                audioPlayStateReportListener);
+        this.timer = new AudioPlayerTimer();
+        this.progressReporter = new AudioPlayerProgressReporter(
+                new ProgressReportDelayEventRunnable(audioPlayStateReport),
+                new ProgressReportIntervalEventRunnable(audioPlayStateReport), timer);
+        this.audioPlayerListeners = Collections.synchronizedList(
+                new ArrayList<IMediaPlayer.IMediaPlayerListener>());
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        String namespace = ApiConstants.NAMESPACE;
+        String name = ApiConstants.Events.PlaybackState.NAME;
+        Header header = new Header(namespace, name);
+        PlaybackStatePayload payload = new PlaybackStatePayload(latestStreamToken,
+                mediaPlayer.getCurrentPosition(),
+                audioPlayStateReport.getState().name());
+        return new ClientContext(header, payload);
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        LogUtil.d(TAG, "dcs-play-directive:" + directive.rawMessage);
+        String directiveName = directive.getName();
+        LogUtil.d(TAG, "dcs-play-directiveName:" + directiveName);
+        if (ApiConstants.Directives.Play.NAME.equals(directiveName)) {
+            handlePlay((PlayPayload) directive.getPayload());
+        } else if (ApiConstants.Directives.Stop.NAME.equals(directiveName)) {
+            handleStop((StopPayload) directive.getPayload());
+        } else if (ApiConstants.Directives.ClearQueue.NAME.equals(directiveName)) {
+            handleClearQueue((ClearQueuePayload) directive.getPayload());
+        } else {
+            String message = "audioPlayer cannot handle the directive";
+            throw (new HandleDirectiveException(
+                    HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+        }
+    }
+
+    /**
+     * 处理播放指令(Play)
+     *
+     * @param payload payload
+     */
+    private void handlePlay(PlayPayload payload) {
+        PlayPayload.AudioItem item = payload.audioItem;
+        if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ALL) {
+            clearAll();
+        } else if (payload.playBehavior == PlayPayload.PlayBehavior.REPLACE_ENQUEUED) {
+            clearEnqueued();
+        }
+        final PlayPayload.Stream stream = item.stream;
+        String streamUrl = stream.url;
+        String streamId = stream.token;
+        long offset = stream.offsetInMilliseconds;
+        LogUtil.i(TAG, "URL:" + streamUrl);
+        LogUtil.i(TAG, "StreamId:" + streamId);
+        LogUtil.i(TAG, "Offset:" + offset);
+        add(stream);
+    }
+
+    /**
+     * 处理停止指令(Stop)
+     *
+     * @param payload payload
+     */
+    private void handleStop(StopPayload payload) {
+        stop();
+    }
+
+    /**
+     * 处理清空队列指令(Stop)
+     *
+     * @param clearQueuePayload clearQueuePayload
+     */
+    private void handleClearQueue(ClearQueuePayload clearQueuePayload) {
+        // 清除播放列表,并停止当前播放的音频(如果有)
+        if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ALL) {
+            audioPlayStateReport.clearQueueAll();
+            clearAll();
+        } else if (clearQueuePayload.clearBehavior == ClearQueuePayload.ClearBehavior.CLEAR_ENQUEUED) {
+            // 清除播放列表,但不影响当前播放
+            audioPlayStateReport.clearQueueEnqueued();
+            clearEnqueued();
+        }
+    }
+
+    private void add(PlayPayload.Stream stream) {
+        String expectedPreviousToken = stream.expectedPreviousToken;
+        boolean startPlaying = playQueue.isEmpty();
+        if (expectedPreviousToken == null || latestStreamToken.isEmpty()
+                || latestStreamToken.equals(expectedPreviousToken)) {
+            playQueue.add(stream);
+        }
+        LogUtil.d(TAG, " coming  playQueue size :" + playQueue.size());
+        if (startPlaying) {
+            startPlay();
+        }
+    }
+
+    /**
+     * 开始播放音乐
+     */
+    private void startPlay() {
+        if (playQueue.isEmpty()) {
+            LogUtil.d(TAG, "startPlay-playQueue isEmpty !!");
+            return;
+        }
+        PlayPayload.Stream currentStream = playQueue.peek();
+        if (currentStream == null) {
+            return;
+        }
+        latestStreamToken = currentStream.token;
+        String url = currentStream.url;
+        // 从哪个位置开始播放
+        long offset = currentStream.offsetInMilliseconds;
+        // 判断是否是流类型还是URL类型
+        if (currentStream.hasAttachedContent()) {
+            mediaPlayer.play(new IMediaPlayer.MediaResource(currentStream.getAttachedContent()));
+        } else {
+            mediaPlayer.play(new IMediaPlayer.MediaResource(url));
+        }
+        mediaPlayer.seekTo((int) offset);
+    }
+
+    private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+        // 是否处于暂停
+        private boolean isPause;
+        // 是否第一次到达了100
+        private boolean stutterFinished;
+        // 是否处于上报ProgressReport事件中
+        private boolean progressReporting;
+        // 是否处于缓冲中
+        private boolean bufferUnderRunInProgress;
+
+        @Override
+        public void onInit() {
+            super.onInit();
+            LogUtil.d(TAG, "onInit");
+            isPause = false;
+            stutterFinished = false;
+            progressReporting = false;
+            bufferUnderRunInProgress = false;
+        }
+
+        @Override
+        public void onPrepared() {
+            super.onPrepared();
+            LogUtil.d(TAG, "onPrepared");
+            fireOnPrepared();
+        }
+
+        @Override
+        public void onPlaying() {
+            super.onPlaying();
+            LogUtil.d(TAG, "onPlaying");
+            // 暂停后继续播放
+            if (isPause) {
+                isPause = false;
+                audioPlayStateReport.playbackResumed();
+            } else {
+                // 第一次播放
+                PlayPayload.Stream stream = playQueue.peek();
+                if (stream == null) {
+                    return;
+                }
+                long offset = stream.offsetInMilliseconds;
+                LogUtil.d(TAG, "onPlaying---Duration----:" + mediaPlayer.getDuration());
+                timer.reset(offset, mediaPlayer.getDuration());
+
+                // 上报PlaybackStarted事件
+                audioPlayStateReport.playbackStarted();
+            }
+            startTimerAndProgressReporter();
+            fireOnPlaying();
+        }
+
+        @Override
+        public void onPaused() {
+            LogUtil.d(TAG, "onPaused");
+            stopTimerAndProgressReporter();
+            isPause = true;
+            audioPlayStateReport.playbackPaused();
+            fireOnPaused();
+        }
+
+        @Override
+        public void onStopped() {
+            super.onStopped();
+            stopTimerAndProgressReporter();
+            audioPlayStateReport.playbackStopped();
+            fireOnStopped();
+        }
+
+        @Override
+        public void onCompletion() {
+            LogUtil.d(TAG, "onCompletion");
+            stopTimerAndProgressReporter();
+            playQueue.poll();
+            audioPlayStateReport.playbackFinished();
+            audioPlayStateReport.playbackNearlyFinished();
+            if (!playQueue.isEmpty()) {
+                startPlay();
+            }
+            fireOnCompletion();
+        }
+
+        @Override
+        public void onRelease() {
+            LogUtil.d(TAG, "onError");
+            stopTimerAndProgressReporter();
+            fireOnRelease();
+        }
+
+        @Override
+        public void onError(String error, IMediaPlayer.ErrorType errorType) {
+            LogUtil.d(TAG, "onError");
+            playQueue.clear();
+            audioPlayStateReport.playbackFailed(errorType);
+            stopTimerAndProgressReporter();
+            fireOnError(error, errorType);
+        }
+
+        @Override
+        public void onBufferingUpdate(int percent) {
+            LogUtil.d(TAG, "onBufferingUpdate:" + percent);
+            fireOnBufferingUpdate(percent);
+            PlayPayload.Stream stream = playQueue.peek();
+            if (stream == null) {
+                return;
+            }
+            // Play指令有progressReportDelayInMilliseconds
+            if (!progressReporting && stream.getProgressReportRequired()) {
+                LogUtil.d(TAG, "onBufferingUpdate:" + percent);
+                progressReporting = true;
+                progressReporter.disable();
+                progressReporter.setup(stream.progressReport);
+                long offset = stream.offsetInMilliseconds;
+                timer.reset(offset, mediaPlayer.getDuration());
+                startTimerAndProgressReporter();
+            }
+
+            // 已经缓冲完成了
+            if (stutterFinished) {
+                return;
+            }
+            // 开始缓冲
+            if (!bufferUnderRunInProgress) {
+                LogUtil.d(TAG, "==playbackStutterStarted");
+                bufferUnderRunInProgress = true;
+                bufferingStartMilliseconds = System.currentTimeMillis();
+                audioPlayStateReport.playbackStutterStarted();
+            }
+            // 缓冲完毕后上报playbackStutterFinished
+            if (percent >= 100) {
+                stutterFinished = true;
+                bufferingEndMilliseconds = System.currentTimeMillis();
+                audioPlayStateReport.playbackStutterFinished();
+            }
+        }
+    };
+
+    private void startTimerAndProgressReporter() {
+        timer.start();
+        if (progressReporter.isSetup()) {
+            progressReporter.start();
+        }
+    }
+
+    private void stopTimerAndProgressReporter() {
+        timer.stop();
+        progressReporter.stop();
+    }
+
+    private void clearAll() {
+        stop();
+        playQueue.clear();
+    }
+
+    private void clearEnqueued() {
+        PlayPayload.Stream top = playQueue.poll();
+        playQueue.clear();
+        if (top != null) {
+            playQueue.add(top);
+        }
+    }
+
+    private void stop() {
+        if (!playQueue.isEmpty() && isPlayingOrPaused()) {
+            stopTimerAndProgressReporter();
+            // 要把播放策略中的对应的那一条删除了
+            mediaPlayer.stop();
+        }
+    }
+
+    private boolean isPlaying() {
+        return (audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PLAYING
+                || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED
+                || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.BUFFER_UNDERRUN);
+    }
+
+    private boolean isPlayingOrPaused() {
+        return isPlaying() || audioPlayStateReport.getState() == AudioPlayStateReport.AudioPlayerState.PAUSED;
+    }
+
+    @Override
+    public void release() {
+        if (mediaPlayer != null) {
+            mediaPlayer.release();
+            mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+        }
+        stopTimerAndProgressReporter();
+        audioPlayerListeners.clear();
+    }
+
+    /**
+     * 播放上报时需要的信息
+     */
+    private AudioPlayStateReport.AudioPlayStateReportListener audioPlayStateReportListener =
+            new AudioPlayStateReport.AudioPlayStateReportListener() {
+                @Override
+                public String getCurrentStreamToken() {
+                    return latestStreamToken;
+                }
+
+                @Override
+                public long getCurrentOffsetInMilliseconds() {
+                    return getCurrentOffsetInMillisecondsByTime();
+                }
+
+                @Override
+                public long getStutterDurationInMilliseconds() {
+                    // 缓冲时间ms
+                    return bufferingEndMilliseconds - bufferingStartMilliseconds;
+                }
+            };
+
+    private long getCurrentOffsetInMillisecondsByTime() {
+        AudioPlayStateReport.AudioPlayerState playerActivity = audioPlayStateReport.getState();
+        long offset;
+        switch (playerActivity) {
+            case PLAYING:
+            case PAUSED:
+            case BUFFER_UNDERRUN:
+            case STOPPED:
+            case FINISHED:
+                offset = timer.getOffsetInMilliseconds();
+                break;
+            case IDLE:
+            default:
+                offset = 0;
+        }
+        LogUtil.d(TAG, "getCurrentOffsetInMilliseconds offset:" + offset);
+        return offset;
+    }
+
+    private static class ProgressReportDelayEventRunnable implements Runnable {
+        private final AudioPlayStateReport audioPlayStateReport;
+
+        ProgressReportDelayEventRunnable(AudioPlayStateReport audioPlayStateReport) {
+            this.audioPlayStateReport = audioPlayStateReport;
+        }
+
+        @Override
+        public void run() {
+            audioPlayStateReport.reportProgressDelay();
+        }
+    }
+
+    private static class ProgressReportIntervalEventRunnable implements Runnable {
+        private final AudioPlayStateReport audioPlayStateReport;
+
+        ProgressReportIntervalEventRunnable(AudioPlayStateReport audioPlayStateReport) {
+            this.audioPlayStateReport = audioPlayStateReport;
+        }
+
+        @Override
+        public void run() {
+            audioPlayStateReport.reportProgressInterval();
+        }
+    }
+
+    private void fireOnPrepared() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onPrepared();
+        }
+    }
+
+    private void fireOnRelease() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onRelease();
+        }
+    }
+
+    private void fireOnPlaying() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onPlaying();
+        }
+    }
+
+    private void fireOnPaused() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onPaused();
+        }
+    }
+
+    private void fireOnStopped() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onStopped();
+        }
+    }
+
+    private void fireOnCompletion() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onCompletion();
+        }
+    }
+
+    private void fireOnError(String error, IMediaPlayer.ErrorType errorType) {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onError(error, errorType);
+        }
+    }
+
+    private void fireOnBufferingUpdate(int percent) {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onBufferingUpdate(percent);
+        }
+    }
+
+    private void fireBufferingStart() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onBufferingStart();
+        }
+    }
+
+    private void fireBufferingEnd() {
+        for (IMediaPlayer.IMediaPlayerListener listener : audioPlayerListeners) {
+            listener.onBufferingEnd();
+        }
+    }
+
+    public void addAudioPlayListener(IMediaPlayer.IMediaPlayerListener listener) {
+        audioPlayerListeners.add(listener);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/AudioPlayerPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块上报各种事件的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/4.
+ */
+public class AudioPlayerPayload extends Payload {
+    public String token;
+    public long offsetInMilliseconds;
+
+    public AudioPlayerPayload(String token, long offsetInMilliseconds) {
+        this.token = token;
+        this.offsetInMilliseconds = offsetInMilliseconds;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/ClearQueuePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ClearQueue指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ClearQueuePayload extends Payload {
+    public enum ClearBehavior {
+        CLEAR_ENQUEUED,
+        CLEAR_ALL
+    }
+
+    public ClearBehavior clearBehavior;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlayPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+import java.io.InputStream;
+import java.io.Serializable;
+
+/**
+ * Audio Player模块Play指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class PlayPayload extends Payload {
+    public PlayBehavior playBehavior;
+    public AudioItem audioItem;
+
+    public enum PlayBehavior {
+        REPLACE_ALL,
+        ENQUEUE,
+        REPLACE_ENQUEUED
+    }
+
+    public static class AudioItem implements Serializable {
+        public String audioItemId;
+        public Stream stream;
+    }
+
+    public static class Stream implements Serializable {
+        public String url;
+        public String token;
+        public String expiryTime;
+        public long offsetInMilliseconds;
+        public String expectedPreviousToken;
+        public String streamFormat;
+        public boolean urlIsAContentId;
+        public ProgressReport progressReport;
+        @JsonIgnore
+        public InputStream attachedContent;
+
+        public boolean getProgressReportRequired() {
+            return progressReport != null && progressReport.isRequired();
+        }
+
+        public void setUrl(String url) {
+            urlIsAContentId = url.startsWith("cid");
+            if (urlIsAContentId) {
+                this.url = url.substring(4);
+            } else {
+                this.url = url;
+            }
+        }
+
+        public boolean requiresAttachedContent() {
+            return urlIsAContentId && !hasAttachedContent();
+        }
+
+        public boolean hasAttachedContent() {
+            return attachedContent != null;
+        }
+
+        @JsonIgnore
+        public InputStream getAttachedContent() {
+            return attachedContent;
+        }
+    }
+
+    public static class ProgressReport implements Serializable {
+        public long progressReportDelayInMilliseconds;
+        public long progressReportIntervalInMilliseconds;
+
+        public boolean isRequired() {
+            return progressReportDelayInMilliseconds > 0 || progressReportIntervalInMilliseconds > 0;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackFailedPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+
+/**
+ * Audio Player模块上报PlaybackFailed事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/8.
+ */
+public class PlaybackFailedPayload extends Payload {
+    private String token;
+    private PlaybackStatePayload currentPlaybackState;
+    private ErrorStructure error;
+
+    public PlaybackFailedPayload(String token, PlaybackStatePayload playbackState,
+                                 IMediaPlayer.ErrorType errorType) {
+        this.token = token;
+        this.currentPlaybackState = playbackState;
+        error = new ErrorStructure(errorType);
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public PlaybackStatePayload getCurrentPlaybackState() {
+        return currentPlaybackState;
+    }
+
+    public ErrorStructure getError() {
+        return error;
+    }
+
+    private static final class ErrorStructure {
+        private IMediaPlayer.ErrorType type;
+        private String message;
+
+        public ErrorStructure(IMediaPlayer.ErrorType type) {
+            this.type = type;
+            this.message = type.getMessage();
+        }
+
+        public IMediaPlayer.ErrorType getType() {
+            return type;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStatePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class PlaybackStatePayload extends Payload {
+    public String token;
+    public long offsetInMilliseconds;
+    public String playerActivity;
+
+    public PlaybackStatePayload(String token, long offsetInMilliseconds, String playerActivity) {
+        this.token = token;
+        this.offsetInMilliseconds = offsetInMilliseconds;
+        this.playerActivity = playerActivity;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/PlaybackStutterFinishedPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+/**
+ * Audio Player模块上报PlaybackStutterFinished事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/4.
+ */
+public class PlaybackStutterFinishedPayload extends AudioPlayerPayload {
+    public long stutterDurationInMilliseconds;
+
+    public PlaybackStutterFinishedPayload(String token, long offsetInMilliseconds,
+                                          long stutterDurationInMilliseconds) {
+        super(token, offsetInMilliseconds);
+        this.stutterDurationInMilliseconds = stutterDurationInMilliseconds;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/message/StopPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Audio Player模块Stop指令对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/6.
+ */
+public class StopPayload extends Payload {
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayStateReport.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.AudioPlayerPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackFailedPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStatePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlaybackStutterFinishedPayload;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+
+/**
+ * Audio Player模块各种事件上报的处理,同时维护当前的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class AudioPlayStateReport {
+    public enum AudioPlayerState {
+        IDLE,
+        PLAYING,
+        PAUSED,
+        FINISHED,
+        STOPPED,
+        BUFFER_UNDERRUN
+    }
+
+    private AudioPlayerState currentState = AudioPlayerState.FINISHED;
+    private IMessageSender messageSender;
+    private String namespace;
+    private AudioPlayStateReportListener audioPlayStateReportListener;
+
+    public AudioPlayStateReport(String namespace, IMessageSender messageSender,
+                                AudioPlayStateReportListener audioPlayStateReportListener) {
+        this.namespace = namespace;
+        this.messageSender = messageSender;
+        this.audioPlayStateReportListener = audioPlayStateReportListener;
+
+    }
+
+    public AudioPlayerState getState() {
+        return currentState;
+    }
+
+    public void playbackResumed() {
+        currentState = AudioPlayerState.PLAYING;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackResumed.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackFinished() {
+        currentState = AudioPlayerState.FINISHED;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackFinished.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackStarted() {
+        currentState = AudioPlayerState.PLAYING;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStarted.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackFailed(IMediaPlayer.ErrorType errorType) {
+        currentState = AudioPlayerState.STOPPED;
+        long offset = audioPlayStateReportListener.getCurrentOffsetInMilliseconds();
+        PlaybackStatePayload playbackStatePayload =
+                new PlaybackStatePayload(audioPlayStateReportListener.getCurrentStreamToken(),
+                        offset, currentState.toString());
+
+        Header header = new MessageIdHeader(namespace,
+                ApiConstants.Events.PlaybackFailed.NAME);
+        Event event = new Event(header,
+                new PlaybackFailedPayload(audioPlayStateReportListener.getCurrentStreamToken(),
+                        playbackStatePayload, errorType));
+
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackPaused() {
+        currentState = AudioPlayerState.PAUSED;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackPaused.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackNearlyFinished() {
+        currentState = AudioPlayerState.FINISHED;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackNearlyFinished.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackStutterStarted() {
+        currentState = AudioPlayerState.BUFFER_UNDERRUN;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStutterStarted.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackStutterFinished() {
+        currentState = AudioPlayerState.PLAYING;
+        Event event = createAudioPlayerPlaybackStutterFinishedEvent(
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds(),
+                audioPlayStateReportListener.getStutterDurationInMilliseconds()
+        );
+        messageSender.sendEvent(event);
+    }
+
+    public void playbackStopped() {
+        currentState = AudioPlayerState.STOPPED;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.PlaybackStopped.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void clearQueueAll() {
+        Event event = createAudioPlayerPlaybackQueueClearedEvent();
+        messageSender.sendEvent(event);
+        if (currentState == AudioPlayerState.PLAYING || currentState == AudioPlayerState.PAUSED
+                || currentState == AudioPlayerState.BUFFER_UNDERRUN) {
+            currentState = AudioPlayerState.STOPPED;
+            Event eventStopped = createAudioPlayerEvent(ApiConstants.Events.PlaybackStopped.NAME,
+                    audioPlayStateReportListener.getCurrentStreamToken(),
+                    audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+            messageSender.sendEvent(eventStopped);
+        }
+    }
+
+    public void clearQueueEnqueued() {
+        Event event = createAudioPlayerPlaybackQueueClearedEvent();
+        messageSender.sendEvent(event);
+    }
+
+    private Event createAudioPlayerEvent(String name, String streamToken,
+                                         long offsetInMilliseconds) {
+        Header header = new MessageIdHeader(namespace, name);
+        Payload payload = new AudioPlayerPayload(streamToken, offsetInMilliseconds);
+        return new Event(header, payload);
+    }
+
+    private Event createAudioPlayerPlaybackQueueClearedEvent() {
+        Header header = new MessageIdHeader(ApiConstants.NAMESPACE,
+                ApiConstants.Events.PlaybackQueueCleared.NAME);
+        return new Event(header, new Payload());
+    }
+
+    private Event createAudioPlayerPlaybackStutterFinishedEvent(String streamToken,
+                                                                long offsetInMilliseconds,
+                                                                long stutterDurationInMilliseconds) {
+        Header header = new MessageIdHeader(ApiConstants.NAMESPACE,
+                ApiConstants.Events.PlaybackStutterFinished.NAME);
+        return new Event(header, new PlaybackStutterFinishedPayload(streamToken,
+                offsetInMilliseconds, stutterDurationInMilliseconds));
+    }
+
+    public void reportProgressDelay() {
+        currentState = AudioPlayerState.PLAYING;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.ProgressReportDelayElapsed.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public void reportProgressInterval() {
+        currentState = AudioPlayerState.PLAYING;
+        Event event = createAudioPlayerEvent(ApiConstants.Events.ProgressReportIntervalElapsed.NAME,
+                audioPlayStateReportListener.getCurrentStreamToken(),
+                audioPlayStateReportListener.getCurrentOffsetInMilliseconds());
+        messageSender.sendEvent(event);
+    }
+
+    public interface AudioPlayStateReportListener {
+        String getCurrentStreamToken();
+
+        long getCurrentOffsetInMilliseconds();
+
+        long getStutterDurationInMilliseconds();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerProgressReporter.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 当服务器返回Play指令有progressReportDelayInMilliseconds,
+ * <p>
+ * ProgressReportDelayElapsed和ProgressReportIntervalElapsed事件的上报
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/22.
+ */
+public class AudioPlayerProgressReporter {
+    private final ScheduledExecutorService eventScheduler = Executors.newScheduledThreadPool(1);
+    private ScheduledFuture<?> progressReportDelayFuture;
+    private ScheduledFuture<?> progressReportIntervalFuture;
+    private final Runnable progressReportDelayRunnable;
+    private final Runnable progressReportIntervalRunnable;
+    private final AudioPlayerTimer audioPlayerTimer;
+    private long progressReportDelay;
+    private long progressReportInterval;
+    private boolean isSetup;
+
+    public AudioPlayerProgressReporter(Runnable progressReportDelayRunnable,
+                                       Runnable progressReportIntervalRunnable,
+                                       AudioPlayerTimer audioPlayerTimer) {
+        if (progressReportDelayRunnable == null
+                || progressReportIntervalRunnable == null
+                || audioPlayerTimer == null) {
+            throw new IllegalArgumentException("All arguments must be provided.");
+        }
+        this.progressReportDelayRunnable = progressReportDelayRunnable;
+        this.progressReportIntervalRunnable = progressReportIntervalRunnable;
+        this.audioPlayerTimer = audioPlayerTimer;
+        this.isSetup = false;
+    }
+
+    public synchronized void setup(PlayPayload.ProgressReport progressReport) {
+        if (progressReport == null) {
+            String errorMessage = "ProgressReport must not be null.";
+            throw new IllegalArgumentException(errorMessage);
+        }
+        if (isSetup) {
+            String errorMessage = "AudioPlayerProgressReporter has already been setup. "
+                    + "Please disable it before setting it up again.";
+            throw new IllegalStateException(errorMessage);
+        }
+
+        cancelEvents();
+        progressReportDelay = progressReport.progressReportDelayInMilliseconds;
+        progressReportInterval = progressReport.progressReportIntervalInMilliseconds;
+        isSetup = true;
+    }
+
+    public synchronized void disable() {
+        isSetup = false;
+        cancelEvents();
+        progressReportDelay = 0;
+        progressReportInterval = 0;
+    }
+
+    public synchronized void start() {
+        cancelEvents();
+
+        if (!isSetup) {
+            String errorMessage = "AudioPlayerProgressReporter cannot be started "
+                    + "because it has not been setup yet.";
+            throw new IllegalStateException(errorMessage);
+        }
+
+        long currentOffsetIntoTrack = audioPlayerTimer.getOffsetInMilliseconds();
+
+        long timeUntilDelayReport = progressReportDelay - currentOffsetIntoTrack;
+        if (timeUntilDelayReport > 0) {
+            scheduleDelayEvent(timeUntilDelayReport);
+        }
+
+        long timeUntilIntervalReport = progressReportInterval == 0 ? 0 :
+                progressReportInterval - (currentOffsetIntoTrack % progressReportInterval);
+        if (timeUntilIntervalReport > 0) {
+            scheduleIntervalEvent(timeUntilIntervalReport, progressReportInterval);
+        }
+    }
+
+    public synchronized void stop() {
+        cancelEvents();
+    }
+
+    public synchronized boolean isSetup() {
+        return isSetup;
+    }
+
+    private void scheduleDelayEvent(long delay) {
+        progressReportDelayFuture = eventScheduler.schedule(progressReportDelayRunnable, delay,
+                TimeUnit.MILLISECONDS);
+    }
+
+    private void scheduleIntervalEvent(long delay, long interval) {
+        progressReportIntervalFuture = eventScheduler.scheduleAtFixedRate(
+                progressReportIntervalRunnable, delay, interval, TimeUnit.MILLISECONDS);
+    }
+
+    private void cancelEvents() {
+        if (progressReportDelayFuture != null && !progressReportDelayFuture.isDone()) {
+            progressReportDelayFuture.cancel(false);
+        }
+        if (progressReportIntervalFuture != null && !progressReportIntervalFuture.isDone()) {
+            progressReportIntervalFuture.cancel(false);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/audioplayer/report/AudioPlayerTimer.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.audioplayer.report;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * audio 播放统计OffsetInMilliseconds
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/22.
+ */
+public class AudioPlayerTimer {
+    private long startNano;
+    private long elapsedTimeMs;
+    private long totalStreamLength;
+    private boolean isPlaying = false;
+
+    public synchronized void start() {
+        startNano = System.nanoTime();
+        isPlaying = true;
+    }
+
+    public synchronized void stop() {
+        if (isPlaying) {
+            elapsedTimeMs += getCurrentOffsetInMilliseconds();
+            isPlaying = false;
+        }
+    }
+
+    public synchronized long getOffsetInMilliseconds() {
+        long offset = elapsedTimeMs + (isPlaying ? getCurrentOffsetInMilliseconds() : 0);
+        if (totalStreamLength > 0) {
+            offset = Math.min(totalStreamLength, offset);
+        }
+        return offset;
+    }
+
+    public void reset() {
+        reset(0);
+    }
+
+    public void reset(long startPosition) {
+        reset(startPosition, -1);
+    }
+
+    public synchronized void reset(long startPosition, long maxPosition) {
+        elapsedTimeMs = startPosition;
+        isPlaying = false;
+        startNano = System.nanoTime();
+        totalStreamLength = maxPosition;
+    }
+
+    private long getCurrentOffsetInMilliseconds() {
+        return TimeUnit.MILLISECONDS.convert(System.nanoTime() - startNano, TimeUnit.NANOSECONDS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.playbackcontroller;
+
+/**
+ * 定义了表示PlaybackController模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.playback_controller";
+    public static final String NAME = "PlaybackControllerInterface";
+
+    public static final class Events {
+        public static final class NextCommandIssued {
+            public static final String NAME = NextCommandIssued.class.getSimpleName();
+        }
+
+        public static final class PreviousCommandIssued {
+            public static final String NAME = PreviousCommandIssued.class.getSimpleName();
+        }
+
+        public static final class PlayCommandIssued {
+            public static final String NAME = PlayCommandIssued.class.getSimpleName();
+        }
+
+        public static final class PauseCommandIssued {
+            public static final String NAME = PauseCommandIssued.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/playbackcontroller/PlaybackControllerDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.playbackcontroller;
+
+import com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+
+/**
+ * 音频播放控制
+ * <p>
+ * 用户按了端上的播放/暂停等控制按钮,或者通过端上的GUI进行了此类操作时,上报PlayCommandIssued、PauseCommandIssued等事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class PlaybackControllerDeviceModule extends BaseDeviceModule {
+    private AlertsDeviceModule mAlertsDeviceModule;
+
+    public enum PlaybackAction {
+        PLAY,
+        PAUSE,
+        PREVIOUS,
+        NEXT
+    }
+
+    public PlaybackControllerDeviceModule(IPlaybackController playback, IMessageSender messageSender,
+                                          AlertsDeviceModule alertsDeviceModule) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.mAlertsDeviceModule = alertsDeviceModule;
+        playback.registerPlaybackListener(new IPlaybackController.IPlaybackListener() {
+            @Override
+            public void onPlay(IResponseListener responseListener) {
+                handlePlaybackAction(PlaybackAction.PLAY, responseListener);
+            }
+
+            @Override
+            public void onPause(IResponseListener responseListener) {
+                handlePlaybackAction(PlaybackAction.PAUSE, responseListener);
+            }
+
+            @Override
+            public void onPrevious(IResponseListener responseListener) {
+                handlePlaybackAction(PlaybackAction.PREVIOUS, responseListener);
+            }
+
+            @Override
+            public void onNext(IResponseListener responseListener) {
+                handlePlaybackAction(PlaybackAction.NEXT, responseListener);
+            }
+        });
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        return null;
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+    }
+
+    @Override
+    public void release() {
+    }
+
+    private void handlePlaybackAction(PlaybackAction action, IResponseListener responseListener) {
+        switch (action) {
+            case PLAY:
+                if (mAlertsDeviceModule.hasActiveAlerts()) {
+                    mAlertsDeviceModule.stopActiveAlert();
+                } else {
+                    Event event = createPlaybackControllerEvent(ApiConstants.Events.PlayCommandIssued.NAME);
+                    messageSender.sentEventWithClientContext(event, responseListener);
+                }
+                break;
+            case PAUSE:
+                if (mAlertsDeviceModule.hasActiveAlerts()) {
+                    mAlertsDeviceModule.stopActiveAlert();
+                } else {
+                    Event event = createPlaybackControllerEvent(ApiConstants.Events.PauseCommandIssued.NAME);
+                    messageSender.sentEventWithClientContext(event, responseListener);
+                }
+                break;
+            case PREVIOUS:
+                Event event = createPlaybackControllerEvent(ApiConstants.Events.PreviousCommandIssued.NAME);
+                messageSender.sentEventWithClientContext(event, responseListener);
+                break;
+            case NEXT:
+                Event eventNext = createPlaybackControllerEvent(ApiConstants.Events.NextCommandIssued.NAME);
+                messageSender.sentEventWithClientContext(eventNext, responseListener);
+                break;
+            default:
+                break;
+        }
+    }
+
+    private Event createPlaybackControllerEvent(String name) {
+        Header header = new MessageIdHeader(ApiConstants.NAMESPACE, name);
+        return new Event(header, new Payload());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.screen;
+
+/**
+ * 定义了表示Screen模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.screen";
+    public static final String NAME = "ScreenInterface";
+
+    public static final class Events {
+        public static final class LinkClicked {
+            public static final String NAME = LinkClicked.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class HtmlView {
+            public static final String NAME = HtmlView.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/ScreenDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.screen;
+
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+import com.baidu.duer.dcs.devicemodule.screen.message.LinkClickedPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+
+/**
+ * Screen模块处理并执行服务下发的指令,如HtmlView指令,以及发送事件,如LinkClicked事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class ScreenDeviceModule extends BaseDeviceModule {
+    private final IWebView webView;
+
+    public ScreenDeviceModule(IWebView webView, IMessageSender messageSender) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.webView = webView;
+        webView.addWebViewListener(new IWebView.IWebViewListener() {
+            @Override
+            public void onLinkClicked(String url) {
+                sendLinkClickedEvent(url);
+            }
+        });
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        return null;
+    }
+
+    @Override
+    public void handleDirective(Directive directive) {
+        String name = directive.header.getName();
+        if (name.equals(ApiConstants.Directives.HtmlView.NAME)) {
+            handleHtmlPayload(directive.getPayload());
+        }
+    }
+
+    @Override
+    public void release() {
+    }
+
+    private void handleHtmlPayload(Payload payload) {
+        if (payload instanceof HtmlPayload) {
+            HtmlPayload htmlPayload = (HtmlPayload) payload;
+            webView.loadUrl(htmlPayload.getUrl());
+        }
+    }
+
+    private void sendLinkClickedEvent(String url) {
+        String name = ApiConstants.Events.LinkClicked.NAME;
+        Header header = new MessageIdHeader(getNameSpace(), name);
+
+        LinkClickedPayload linkClickedPayload = new LinkClickedPayload(url);
+        Event event = new Event(header, linkClickedPayload);
+        if (messageSender != null) {
+            messageSender.sendEvent(event);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/HtmlPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.screen.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.io.Serializable;
+
+/**
+ * HtmlView指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class HtmlPayload extends Payload implements Serializable {
+    private String url;
+    private String token;
+
+    public HtmlPayload() {
+    }
+
+    public HtmlPayload(String url, String token) {
+        this.url = url;
+        this.token = token;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/screen/message/LinkClickedPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.screen.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * LinkClicked事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class LinkClickedPayload extends Payload {
+    private String url;
+
+    public LinkClickedPayload(String url) {
+        this.url = url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller;
+
+/**
+ * 定义了表示SpeakController模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.speaker_controller";
+    public static final String NAME = "SpeakerControllerInterface";
+
+    public static final class Events {
+        public static final class VolumeChanged {
+            public static final String NAME = VolumeChanged.class.getSimpleName();
+        }
+
+        public static final class MuteChanged {
+            public static final String NAME = MuteChanged.class.getSimpleName();
+        }
+
+        public static final class VolumeState {
+            public static final String NAME = VolumeState.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class SetVolume {
+            public static final String NAME = SetVolume.class.getSimpleName();
+        }
+
+        public static final class AdjustVolume {
+            public static final String NAME = AdjustVolume.class.getSimpleName();
+        }
+
+        public static final class SetMute {
+            public static final String NAME = SetMute.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/SpeakerControllerDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller;
+
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.AdjustVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.MuteChangedPayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetMutePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.VolumeStatePayload;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException.ExceptionType;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.BaseMultiChannelMediaPlayer;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * SpeakerController模块处理服务下发的SetVolume、AdjustVolume、SetMute指令,发送VolumeChanged、MuteChanged事件,
+ * 以及维护自身的端状态
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class SpeakerControllerDeviceModule extends BaseDeviceModule {
+    private final BaseMultiChannelMediaPlayer.ISpeakerController speakerController;
+
+    public SpeakerControllerDeviceModule(BaseMultiChannelMediaPlayer.ISpeakerController speakerController,
+                                         IMessageSender messageSender) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.speakerController = speakerController;
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        String namespace = getNameSpace();
+        String name = ApiConstants.Events.VolumeState.NAME;
+        Header header = new Header(namespace, name);
+        long volume = (long) (speakerController.getVolume() * 100.0F);
+        boolean mute = speakerController.getMute();
+        VolumeStatePayload payload = new VolumeStatePayload(volume, mute);
+        return new ClientContext(header, payload);
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        Header header = directive.header;
+        String name = header.getName();
+        Payload payload = directive.getPayload();
+        if (name.equals(ApiConstants.Directives.AdjustVolume.NAME)) {
+            if (payload instanceof AdjustVolumePayload) {
+                AdjustVolumePayload adjustVolumePayload = (AdjustVolumePayload) directive.getPayload();
+                float increment = (float) adjustVolumePayload.getVolume() / 100.0F;
+                float volume = speakerController.getVolume() + increment;
+                volume = Math.min(1.0F, Math.max(volume, -1.0F));
+                setVolume(volume);
+            }
+        } else if (name.equals(ApiConstants.Directives.SetVolume.NAME)) {
+            if (payload instanceof SetVolumePayload) {
+                SetVolumePayload setVolumePayload = (SetVolumePayload) payload;
+                float volume = (float) setVolumePayload.getVolume() / 100.0F;
+                this.setVolume(volume);
+            }
+        } else if (name.equals(ApiConstants.Directives.SetMute.NAME)) {
+            if (payload instanceof SetMutePayload) {
+                SetMutePayload setMutePayload = (SetMutePayload) payload;
+                setMute(setMutePayload.getMute());
+            }
+        } else {
+            String message = "SpeakerController cannot handle the directive";
+            throw new HandleDirectiveException(ExceptionType.UNSUPPORTED_OPERATION, message);
+        }
+    }
+
+    @Override
+    public void release() {
+
+    }
+
+    private void setVolume(float volume) {
+        speakerController.setVolume(volume);
+        messageSender.sendEvent(volumeChangedEvent());
+    }
+
+    private void setMute(boolean mute) {
+        speakerController.setMute(mute);
+        messageSender.sendEvent(muteChangedEvent());
+    }
+
+    private Event volumeChangedEvent() {
+        String nameSpace = getNameSpace();
+        String name = ApiConstants.Events.VolumeChanged.NAME;
+        MessageIdHeader header = new MessageIdHeader(nameSpace, name);
+        VolumeStatePayload payload = new VolumeStatePayload(getVolume(), isMuted());
+        return new Event(header, payload);
+    }
+
+    private Event muteChangedEvent() {
+        String nameSpace = getNameSpace();
+        String name = ApiConstants.Events.MuteChanged.NAME;
+        MessageIdHeader header = new MessageIdHeader(nameSpace, name);
+        MuteChangedPayload payload = new MuteChangedPayload(getVolume(), isMuted());
+        return new Event(header, payload);
+    }
+
+    private long getVolume() {
+        return (long) (speakerController.getVolume() * 100.0F);
+    }
+
+    private boolean isMuted() {
+        return speakerController.getMute();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/AdjustVolumePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * adjustVolume指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class AdjustVolumePayload extends Payload {
+    private long volume;
+
+    public AdjustVolumePayload() {
+    }
+
+    public AdjustVolumePayload(long volume) {
+        this.volume = volume;
+    }
+
+    public void setVolume(long volume) {
+        this.volume = volume;
+    }
+
+    public long getVolume() {
+        return volume;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/MuteChangedPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 上报MuteChanged事件对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class MuteChangedPayload extends Payload {
+    private long volume;
+    private boolean muted;
+
+    public MuteChangedPayload(long volume, boolean muted) {
+        this.volume = volume;
+        this.muted = muted;
+    }
+
+    public void setVolume(long volume) {
+        this.volume = volume;
+    }
+
+    public long getVolume() {
+        return this.volume;
+    }
+
+    public void setMuted(boolean muted) {
+        this.muted = muted;
+    }
+
+    public boolean getMuted() {
+        return muted;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetMutePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setMuted指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class SetMutePayload extends Payload {
+    private boolean mute;
+
+    public SetMutePayload() {
+    }
+
+    public SetMutePayload(boolean mute) {
+        this.mute = mute;
+    }
+
+    public void setMute(boolean mute) {
+        this.mute = mute;
+    }
+
+    public boolean getMute() {
+        return this.mute;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/SetVolumePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setVolume指令对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class SetVolumePayload extends Payload {
+    private long volume;
+
+    public SetVolumePayload() {
+    }
+
+    public SetVolumePayload(long volume) {
+        this.volume = volume;
+    }
+
+    public void setVolume(long volume) {
+        this.volume = volume;
+    }
+
+    public long getVolume() {
+        return volume;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/speakcontroller/message/VolumeStatePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.speakcontroller.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 本模块端状态对应的Payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/5.
+ */
+public class VolumeStatePayload extends Payload {
+    private long volume;
+    private boolean muted;
+
+    public VolumeStatePayload() {
+    }
+
+    public VolumeStatePayload(long volume, boolean muted) {
+        this.volume = volume;
+        this.muted = muted;
+    }
+
+    public void setVolume(long volume) {
+        this.volume = volume;
+    }
+
+    public long getVolume() {
+        return this.volume;
+    }
+
+    public void setMuted(boolean muted) {
+        this.muted = muted;
+    }
+
+    public boolean getMuted() {
+        return muted;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system;
+
+/**
+ * 定义了表示System模块的namespace、name,以及其事件、指令、异常的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.system";
+    public static final String NAME = "SystemInterface";
+
+    public static final class Events {
+        public static final class SynchronizeState {
+            public static final String NAME = SynchronizeState.class.getSimpleName();
+        }
+
+        public static final class ExceptionEncountered {
+            public static final String NAME = ExceptionEncountered.class.getSimpleName();
+        }
+
+        public static final class UserInactivityReport {
+            public static final String NAME = UserInactivityReport.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class ResetUserInactivity {
+            public static final String NAME = ResetUserInactivity.class.getSimpleName();
+        }
+
+        public static final class SetEndpoint {
+            public static final String NAME = SetEndpoint.class.getSimpleName();
+        }
+
+        public static final class ThrowException {
+            public static final String NAME = ThrowException.class.getSimpleName();
+        }
+    }
+
+    public static final class Exception {
+        public static final String NAME = Exception.class.getSimpleName();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/HandleDirectiveException.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system;
+
+/**
+ * 指令没有处理异常
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class HandleDirectiveException extends Exception {
+    private ExceptionType exceptionType;
+
+    public HandleDirectiveException(ExceptionType exceptionType, String message) {
+        super(message);
+        this.exceptionType = exceptionType;
+    }
+
+    public ExceptionType getExceptionType() {
+        return exceptionType;
+    }
+
+    public enum ExceptionType {
+        UNEXPECTED_INFORMATION_RECEIVED,
+        UNSUPPORTED_OPERATION,
+        INTERNAL_ERROR
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/SystemDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system;
+
+import com.baidu.duer.dcs.devicemodule.system.message.ExceptionEncounteredPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.UserInactivityReportPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * System模块处理ResetUserInactivity、SetEndpoint、ThrowException指令,发送SynchronizeState、UserInactivityReport等事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class SystemDeviceModule extends BaseDeviceModule {
+    private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(1);
+    private static final long MILLISECONDS_PER_SECOND = 1000;
+    private static final long USER_INACTIVITY_REPORT_PERIOD_HOURS = 1;
+    private final List<IDeviceModuleListener> deviceModuleListeners;
+    private AtomicLong lastUserInteractionInSeconds;
+    private Provider provider;
+
+    public SystemDeviceModule(final IMessageSender messageSender) {
+        super(ApiConstants.NAMESPACE, messageSender);
+
+        Runnable runnable = new Runnable() {
+            @Override
+            public void run() {
+                long inactiveTimeInSeconds = currentTimeSeconds() - lastUserInteractionInSeconds.get();
+                Event event = userInactivityReportEvent(inactiveTimeInSeconds);
+                messageSender.sendEvent(event);
+            }
+        };
+
+        lastUserInteractionInSeconds = new AtomicLong(currentTimeSeconds());
+        scheduledExecutor.scheduleAtFixedRate(runnable, USER_INACTIVITY_REPORT_PERIOD_HOURS,
+                USER_INACTIVITY_REPORT_PERIOD_HOURS, TimeUnit.HOURS);
+
+        deviceModuleListeners = Collections.synchronizedList(new ArrayList<IDeviceModuleListener>());
+    }
+
+
+    @Override
+    public ClientContext clientContext() {
+        return null;
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        String name = directive.header.getName();
+        if (ApiConstants.Directives.ResetUserInactivity.NAME.equals(name)) {
+            userActivity();
+        } else if (ApiConstants.Directives.SetEndpoint.NAME.equals(name)) {
+            handleSetEndpointDirective(directive);
+        } else if (ApiConstants.Directives.ThrowException.NAME.equals(name)) {
+            handleThrowException(directive);
+        } else {
+            String message = "system cannot handle this directive";
+            throw (new HandleDirectiveException(
+                    HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+        }
+    }
+
+    @Override
+    public void release() {
+        if (!scheduledExecutor.isShutdown()) {
+            scheduledExecutor.shutdownNow();
+        }
+        deviceModuleListeners.clear();
+    }
+
+    private void handleSetEndpointDirective(Directive directive) {
+        Payload payload = directive.getPayload();
+        if (payload instanceof SetEndPointPayload) {
+            SetEndPointPayload setEndPointPayload = (SetEndPointPayload) payload;
+            fireSetEndpoint(setEndPointPayload);
+        }
+    }
+
+    private void handleThrowException(Directive directive) {
+        Payload payload = directive.getPayload();
+        if (payload instanceof ThrowExceptionPayload) {
+            ThrowExceptionPayload throwExceptionPayload = (ThrowExceptionPayload) payload;
+            fireThrowException(throwExceptionPayload);
+        }
+    }
+
+    public void sendSynchronizeStateEvent() {
+        String name = ApiConstants.Events.SynchronizeState.NAME;
+        Header header = new MessageIdHeader(getNameSpace(), name);
+        Payload payload = new Payload();
+        Event event = new Event(header, payload);
+
+        if (messageSender != null) {
+            messageSender.sentEventWithClientContext(event, null);
+        }
+    }
+
+    private Event userInactivityReportEvent(long inactiveTimeInSeconds) {
+        final String name = ApiConstants.Events.UserInactivityReport.NAME;
+        Header header = new MessageIdHeader(getNameSpace(), name);
+        Payload payload = new UserInactivityReportPayload(inactiveTimeInSeconds);
+        Event event = new Event(header, payload);
+        return event;
+    }
+
+    public void sendExceptionEncounteredEvent(String directiveJson,
+                                              HandleDirectiveException.ExceptionType type,
+                                              String message) {
+        final String name = ApiConstants.Events.ExceptionEncountered.NAME;
+        Header header = new MessageIdHeader(getNameSpace(), name);
+
+        ExceptionEncounteredPayload exceptionEncounteredPayLoad = new ExceptionEncounteredPayload(
+                directiveJson, type, message);
+        Event event = new Event(header, exceptionEncounteredPayLoad);
+        messageSender.sentEventWithClientContext(event, null);
+    }
+
+    private void userActivity() {
+        lastUserInteractionInSeconds.set(currentTimeSeconds());
+    }
+
+    private long currentTimeSeconds() {
+        return System.currentTimeMillis() / MILLISECONDS_PER_SECOND;
+    }
+
+    public Provider getProvider() {
+        if (provider == null) {
+            provider = new Provider();
+        }
+
+        return provider;
+    }
+
+    public class Provider {
+        public void userActivity() {
+            SystemDeviceModule.this.userActivity();
+        }
+    }
+
+    private void fireSetEndpoint(SetEndPointPayload setEndPointPayload) {
+        for (IDeviceModuleListener listener : deviceModuleListeners) {
+            listener.onSetEndpoint(setEndPointPayload);
+        }
+    }
+
+    private void fireThrowException(ThrowExceptionPayload throwExceptionPayload) {
+        for (IDeviceModuleListener listener : deviceModuleListeners) {
+            listener.onThrowException(throwExceptionPayload);
+        }
+    }
+
+    public void addModuleListener(IDeviceModuleListener listener) {
+        deviceModuleListeners.add(listener);
+    }
+
+    public interface IDeviceModuleListener {
+        void onSetEndpoint(SetEndPointPayload endPointPayload);
+
+        void onThrowException(ThrowExceptionPayload throwExceptionPayload);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ExceptionEncounteredPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException.ExceptionType;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ExceptionEncountered事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class ExceptionEncounteredPayload extends Payload {
+    private String unparsedDirective;
+    private Error error;
+
+    public ExceptionEncounteredPayload(String unparsedDirective, ExceptionType type, String message) {
+        this.unparsedDirective = unparsedDirective;
+        Error error = new Error(type, message);
+        this.error = error;
+    }
+
+    public void setUnparsedDirective(String unparsedDirective) {
+        this.unparsedDirective = unparsedDirective;
+    }
+
+    public String getUnparsedDirective() {
+        return unparsedDirective;
+    }
+
+    public void setError(Error error) {
+        this.error = error;
+    }
+
+    public Error getError() {
+        return error;
+    }
+
+    public static class Error {
+        public ExceptionType type;
+        public String message;
+
+        public Error(ExceptionType type, String message) {
+            this.type = type;
+            this.message = message;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/SetEndPointPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * setEndPoint指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class SetEndPointPayload extends Payload {
+    private String endpoint;
+
+    public SetEndPointPayload() {
+
+    }
+
+    public SetEndPointPayload(String endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    public void setEndpoint(String endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    public String getEndpoint() {
+        return endpoint;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/ThrowExceptionPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ThrowException指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/8.
+ */
+public class ThrowExceptionPayload extends Payload {
+    private String code;
+    private String description;
+
+    public ThrowExceptionPayload() {
+    }
+
+    public ThrowExceptionPayload(String code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String toString() {
+        return "code=" + code + "  description=" + description;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/system/message/UserInactivityReportPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.system.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * UserInactivityReport事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/3.
+ */
+public class UserInactivityReportPayload extends Payload {
+    private long inactiveTimeInSeconds;
+
+    public UserInactivityReportPayload(long inactiveTimeInSeconds) {
+        this.inactiveTimeInSeconds = inactiveTimeInSeconds;
+    }
+
+    void setInactiveTimeInSeconds(long inactiveTimeInSeconds) {
+        this.inactiveTimeInSeconds = inactiveTimeInSeconds;
+    }
+
+    long getInactiveTimeInSeconds() {
+        return inactiveTimeInSeconds;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceinput;
+
+/**
+ * 定义了表示Voice Input模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.voice_input";
+    public static final String NAME = "VoiceInputInterface";
+
+    public static final class Events {
+        public static final class ListenStarted {
+            public static final String NAME = ListenStarted.class.getSimpleName();
+        }
+
+        public static final class ListenTimedOut {
+            public static final String NAME = ListenTimedOut.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class Listen {
+            public static final String NAME = Listen.class.getSimpleName();
+        }
+
+        public static final class StopListen {
+            public static final String NAME = StopListen.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/VoiceInputDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceinput;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.voiceinput.message.ListenStartedPayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.DialogRequestIdHandler;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.DialogRequestIdHeader;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.systeminterface.IAudioInput;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Voice Input模块处理并执行服务下发的StopListen、Listen指令,上报ListenStarted、ListenTimedOut事件
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class VoiceInputDeviceModule extends BaseDeviceModule {
+    public static final String TAG = VoiceInputDeviceModule.class.getSimpleName();
+    private final IAudioInput audioInput;
+    private final List<IVoiceInputListener> voiceInputListeners;
+    private final IMediaPlayer mediaPlayer;
+    private final DialogRequestIdHandler dialogRequestIdHandler;
+    private final DcsResponseDispatcher dcsResponseDispatcher;
+
+    public VoiceInputDeviceModule(final IMediaPlayer mediaPlayer,
+                                  IMessageSender messageSender,
+                                  final IAudioInput audioInput,
+                                  DialogRequestIdHandler dialogRequestIdHandler,
+                                  DcsResponseDispatcher dcsResponseDispatcher) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.audioInput = audioInput;
+        this.voiceInputListeners = Collections.synchronizedList(new ArrayList<IVoiceInputListener>());
+        this.mediaPlayer = mediaPlayer;
+        this.dialogRequestIdHandler = dialogRequestIdHandler;
+        this.dcsResponseDispatcher = dcsResponseDispatcher;
+
+        this.audioInput.registerAudioInputListener(new IAudioInput.IAudioInputListener() {
+            @Override
+            public void onStartRecord(DcsStreamRequestBody dcsStreamRequestBody) {
+                stopSpeaker();
+                // 发送网络请求
+                sendListenStartedEvent(dcsStreamRequestBody, new IResponseListener() {
+                    @Override
+                    public void onSucceed(int statusCode) {
+                        fireOnSucceed(statusCode);
+                        // 没有下发新的语音speak-stream
+                        if (statusCode == 204) {
+                            // 设置对话通道为非活跃状态
+                            mediaPlayer.setActive(false);
+                        } else {
+                            mediaPlayer.setActive(true);
+                        }
+                    }
+
+                    @Override
+                    public void onFailed(String errorMessage) {
+                        LogUtil.d(TAG, "onFailed,errorMessage:" + errorMessage);
+                        fireOnFailed(errorMessage);
+                        audioInput.stopRecord();
+                        mediaPlayer.setActive(false);
+                    }
+                });
+
+                fireOnStartRecord();
+            }
+
+            @Override
+            public void onStopRecord() {
+                fireFinishRecord();
+            }
+        });
+    }
+
+
+    @Override
+    public ClientContext clientContext() {
+        return null;
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        String name = directive.getName();
+        if (name.equals(ApiConstants.Directives.StopListen.NAME)) {
+            audioInput.stopRecord();
+        } else if (name.equals(ApiConstants.Directives.Listen.NAME)) {
+            audioInput.startRecord();
+        } else {
+            String message = "No device to handle the directive";
+            throw new HandleDirectiveException(
+                    HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION,
+                    message);
+        }
+    }
+
+    @Override
+    public void release() {
+        voiceInputListeners.clear();
+    }
+
+    /**
+     * 停止speaker对话通道的语音播放
+     */
+    private void stopSpeaker() {
+        mediaPlayer.setActive(true);
+        mediaPlayer.stop();
+        dcsResponseDispatcher.interruptDispatch();
+    }
+
+    private void sendListenStartedEvent(DcsStreamRequestBody streamRequestBody, IResponseListener responseListener) {
+        String dialogRequestId = dialogRequestIdHandler.createActiveDialogRequestId();
+        String name = ApiConstants.Events.ListenStarted.NAME;
+        DialogRequestIdHeader header = new DialogRequestIdHeader(getNameSpace(), name, dialogRequestId);
+        Payload payload = new ListenStartedPayload(ListenStartedPayload.FORMAT);
+        Event event = new Event(header, payload);
+        messageSender.sendEvent(event, streamRequestBody, responseListener);
+    }
+
+    private void fireOnStartRecord() {
+        for (IVoiceInputListener listener : voiceInputListeners) {
+            listener.onStartRecord();
+        }
+    }
+
+    private void fireFinishRecord() {
+        for (IVoiceInputListener listener : voiceInputListeners) {
+            listener.onFinishRecord();
+        }
+    }
+
+    private void fireOnSucceed(int statusCode) {
+        for (IVoiceInputListener listener : voiceInputListeners) {
+            listener.onSucceed(statusCode);
+        }
+    }
+
+    private void fireOnFailed(String errorMessage) {
+        for (IVoiceInputListener listener : voiceInputListeners) {
+            listener.onFailed(errorMessage);
+        }
+    }
+
+    public void addVoiceInputListener(IVoiceInputListener listener) {
+        this.voiceInputListeners.add(listener);
+    }
+
+    public interface IVoiceInputListener {
+        /**
+         * 开始录音的回调
+         */
+        void onStartRecord();
+
+        /**
+         * 结束录音的回调
+         */
+        void onFinishRecord();
+
+        /**
+         * 录音-网络请求成功
+         *
+         * @param statusCode 网络返回状态码
+         */
+        void onSucceed(int statusCode);
+
+        /**
+         * 录音-网络请求失败
+         *
+         * @param errorMessage 错误信息
+         */
+        void onFailed(String errorMessage);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceinput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * Listen指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ListenPayload extends Payload {
+    private long timeoutInMilliseconds;
+
+    public void setTimeoutInMilliseconds(long timeoutInMilliseconds) {
+        this.timeoutInMilliseconds = timeoutInMilliseconds;
+    }
+
+    public long getTimeoutInMilliseconds() {
+        return timeoutInMilliseconds;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceinput/message/ListenStartedPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceinput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * ListenStarted事件对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class ListenStartedPayload extends Payload {
+    public static final String FORMAT = "AUDIO_L16_RATE_16000_CHANNELS_1";
+    private String format;
+
+    public ListenStartedPayload(String format) {
+        this.format = format;
+    }
+
+    public void setFormat(String format) {
+        this.format = format;
+    }
+
+    public String getFormat() {
+        return format;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/ApiConstants.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceoutput;
+
+/**
+ * 定义了表示Voice Output模块的namespace、name,以及其事件、指令的name
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class ApiConstants {
+    public static final String NAMESPACE = "ai.dueros.device_interface.voice_output";
+    public static final String NAME = "VoiceOutputInterface";
+
+    public static final class Events {
+        public static final class SpeechStarted {
+            public static final String NAME = SpeechStarted.class.getSimpleName();
+        }
+
+        public static final class SpeechFinished {
+            public static final String NAME = SpeechFinished.class.getSimpleName();
+        }
+
+        public static final class SpeechState {
+            public static final String NAME = SpeechState.class.getSimpleName();
+        }
+    }
+
+    public static final class Directives {
+        public static final class Speak {
+            public static final String NAME = Speak.class.getSimpleName();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/VoiceOutputDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceoutput;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeakPayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeechLifecyclePayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.VoiceOutputStatePayload;
+import com.baidu.duer.dcs.framework.BaseDeviceModule;
+import com.baidu.duer.dcs.framework.IMessageSender;
+import com.baidu.duer.dcs.framework.IResponseListener;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.MessageIdHeader;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Voice Output模块处理并执行服务下发的Speak指令,上报SpeechStarted、SpeechFinished事件,以及维护自身的端状态
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class VoiceOutputDeviceModule extends BaseDeviceModule {
+    private static final String TAG = VoiceOutputDeviceModule.class.getSimpleName();
+    // 播放回调
+    private final List<IVoiceOutputListener> voiceOutputListeners;
+    // 播放队列
+    private final LinkedList<SpeakPayload> speakQueue = new LinkedList<>();
+    // 语音播放的播放器
+    private final IMediaPlayer mediaPlayer;
+    private SpeechState speechState = SpeechState.FINISHED;
+
+    // 上一次的token
+    private String lastSpeakToken = "";
+
+    // 当前播放状态
+    private enum SpeechState {
+        PLAYING,
+        FINISHED
+    }
+
+    public VoiceOutputDeviceModule(IMediaPlayer mediaPlayer,
+                                   IMessageSender messageSender) {
+        super(ApiConstants.NAMESPACE, messageSender);
+        this.mediaPlayer = mediaPlayer;
+        this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
+        this.voiceOutputListeners = Collections.synchronizedList(new ArrayList<IVoiceOutputListener>());
+    }
+
+    @Override
+    public ClientContext clientContext() {
+        String namespace = ApiConstants.NAMESPACE;
+        String name = ApiConstants.Events.SpeechState.NAME;
+        Header header = new Header(namespace, name);
+        VoiceOutputStatePayload payload = new VoiceOutputStatePayload(lastSpeakToken,
+                mediaPlayer.getCurrentPosition(),
+                speechState.name());
+        return new ClientContext(header, payload);
+    }
+
+    @Override
+    public void handleDirective(Directive directive) throws HandleDirectiveException {
+        String directiveName = directive.getName();
+        LogUtil.d(TAG, "rawMessage:" + directive.rawMessage);
+        LogUtil.d(TAG, "directiveName:" + directiveName);
+        if (directiveName.equals(ApiConstants.Directives.Speak.NAME)) {
+            SpeakPayload speak = (SpeakPayload) directive.payload;
+            handleSpeak(speak);
+        } else {
+            String message = "VoiceOutput cannot handle the directive";
+            throw (new HandleDirectiveException(
+                    HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
+        }
+    }
+
+    private void handleSpeak(SpeakPayload speak) {
+        speakQueue.add(speak);
+        // 如果已经有了,就只入队列,等待下一次的调度
+        if (speakQueue.size() == 1) {
+            startSpeech();
+        }
+    }
+
+    private void startSpeech() {
+        final SpeakPayload speak = speakQueue.getFirst();
+        if (null != speak) {
+            lastSpeakToken = speak.token;
+            InputStream inputStream = new ByteArrayInputStream(speak.attachedContent);
+            mediaPlayer.play(new IMediaPlayer.MediaResource(inputStream));
+        }
+    }
+
+    private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
+        @Override
+        public void onPrepared() {
+            super.onPrepared();
+            speechState = SpeechState.PLAYING;
+            sendStartedEvent(lastSpeakToken);
+            fireOnVoiceOutputStarted();
+        }
+
+        @Override
+        public void onStopped() {
+            super.onStopped();
+            speakQueue.clear();
+        }
+
+        @Override
+        public void onError(String error, IMediaPlayer.ErrorType errorType) {
+            super.onError(error, errorType);
+            finishedSpeechItem();
+        }
+
+        @Override
+        public void onCompletion() {
+            LogUtil.d(TAG, " IMediaPlayer onCompletion");
+            finishedSpeechItem();
+        }
+    };
+
+    /**
+     * 播放完一条后开始下一条的处理
+     */
+    private void finishedSpeechItem() {
+        speakQueue.poll();
+        LogUtil.d(TAG, "finishedSpeechItem speakQueue size :" + speakQueue.size());
+        if (speakQueue.isEmpty()) {
+            speechState = SpeechState.FINISHED;
+            sendFinishedEvent(lastSpeakToken);
+            fireOnVoiceOutputFinished();
+        } else {
+            startSpeech();
+        }
+    }
+
+    @Override
+    public void release() {
+        if (mediaPlayer != null) {
+            mediaPlayer.release();
+            mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
+        }
+        if (isSpeaking()) {
+            speechState = SpeechState.FINISHED;
+        }
+        speakQueue.clear();
+        voiceOutputListeners.clear();
+    }
+
+    public boolean isSpeaking() {
+        return speechState == SpeechState.PLAYING;
+    }
+
+    /**
+     * 播放开始时上报的事件
+     *
+     * @param token token  一条speak的唯一标识
+     */
+    private void sendStartedEvent(String token) {
+        String namespace = ApiConstants.NAMESPACE;
+        String name = ApiConstants.Events.SpeechStarted.NAME;
+        MessageIdHeader header = new MessageIdHeader(namespace, name);
+        Event event = new Event(header, new SpeechLifecyclePayload(token));
+        messageSender.sendEvent(event);
+    }
+
+    /**
+     * 播放结束时上报的事件
+     *
+     * @param token token  一条speak的唯一标识
+     */
+    private void sendFinishedEvent(String token) {
+        String namespace = ApiConstants.NAMESPACE;
+        String name = ApiConstants.Events.SpeechFinished.NAME;
+        MessageIdHeader header = new MessageIdHeader(namespace, name);
+        Event event = new Event(header, new SpeechLifecyclePayload(token));
+        messageSender.sendEvent(event, new IResponseListener() {
+            @Override
+            public void onSucceed(int statusCode) {
+                // 没有新的语音speak-stream
+                if (statusCode == 204) {
+                    mediaPlayer.setActive(false);
+                } else {
+                    mediaPlayer.setActive(true);
+                }
+            }
+
+            @Override
+            public void onFailed(String errorMessage) {
+                mediaPlayer.setActive(false);
+            }
+        });
+    }
+
+    private void fireOnVoiceOutputStarted() {
+        for (IVoiceOutputListener listener : voiceOutputListeners) {
+            listener.onVoiceOutputStarted();
+        }
+    }
+
+    private void fireOnVoiceOutputFinished() {
+        for (IVoiceOutputListener listener : voiceOutputListeners) {
+            listener.onVoiceOutputFinished();
+        }
+    }
+
+    /**
+     * 添加播放监听
+     *
+     * @param listener listener
+     */
+    public void addVoiceOutputListener(IVoiceOutputListener listener) {
+        this.voiceOutputListeners.add(listener);
+    }
+
+    /**
+     * 播报监听器接口
+     */
+    public interface IVoiceOutputListener {
+        /**
+         * 开始播放时回调
+         */
+        void onVoiceOutputStarted();
+
+        /**
+         * 播放完成时回调
+         */
+        void onVoiceOutputFinished();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeakPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.AttachedContentPayload;
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * Speak指令对应的payload结构
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class SpeakPayload extends Payload implements AttachedContentPayload {
+    public String url;
+    public String format;
+    public String token;
+
+    @JsonIgnore
+    public byte[] attachedContent;
+
+    // start with cid:
+    public void setUrl(String url) {
+        this.url = url.substring(4);
+    }
+
+    @Override
+    public boolean requiresAttachedContent() {
+        return !hasAttachedContent();
+    }
+
+    @Override
+    public boolean hasAttachedContent() {
+        return attachedContent != null;
+    }
+
+    @Override
+    public String getAttachedContentId() {
+        return url;
+    }
+
+    @Override
+    public byte[] getAttachedContent() {
+        return attachedContent;
+    }
+
+    @Override
+    public void setAttachedContent(String cid, byte[] data) {
+        if (getAttachedContentId().equals(cid)) {
+            this.attachedContent = data;
+        } else {
+            throw new IllegalArgumentException(
+                    "Tried to add the wrong audio content to a Speak directive. This cid: "
+                            + getAttachedContentId() + " other cid: " + cid);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/SpeechLifecyclePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+/**
+ * SpeechStarted和SpeechFinished事件对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public class SpeechLifecyclePayload extends Payload {
+    private String token;
+
+    public SpeechLifecyclePayload(String token) {
+        this.token = token;
+    }
+
+    public void setToken(String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/devicemodule/voiceoutput/message/VoiceOutputStatePayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.devicemodule.voiceoutput.message;
+
+import com.baidu.duer.dcs.framework.message.Payload;
+
+/**
+ * 本模块端状态对应的payload结构
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class VoiceOutputStatePayload extends Payload {
+    public String token;
+    public long offsetInMilliseconds;
+    public String playerActivity;
+
+    public VoiceOutputStatePayload(String token, long offsetInMilliseconds, String playerActivity) {
+        this.token = token;
+        this.offsetInMilliseconds = offsetInMilliseconds;
+        this.playerActivity = playerActivity;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseDeviceModule.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.Directive;
+
+/**
+ * 定义deviceModule端状态和处理指令的接口
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public abstract class BaseDeviceModule {
+    private final String nameSpace;
+    protected final IMessageSender messageSender;
+
+    public BaseDeviceModule(String nameSpace) {
+        this(nameSpace, null);
+    }
+
+    public BaseDeviceModule(String nameSpace, IMessageSender messageSender) {
+        this.nameSpace = nameSpace;
+        this.messageSender = messageSender;
+    }
+
+    /**
+     * 端状态:服务端在处理某些事件时,需要了解在请求当时设备端各模块所处的状态。比如端上是否正在播放音乐,
+     * 是否有闹钟在响,是否正在播报等等
+     *
+     * @return 端状态
+     */
+    public abstract ClientContext clientContext();
+
+    /**
+     * 处理服务端下发的指令
+     *
+     * @param directive
+     * @throws HandleDirectiveException
+     */
+    public abstract void handleDirective(Directive directive) throws HandleDirectiveException;
+
+    public abstract void release();
+
+    public String getNameSpace() {
+        return nameSpace;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/BaseMultiChannelMediaPlayer.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 1.用途:控制各个DeviceModule的播放策略-基类,主要控制的是{@link com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule}
+ * and {@link com.baidu.duer.dcs.devicemodule.voiceoutput.VoiceOutputDeviceModule}
+ * and {@link com.baidu.duer.dcs.devicemodule.audioplayer.AudioPlayerDeviceModule}
+ * <p>
+ * 2.如果你需要实现自己的策略需要复写handlePlay方法,该sample中提供了一种暂停策略,即
+ * {@link com.baidu.duer.dcs.framework.PauseStrategyMultiChannelMediaPlayer}
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public abstract class BaseMultiChannelMediaPlayer {
+    // 注册的mediaPlayer
+    protected Map<String, ChannelMediaPlayerInfo> mediaPlayers = new ConcurrentHashMap<>();
+    private IPlatformFactory factory;
+
+    public BaseMultiChannelMediaPlayer(IPlatformFactory factory) {
+        this.factory = factory;
+    }
+
+    /**
+     * 添加一个频道并创建一个mediaPlayer
+     *
+     * @param channelName 频道的名字
+     * @param priority    频道的优先级
+     * @return IMediaPlayer 用于处理端能力的播放
+     */
+    public IMediaPlayer addNewChannel(String channelName, int priority) {
+        IMediaPlayer mediaPlayer = factory.createMediaPlayer();
+
+        ChannelMediaPlayerInfo info = new ChannelMediaPlayerInfo();
+        info.channelName = channelName;
+        info.priority = priority;
+        info.mediaPlayer = mediaPlayer;
+        mediaPlayers.put(channelName, info);
+
+        return new ChannelMediaPlayer(info);
+    }
+
+    /**
+     * 处理对话频道(speak), 闹钟/提醒频道(alert),音乐频道(audio)的播放策略,
+     * 比如: 当播放一个低优先级的指令内容时,来了一个高优先级的播放指令是否需要暂停/降低 低优先级频道对应的mediaPlayer
+     *
+     * @param channelName   频道的名字(即通过addNewChannel方法指定的)
+     * @param mediaResource 媒体资源
+     */
+    protected abstract void handlePlay(String channelName, IMediaPlayer.MediaResource mediaResource);
+
+    protected int getPriorityByChannelName(String channelName) {
+        if (mediaPlayers.containsKey(channelName)) {
+            ChannelMediaPlayerInfo info = mediaPlayers.get(channelName);
+            return info.priority;
+        }
+        return UNKNOWN_PRIORITY;
+    }
+
+    /**
+     * 根据频道的名字获取对应的播放器
+     *
+     * @param channelName channelName 频道的名字
+     * @return IMediaPlayer
+     */
+    protected IMediaPlayer getMediaPlayer(String channelName) {
+        if (channelName != null && channelName.length() > 0) {
+            if (mediaPlayers.containsKey(channelName)) {
+                return mediaPlayers.get(channelName).mediaPlayer;
+            }
+        }
+        return null;
+    }
+
+    private static final String TAG = BaseMultiChannelMediaPlayer.class.getSimpleName();
+    protected static final int UNKNOWN_PRIORITY = -1;
+    // 按优先级保存的需要播放的数据
+    protected Map<Integer, ChannelMediaPlayerInfo> currentPlayMap = new TreeMap<>(
+            new Comparator<Integer>() {
+                public int compare(Integer obj1, Integer obj2) {
+                    // 降序排序
+                    return obj2 - obj1;
+                }
+            });
+
+    /**
+     * 播放信息
+     */
+    protected static class ChannelMediaPlayerInfo {
+        // 播放信息
+        IMediaPlayer.MediaResource mediaResource;
+        // 频道名字
+        String channelName;
+        // 频道优先级
+        int priority;
+        // 播放器
+        IMediaPlayer mediaPlayer;
+    }
+
+    /**
+     * 获取控制音量,静音等操作的实例
+     *
+     * @return ISpeakerController
+     */
+    public ISpeakerController getSpeakerController() {
+        return new SpeakerControllerImpl();
+    }
+
+    /**
+     * 暂停所有的mediaPlayer播放
+     */
+    private void pauseAll() {
+        // 需要暂停所有的播放,有可能没有requestDialogId的指令正在speaking
+        Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo value = entry.getValue();
+            value.mediaPlayer.pause();
+        }
+    }
+
+    private void stop(String channelName) {
+        IMediaPlayer mediaPlayer = getMediaPlayer(channelName);
+        if (mediaPlayer != null) {
+            mediaPlayer.stop();
+        }
+    }
+
+    /**
+     * 设置所有频道的mediaPlayer的音量
+     *
+     * @param volume 音量 0-1
+     */
+    private void setVolumeAll(float volume) {
+        Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo info = entry.getValue();
+            info.mediaPlayer.setVolume(volume);
+        }
+    }
+
+    /**
+     * 获取最高优先级的音量
+     *
+     * @return float 0-1
+     */
+    private float getVolumeTopPriority() {
+        Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+        if (it.hasNext()) {
+            Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo info = entry.getValue();
+            return info.mediaPlayer.getVolume();
+        }
+        return 0;
+    }
+
+    /**
+     * 设置所有频道的mediaPlayer静音状态
+     *
+     * @param mute 静音状态
+     */
+    private void setMuteAll(boolean mute) {
+        Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo info = entry.getValue();
+            info.mediaPlayer.setMute(mute);
+        }
+    }
+
+    /**
+     * 获取最高优先级的mediaPlayer静音状态
+     *
+     * @return true 静音,false 非静音
+     */
+    private boolean getMuteTopPriority() {
+        Iterator<Map.Entry<String, ChannelMediaPlayerInfo>> it = mediaPlayers.entrySet().iterator();
+        if (it.hasNext()) {
+            Map.Entry<String, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo info = entry.getValue();
+            return info.mediaPlayer.getMute();
+        }
+        return false;
+    }
+
+    protected void findToPlay() {
+        LogUtil.d(TAG, "findToPlay");
+        // 找到最高优先级的重新播放
+        Iterator<Map.Entry<Integer, ChannelMediaPlayerInfo>> it = currentPlayMap.entrySet().iterator();
+        if (!it.hasNext()) {
+            return;
+        }
+        Map.Entry<Integer, ChannelMediaPlayerInfo> entry = it.next();
+        ChannelMediaPlayerInfo info = entry.getValue();
+        LogUtil.d(TAG, "findToPlay-channelName:" + info.channelName);
+        if (info.mediaPlayer.getPlayState() == IMediaPlayer.PlayState.PAUSED) {
+            LogUtil.d(TAG, "findToPlay-value-resume:" + info.priority);
+            info.mediaPlayer.resume();
+        } else {
+            LogUtil.d(TAG, "findToPlay-PlayState:" + info.mediaPlayer.getPlayState());
+            // 不是处于正在播放或者准备播放中或者准备完成,开始播放
+            if (info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PLAYING
+                    && info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PREPARING
+                    && info.mediaPlayer.getPlayState() != IMediaPlayer.PlayState.PREPARED) {
+                LogUtil.d(TAG, "findToPlay-value-play:" + info.priority);
+                info.mediaPlayer.play(info.mediaResource);
+            } else {
+                LogUtil.d(TAG, "findToPlay-value-isPlaying-false:" + info.priority);
+            }
+        }
+    }
+
+    private final class ListenerProxy extends IMediaPlayer.SimpleMediaPlayerListener {
+        private String channelName;
+
+        ListenerProxy(String channelName) {
+            this.channelName = channelName;
+        }
+
+        @Override
+        public void onStopped() {
+            super.onStopped();
+            // stop 后就删除不需要播放了
+            int priority = getPriorityByChannelName(channelName);
+            LogUtil.d(TAG, "ListenerProxy onStopped  del:" + channelName);
+            if (priority != UNKNOWN_PRIORITY) {
+                currentPlayMap.remove(priority);
+            }
+            LogUtil.d(TAG, "ListenerProxy onStopped after del :" + currentPlayMap.size());
+        }
+
+        @Override
+        public void onCompletion() {
+            super.onCompletion();
+            LogUtil.d(TAG, "ListenerProxy onCompletion,channelName:" + channelName);
+            // 删除当前的
+            int priority = BaseMultiChannelMediaPlayer.this.getPriorityByChannelName(channelName);
+            if (priority != UNKNOWN_PRIORITY) {
+                currentPlayMap.remove(priority);
+            }
+        }
+    }
+
+    /**
+     * 带有优先级信息的IMediaPlayer
+     */
+    private final class ChannelMediaPlayer implements IMediaPlayer {
+        private ChannelMediaPlayerInfo mediaPlayerInfo;
+        private String channelName;
+        private IMediaPlayer mediaPlayer;
+
+        ChannelMediaPlayer(ChannelMediaPlayerInfo info) {
+            this.mediaPlayerInfo = info;
+            this.channelName = mediaPlayerInfo.channelName;
+            this.mediaPlayer = mediaPlayerInfo.mediaPlayer;
+        }
+
+        @Override
+        public void play(MediaResource mediaResource) {
+            LogUtil.d(TAG, "ChannelMediaPlayer-play,will handlePlay");
+            BaseMultiChannelMediaPlayer.this.handlePlay(channelName, mediaResource);
+        }
+
+        @Override
+        public void pause() {
+            mediaPlayer.pause();
+        }
+
+        @Override
+        public void stop() {
+            LogUtil.d(TAG, "ChannelMediaPlayer-stop-channelName:" + channelName);
+            BaseMultiChannelMediaPlayer.this.handleStop(channelName);
+        }
+
+        @Override
+        public void resume() {
+            mediaPlayer.resume();
+        }
+
+        @Override
+        public void seekTo(int milliseconds) {
+            mediaPlayer.seekTo(milliseconds);
+        }
+
+        @Override
+        public void release() {
+            mediaPlayer.release();
+        }
+
+        @Override
+        public PlayState getPlayState() {
+            return mediaPlayer.getPlayState();
+        }
+
+        @Override
+        public void setVolume(float volume) {
+            mediaPlayer.setVolume(volume);
+        }
+
+        @Override
+        public float getVolume() {
+            return mediaPlayer.getVolume();
+        }
+
+        @Override
+        public void setMute(boolean mute) {
+            mediaPlayer.setMute(mute);
+        }
+
+        @Override
+        public boolean getMute() {
+            return mediaPlayer.getMute();
+        }
+
+        @Override
+        public long getCurrentPosition() {
+            return mediaPlayer.getCurrentPosition();
+        }
+
+        @Override
+        public long getDuration() {
+            return mediaPlayer.getDuration();
+        }
+
+        @Override
+        public float getBufferPercentage() {
+            return mediaPlayer.getBufferPercentage();
+        }
+
+        @Override
+        public void addMediaPlayerListener(IMediaPlayerListener listener) {
+            // 注意add的顺序
+            // 先1后2的目的是播放完要先从等待播放map中删除对应改成播放完的那一条。
+            // 1.先add wrappedListener
+            IMediaPlayerListener wrappedListener =
+                    new ListenerProxy(channelName);
+            mediaPlayer.addMediaPlayerListener(wrappedListener);
+
+            // 2.再addDeviceModule通知到DeviceModule
+            mediaPlayer.addMediaPlayerListener(listener);
+        }
+
+        @Override
+        public void removeMediaPlayerListener(IMediaPlayerListener listener) {
+            mediaPlayer.removeMediaPlayerListener(listener);
+        }
+
+        @Override
+        public void setActive(boolean isActive) {
+            LogUtil.d(TAG, "ChannelMediaPlayer-setActive-isActive:" + isActive);
+            mediaPlayer.setActive(isActive);
+            // 不是处于活跃频道
+            if (!isActive && mediaPlayer.getPlayState() != IMediaPlayer.PlayState.STOPPED) {
+                BaseMultiChannelMediaPlayer.this.handleActive();
+            }
+        }
+
+        @Override
+        public boolean isActive() {
+            return mediaPlayer.isActive();
+        }
+    }
+
+    /**
+     * 处理停止播放
+     */
+    private void handleStop(String channelName) {
+        stop(channelName);
+        pauseAll();
+    }
+
+    /**
+     * 设置对话通道不活跃后的处理逻辑
+     */
+    private void handleActive() {
+        // 找到最高优先级的开始播放
+        findToPlay();
+    }
+
+    /**
+     * 控制接口
+     */
+    public interface ISpeakerController {
+        /**
+         * 设置音量(0-1)
+         *
+         * @param volume 音量(0-1)
+         */
+        void setVolume(float volume);
+
+        /**
+         * 获取当前最高通道的音量
+         *
+         * @return 音量(0-1)
+         */
+        float getVolume();
+
+        /**
+         * 设置是否静音
+         *
+         * @param mute 是否静音
+         */
+        void setMute(boolean mute);
+
+        /**
+         * 获取当前最高通道的静音状态
+         *
+         * @return 静音状态,true 是静音
+         */
+        boolean getMute();
+    }
+
+    /**
+     * 给speak-controller 用的,控制一些音量等操作
+     */
+    private final class SpeakerControllerImpl implements ISpeakerController {
+
+        @Override
+        public void setVolume(float volume) {
+            BaseMultiChannelMediaPlayer.this.setVolumeAll(volume);
+            findToPlay();
+        }
+
+        @Override
+        public float getVolume() {
+            return BaseMultiChannelMediaPlayer.this.getVolumeTopPriority();
+        }
+
+        @Override
+        public void setMute(boolean mute) {
+            BaseMultiChannelMediaPlayer.this.setMuteAll(mute);
+            findToPlay();
+        }
+
+        @Override
+        public boolean getMute() {
+            return BaseMultiChannelMediaPlayer.this.getMuteTopPriority();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsClient.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.dispatcher.AudioData;
+import com.baidu.duer.dcs.framework.dispatcher.MultipartParser;
+import com.baidu.duer.dcs.framework.heartbeat.HeartBeat;
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.http.HttpRequestInterface;
+import com.baidu.duer.dcs.http.OkHttpRequestImpl;
+import com.baidu.duer.dcs.http.callback.ResponseCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * 和服务器端保持长连接、发送events和接收directives和维持心跳
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsClient {
+    public static final String TAG = DcsClient.class.getSimpleName();
+    private final DcsResponseDispatcher dcsResponseDispatcher;
+    private final HttpRequestInterface httpRequestImp;
+    private final HeartBeat heartBeat;
+    private IDcsClientListener dcsClientListener;
+
+    public DcsClient(DcsResponseDispatcher dcsResponseDispatcher, IDcsClientListener dcsClientListener) {
+        this.dcsResponseDispatcher = dcsResponseDispatcher;
+        this.dcsClientListener = dcsClientListener;
+        httpRequestImp = new OkHttpRequestImpl();
+        heartBeat = new HeartBeat(httpRequestImp);
+        heartBeat.setHeartbeatListener(new HeartBeat.IHeartbeatListener() {
+            @Override
+            public void onStartConnect() {
+                startConnect();
+            }
+        });
+    }
+
+    public void release() {
+        heartBeat.release();
+        httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+        httpRequestImp.cancelRequest(HttpConfig.HTTP_EVENT_TAG);
+    }
+
+    /**
+     * 建立连接
+     */
+    public void startConnect() {
+        httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+        getDirectives(new IResponseListener() {
+            @Override
+            public void onSucceed(int statusCode) {
+                LogUtil.d(TAG, "getDirectives onSucceed");
+                fireOnConnected();
+                heartBeat.startNormalPing();
+            }
+
+            @Override
+            public void onFailed(String errorMessage) {
+                LogUtil.d(TAG, "getDirectives onFailed");
+                fireOnUnconnected();
+                heartBeat.startExceptionalPing();
+            }
+        });
+    }
+
+    /**
+     * 发送带流式请求
+     *
+     * @param requestBody       消息体
+     * @param streamRequestBody stream式消息体
+     * @param listener          回调
+     */
+    public void sendRequest(DcsRequestBody requestBody,
+                            DcsStreamRequestBody streamRequestBody, final IResponseListener listener) {
+        httpRequestImp.doPostEventMultipartAsync(requestBody,
+                streamRequestBody, getResponseCallback(dcsResponseDispatcher, new IResponseListener() {
+                    @Override
+                    public void onSucceed(int statusCode) {
+                        if (listener != null) {
+                            listener.onSucceed(statusCode);
+                        }
+                    }
+
+                    @Override
+                    public void onFailed(String errorMessage) {
+                        if (listener != null) {
+                            listener.onFailed(errorMessage);
+                        }
+
+                        heartBeat.startImmediatePing();
+                    }
+                }));
+    }
+
+    /**
+     * 发送普通请求
+     *
+     * @param requestBody 消息体
+     * @param listener    回调
+     */
+    public void sendRequest(DcsRequestBody requestBody, IResponseListener listener) {
+        httpRequestImp.doPostEventStringAsync(requestBody,
+                getResponseCallback(dcsResponseDispatcher, listener));
+    }
+
+    private void getDirectives(IResponseListener listener) {
+        httpRequestImp.cancelRequest(HttpConfig.HTTP_DIRECTIVES_TAG);
+        httpRequestImp.doGetDirectivesAsync(null,
+                getResponseCallback(dcsResponseDispatcher, listener));
+    }
+
+    private void fireOnConnected() {
+        if (dcsClientListener != null) {
+            dcsClientListener.onConnected();
+        }
+    }
+
+    private void fireOnUnconnected() {
+        if (dcsClientListener != null) {
+            dcsClientListener.onUnconnected();
+        }
+    }
+
+    private ResponseCallback getResponseCallback(final DcsResponseDispatcher dcsResponseDispatcher,
+                                                 final IResponseListener responseListener) {
+        ResponseCallback responseCallback = new ResponseCallback() {
+            @Override
+            public void onError(Call call, Exception e, int id) {
+                LogUtil.d(TAG, "onError,", e);
+                if (responseListener != null) {
+                    responseListener.onFailed(e.getMessage());
+                }
+            }
+
+            @Override
+            public void onResponse(Response response, int id) {
+                super.onResponse(response, id);
+                LogUtil.d(TAG, "onResponse OK ," + response.request().url());
+                LogUtil.d(TAG, "onResponse code ," + response.code());
+                if (responseListener != null) {
+                    responseListener.onSucceed(response.code());
+                }
+            }
+
+            @Override
+            public Response parseNetworkResponse(Response response, int id) throws Exception {
+                int statusCode = response.code();
+                if (statusCode == 200) {
+                    MultipartParser multipartParser = new MultipartParser(
+                            new MultipartParser.IMultipartParserListener() {
+                                @Override
+                                public void onResponseBody(DcsResponseBody responseBody) {
+                                    dcsResponseDispatcher.onResponseBody(responseBody);
+                                }
+
+                                @Override
+                                public void onAudioData(AudioData audioData) {
+                                    dcsResponseDispatcher.onAudioData(audioData);
+                                }
+
+                                @Override
+                                public void onParseFailed(String unParseMessage) {
+                                    dcsResponseDispatcher.onParseFailed(unParseMessage);
+                                }
+                            });
+
+                    try {
+                        multipartParser.parseResponse(response);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+                return response;
+            }
+        };
+
+        return responseCallback;
+    }
+
+    public interface IDcsClientListener {
+        void onConnected();
+
+        void onUnconnected();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsFramework.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
+import com.baidu.duer.dcs.devicemodule.system.SystemDeviceModule;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher.IDcsResponseHandler;
+import com.baidu.duer.dcs.framework.message.ClientContext;
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Event;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * dcs业务处理框架,用于分发指令(directives)、发送事件(events)和创建deviceModule等
+ * <p>
+ * Created by shenguanghao、wuruisheng on 2017/5/31.
+ */
+public class DcsFramework {
+    private static final String TAG = DcsFramework.class.getSimpleName();
+    // 管理平台相关的对象
+    private final IPlatformFactory platformFactory;
+    // 管理deviceModules
+    private final HashMap<String, BaseDeviceModule> dispatchDeviceModules;
+    // 创建会话Id
+    private final DialogRequestIdHandler dialogRequestIdHandler;
+    // 基于通道活跃状态和优先级进行mediaPlayer调度
+    private final BaseMultiChannelMediaPlayer multiChannelMediaPlayer;
+    // 创建deviceModule工厂
+    private DeviceModuleFactory deviceModuleFactory;
+    // 和服务器端保持长连接、发送events和接收directives和维持心跳
+    private DcsClient dcsClient;
+    // 用于DeviceModules发送events
+    private IMessageSender messageSender;
+    // 服务器端返回response调度中心
+    private DcsResponseDispatcher dcsResponseDispatcher;
+
+    public DcsFramework(IPlatformFactory platformFactory) {
+        this.platformFactory = platformFactory;
+        dispatchDeviceModules = new HashMap<>();
+        dialogRequestIdHandler = new DialogRequestIdHandler();
+        multiChannelMediaPlayer = new PauseStrategyMultiChannelMediaPlayer(platformFactory);
+
+        createMessageSender();
+        createDcsClient();
+        createDeviceModuleFactory();
+    }
+
+    public void release() {
+        for (BaseDeviceModule deviceModule : dispatchDeviceModules.values()) {
+            deviceModule.release();
+        }
+        dcsClient.release();
+        dcsResponseDispatcher.release();
+    }
+
+    public DeviceModuleFactory getDeviceModuleFactory() {
+        return deviceModuleFactory;
+    }
+
+    private ArrayList<ClientContext> clientContexts() {
+        ArrayList<ClientContext> clientContexts = new ArrayList<>();
+        for (BaseDeviceModule deviceModule : dispatchDeviceModules.values()) {
+            ClientContext clientContext = deviceModule.clientContext();
+            if (clientContext != null) {
+                clientContexts.add(clientContext);
+            }
+        }
+
+        return clientContexts;
+    }
+
+    private void handleDirective(Directive directive) {
+        String namespace = directive.header.getNamespace();
+        try {
+            BaseDeviceModule deviceModule = dispatchDeviceModules.get(namespace);
+            if (deviceModule != null) {
+                deviceModule.handleDirective(directive);
+            } else {
+                String message = "No device to handle the directive";
+                throw new HandleDirectiveException(
+                        HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message);
+            }
+        } catch (HandleDirectiveException exception) {
+            getSystemDeviceModule().sendExceptionEncounteredEvent(directive.rawMessage,
+                    exception.getExceptionType(), exception.getMessage());
+        } catch (Exception exception) {
+            getSystemDeviceModule().sendExceptionEncounteredEvent(directive.rawMessage,
+                    HandleDirectiveException.ExceptionType.INTERNAL_ERROR,
+                    exception.getMessage()
+            );
+        }
+    }
+
+    private void createDcsClient() {
+        IDcsResponseHandler responseHandler = new IDcsResponseHandler() {
+            @Override
+            public void onResponse(final DcsResponseBody responseBody) {
+                platformFactory.getMainHandler().post(new Runnable() {
+                    @Override
+                    public void run() {
+                        LogUtil.d(TAG, "DcsResponseBodyEnqueue-handleDirective-MSG:"
+                                + responseBody.getDirective().rawMessage);
+                        handleDirective(responseBody.getDirective());
+                    }
+                });
+            }
+
+            @Override
+            public void onParseFailed(String unParsedMessage) {
+                LogUtil.d(TAG, "DcsResponseBodyEnqueue-handleDirective-onParseFailed");
+                String message = "parse failed";
+                getSystemDeviceModule().sendExceptionEncounteredEvent(unParsedMessage,
+                        HandleDirectiveException.ExceptionType.UNEXPECTED_INFORMATION_RECEIVED,
+                        message);
+            }
+        };
+
+        dcsResponseDispatcher = new DcsResponseDispatcher(dialogRequestIdHandler, responseHandler);
+        dcsClient = new DcsClient(dcsResponseDispatcher, new DcsClient.IDcsClientListener() {
+            @Override
+            public void onConnected() {
+                LogUtil.d(TAG, "onConnected");
+                getSystemDeviceModule().sendSynchronizeStateEvent();
+            }
+
+            @Override
+            public void onUnconnected() {
+                LogUtil.d(TAG, "onUnconnected");
+            }
+        });
+        dcsClient.startConnect();
+    }
+
+    private void createMessageSender() {
+        messageSender = new IMessageSender() {
+            @Override
+            public void sendEvent(Event event, DcsStreamRequestBody streamRequestBody,
+                                  IResponseListener responseListener) {
+                DcsRequestBody requestBody = new DcsRequestBody(event);
+                requestBody.setClientContext(clientContexts());
+                dcsClient.sendRequest(requestBody, streamRequestBody, responseListener);
+            }
+
+            @Override
+            public void sendEvent(Event event, IResponseListener responseListener) {
+                sendEventRequest(event, null, responseListener);
+            }
+
+            @Override
+            public void sendEvent(Event event) {
+                sendEventRequest(event, null, null);
+            }
+
+            @Override
+            public void sentEventWithClientContext(Event event, IResponseListener responseListener) {
+                sendEventRequest(event, clientContexts(), responseListener);
+            }
+        };
+    }
+
+    private void sendEventRequest(Event event,
+                                  ArrayList<ClientContext> clientContexts,
+                                  IResponseListener responseListener) {
+        DcsRequestBody dcsRequestBody = new DcsRequestBody(event);
+        dcsRequestBody.setClientContext(clientContexts);
+        dcsClient.sendRequest(dcsRequestBody, responseListener);
+    }
+
+    private void createDeviceModuleFactory() {
+        deviceModuleFactory = new DeviceModuleFactory(new DeviceModuleFactory.IDeviceModuleHandler() {
+            @Override
+            public IPlatformFactory getPlatformFactory() {
+                return platformFactory;
+            }
+
+            @Override
+            public DialogRequestIdHandler getDialogRequestIdHandler() {
+                return dialogRequestIdHandler;
+            }
+
+            @Override
+            public IMessageSender getMessageSender() {
+                return messageSender;
+            }
+
+            @Override
+            public BaseMultiChannelMediaPlayer getMultiChannelMediaPlayer() {
+                return multiChannelMediaPlayer;
+            }
+
+            @Override
+            public void addDeviceModule(BaseDeviceModule deviceModule) {
+                DcsFramework.this.addDeviceModule(deviceModule);
+            }
+
+            @Override
+            public DcsResponseDispatcher getResponseDispatcher() {
+                return dcsResponseDispatcher;
+            }
+        });
+    }
+
+    private void addDeviceModule(BaseDeviceModule deviceModule) {
+        dispatchDeviceModules.put(deviceModule.getNameSpace(), deviceModule);
+    }
+
+    private SystemDeviceModule getSystemDeviceModule() {
+        return deviceModuleFactory.getSystemDeviceModule();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DcsResponseDispatcher.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.dispatcher.AudioData;
+import com.baidu.duer.dcs.framework.dispatcher.DcsResponseBodyEnqueue;
+import com.baidu.duer.dcs.framework.dispatcher.WithDialogIdBlockThread;
+import com.baidu.duer.dcs.framework.dispatcher.WithoutDialogIdBlockThread;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * response调度中心,带有dialogRequestId directives按照顺序执行,对于speak指令播报完才执行下一个指令;
+ * 设备端收到不带dialogRequestId的directives立即执行
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseDispatcher {
+    private final WithDialogIdBlockThread withDialogIdBlockThread;
+    private final WithoutDialogIdBlockThread withoutDialogIdBlockThread;
+    private final BlockingQueue<DcsResponseBody> dependentQueue;
+    private final BlockingQueue<DcsResponseBody> independentQueue;
+    private final DcsResponseBodyEnqueue dcsResponseBodyEnqueue;
+    private final IDcsResponseHandler responseHandler;
+
+    public DcsResponseDispatcher(final DialogRequestIdHandler dialogRequestIdHandler,
+                                 final IDcsResponseHandler responseHandler) {
+        this.responseHandler = responseHandler;
+        dependentQueue = new LinkedBlockingDeque<>();
+        independentQueue = new LinkedBlockingDeque<>();
+        dcsResponseBodyEnqueue = new DcsResponseBodyEnqueue(dialogRequestIdHandler, dependentQueue,
+                independentQueue);
+
+        withDialogIdBlockThread = new WithDialogIdBlockThread(dependentQueue, responseHandler,
+                "withDialogIdBlockThread");
+        withoutDialogIdBlockThread = new WithoutDialogIdBlockThread(independentQueue, responseHandler,
+                "withoutDialogIdBlockThread");
+        withDialogIdBlockThread.start();
+        withoutDialogIdBlockThread.start();
+    }
+
+    public void interruptDispatch() {
+        // 先清空队列,比如播放一首歌:speak+play指令组合的方式,在speak播报过程中进行打断,play就不需要执行了
+        withDialogIdBlockThread.clear();
+        // 让其处于等待新的指令处理
+        unBlockDependentQueue();
+    }
+
+    public void blockDependentQueue() {
+        withDialogIdBlockThread.block();
+    }
+
+    public void unBlockDependentQueue() {
+        withDialogIdBlockThread.unblock();
+    }
+
+    public void onResponseBody(DcsResponseBody responseBody) {
+        dcsResponseBodyEnqueue.handleResponseBody(responseBody);
+    }
+
+    public void onAudioData(AudioData audioData) {
+        dcsResponseBodyEnqueue.handleAudioData(audioData);
+    }
+
+    public void onParseFailed(String unParseMessage) {
+        if (responseHandler != null) {
+            responseHandler.onParseFailed(unParseMessage);
+        }
+    }
+
+    public void release() {
+        withDialogIdBlockThread.stopThread();
+        withoutDialogIdBlockThread.stopThread();
+    }
+
+    public interface IDcsResponseHandler {
+        void onResponse(DcsResponseBody responseBody);
+
+        void onParseFailed(String unParseMessage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DeviceModuleFactory.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.devicemodule.alerts.AlertsDeviceModule;
+import com.baidu.duer.dcs.devicemodule.audioplayer.AudioPlayerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.playbackcontroller.PlaybackControllerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.screen.ScreenDeviceModule;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.SpeakerControllerDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.SystemDeviceModule;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.voiceinput.VoiceInputDeviceModule;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.VoiceOutputDeviceModule;
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.systeminterface.IPlaybackController;
+import com.baidu.duer.dcs.systeminterface.IWebView;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 创建语音输入、语音输出、扬声器、音频播放器、播放控制、闹钟、屏幕显示和系统等deviceModule
+ * <p>
+ * Created by wuruisheng on 2017/6/15.
+ */
+public class DeviceModuleFactory {
+    private static final String TAG = DeviceModuleFactory.class.getSimpleName();
+    private final IDeviceModuleHandler deviceModuleHandler;
+    private final IMediaPlayer dialogMediaPlayer;
+
+    private VoiceInputDeviceModule voiceInputDeviceModule;
+    private VoiceOutputDeviceModule voiceOutputDeviceModule;
+    private SpeakerControllerDeviceModule speakerControllerDeviceModule;
+    private AudioPlayerDeviceModule audioPlayerDeviceModule;
+    private AlertsDeviceModule alertsDeviceModule;
+    private SystemDeviceModule systemDeviceModule;
+    private PlaybackControllerDeviceModule playbackControllerDeviceModule;
+    private ScreenDeviceModule screenDeviceModule;
+
+    // 数字越大,优先级越高,播放优先级
+    private enum MediaChannel {
+        SPEAK("dialog", 3),
+        ALERT("alert", 2),
+        AUDIO("audio", 1);
+
+        private String channelName;
+        private int priority;
+
+        MediaChannel(String channelName, int priority) {
+            this.channelName = channelName;
+            this.priority = priority;
+        }
+    }
+
+    public DeviceModuleFactory(final IDeviceModuleHandler deviceModuleHandler) {
+        this.deviceModuleHandler = deviceModuleHandler;
+        dialogMediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+                .addNewChannel(MediaChannel.SPEAK.channelName, MediaChannel.SPEAK.priority);
+    }
+
+
+    public void createVoiceInputDeviceModule() {
+        /*
+         * 传入VoiceOutput的MediaPlayer,因为根据dcs协议的规范
+         * 对话通道:
+         * 对应语音输入(Voice Input)和语音输出(Voice Output)端能力;
+         * 用户在语音请求时,或者设备在执行Speak指令进行播报时,对话通道进入活跃状态
+         */
+        voiceInputDeviceModule = new VoiceInputDeviceModule(
+                dialogMediaPlayer, deviceModuleHandler.getMessageSender(),
+                deviceModuleHandler.getPlatformFactory().getVoiceInput(),
+                deviceModuleHandler.getDialogRequestIdHandler(),
+                deviceModuleHandler.getResponseDispatcher());
+        deviceModuleHandler.addDeviceModule(voiceInputDeviceModule);
+    }
+
+    public VoiceInputDeviceModule getVoiceInputDeviceModule() {
+        return voiceInputDeviceModule;
+    }
+
+    public void createVoiceOutputDeviceModule() {
+        voiceOutputDeviceModule = new VoiceOutputDeviceModule(dialogMediaPlayer,
+                deviceModuleHandler.getMessageSender());
+        voiceOutputDeviceModule.addVoiceOutputListener(new VoiceOutputDeviceModule.IVoiceOutputListener() {
+            @Override
+            public void onVoiceOutputStarted() {
+                LogUtil.d(TAG, "DcsResponseBodyEnqueue-onVoiceOutputStarted ok ");
+                deviceModuleHandler.getResponseDispatcher().blockDependentQueue();
+            }
+
+            @Override
+            public void onVoiceOutputFinished() {
+                LogUtil.d(TAG, "DcsResponseBodyEnqueue-onVoiceOutputFinished ok ");
+                deviceModuleHandler.getResponseDispatcher().unBlockDependentQueue();
+            }
+        });
+
+        deviceModuleHandler.addDeviceModule(voiceOutputDeviceModule);
+    }
+
+    public void createSpeakControllerDeviceModule() {
+        BaseMultiChannelMediaPlayer.ISpeakerController speakerController =
+                deviceModuleHandler.getMultiChannelMediaPlayer().getSpeakerController();
+        speakerControllerDeviceModule =
+                new SpeakerControllerDeviceModule(speakerController,
+                        deviceModuleHandler.getMessageSender());
+        deviceModuleHandler.addDeviceModule(speakerControllerDeviceModule);
+    }
+
+    public void createAudioPlayerDeviceModule() {
+        IMediaPlayer mediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+                .addNewChannel(MediaChannel.AUDIO.channelName,
+                        MediaChannel.AUDIO.priority);
+        audioPlayerDeviceModule = new AudioPlayerDeviceModule(mediaPlayer,
+                deviceModuleHandler.getMessageSender());
+        deviceModuleHandler.addDeviceModule(audioPlayerDeviceModule);
+    }
+
+    public AudioPlayerDeviceModule getAudioPlayerDeviceModule() {
+        return audioPlayerDeviceModule;
+    }
+
+    public void createAlertsDeviceModule() {
+        IMediaPlayer mediaPlayer = deviceModuleHandler.getMultiChannelMediaPlayer()
+                .addNewChannel(MediaChannel.ALERT.channelName,
+                        MediaChannel.ALERT.priority);
+        alertsDeviceModule = new AlertsDeviceModule(mediaPlayer,
+                deviceModuleHandler.getPlatformFactory().createAlertsDataStore(),
+                deviceModuleHandler.getMessageSender(),
+                deviceModuleHandler.getPlatformFactory().getMainHandler());
+
+        alertsDeviceModule.addAlertListener(new AlertsDeviceModule.IAlertListener() {
+            @Override
+            public void onAlertStarted(String alertToken) {
+            }
+        });
+
+        deviceModuleHandler.addDeviceModule(alertsDeviceModule);
+    }
+
+    public void createSystemDeviceModule() {
+        systemDeviceModule = new SystemDeviceModule(deviceModuleHandler.getMessageSender());
+        systemDeviceModule.addModuleListener(new SystemDeviceModule.IDeviceModuleListener() {
+            @Override
+            public void onSetEndpoint(SetEndPointPayload endPointPayload) {
+                if (null != endPointPayload) {
+                    String endpoint = endPointPayload.getEndpoint();
+                    if (null != endpoint && endpoint.length() > 0) {
+                        HttpConfig.setEndpoint(endpoint);
+                    }
+                }
+            }
+
+            @Override
+            public void onThrowException(ThrowExceptionPayload throwExceptionPayload) {
+                LogUtil.v(TAG, throwExceptionPayload.toString());
+            }
+        });
+        deviceModuleHandler.addDeviceModule(systemDeviceModule);
+    }
+
+    public SystemDeviceModule getSystemDeviceModule() {
+        return systemDeviceModule;
+    }
+
+    public SystemDeviceModule.Provider getSystemProvider() {
+        return systemDeviceModule.getProvider();
+    }
+
+    public void createPlaybackControllerDeviceModule() {
+        IPlaybackController playback = deviceModuleHandler.getPlatformFactory().getPlayback();
+        playbackControllerDeviceModule = new PlaybackControllerDeviceModule(playback,
+                deviceModuleHandler.getMessageSender(), alertsDeviceModule);
+        deviceModuleHandler.addDeviceModule(playbackControllerDeviceModule);
+    }
+
+    public void createScreenDeviceModule() {
+        IWebView webView = deviceModuleHandler.getPlatformFactory().getWebView();
+        screenDeviceModule = new ScreenDeviceModule(webView, deviceModuleHandler.getMessageSender());
+        deviceModuleHandler.addDeviceModule(screenDeviceModule);
+    }
+
+    public interface IDeviceModuleHandler {
+        IPlatformFactory getPlatformFactory();
+
+        DialogRequestIdHandler getDialogRequestIdHandler();
+
+        IMessageSender getMessageSender();
+
+        BaseMultiChannelMediaPlayer getMultiChannelMediaPlayer();
+
+        void addDeviceModule(BaseDeviceModule deviceModule);
+
+        DcsResponseDispatcher getResponseDispatcher();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/DialogRequestIdHandler.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import java.util.UUID;
+
+/**
+ * 生成dialogRequestId
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class DialogRequestIdHandler {
+    private String activeDialogRequestId;
+
+    public DialogRequestIdHandler() {
+    }
+
+    public String createActiveDialogRequestId() {
+        activeDialogRequestId = UUID.randomUUID().toString();
+        return activeDialogRequestId;
+    }
+
+    /**
+     * 判断当前dialogRequestId是否活跃的
+     *
+     * @param dialogRequestId dialogRequestId
+     * @return dialogRequestId与activeDialogRequestId相等则返回true,否则返回false
+     */
+    public Boolean isActiveDialogRequestId(String dialogRequestId) {
+        return activeDialogRequestId != null && activeDialogRequestId.equals(dialogRequestId);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IMessageSender.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.framework.message.Event;
+
+/**
+ * 发送event接口
+ * <p>
+ * Created by wuruisheng on 2017/6/15.
+ */
+public interface IMessageSender {
+    /**
+     * 发送event
+     *
+     * @param event
+     */
+    void sendEvent(Event event);
+
+    /**
+     * 发送event
+     *
+     * @param event
+     * @param responseListener 回调
+     */
+    void sendEvent(Event event, IResponseListener responseListener);
+
+    /**
+     * 发送event且带有stream
+     *
+     * @param event             event对象
+     * @param streamRequestBody stream对象
+     * @param responseListener  回调
+     */
+    void sendEvent(Event event, DcsStreamRequestBody streamRequestBody, IResponseListener responseListener);
+
+    /**
+     * 发送event带上clientContext
+     *
+     * @param event            event对象
+     * @param responseListener 回调
+     */
+    void sentEventWithClientContext(Event event, IResponseListener responseListener);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/IResponseListener.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+/**
+ * 网络请求回调
+ * <p>
+ * Created by wuruisheng on 2017/6/17.
+ */
+public interface IResponseListener {
+    /**
+     * 成功回调
+     *
+     * @param statusCode http返回statusCode
+     */
+    void onSucceed(int statusCode);
+
+    /**
+     * 失败回调
+     *
+     * @param errorMessage 出错的异常信息
+     */
+    void onFailed(String errorMessage);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/PauseStrategyMultiChannelMediaPlayer.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework;
+
+import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
+import com.baidu.duer.dcs.systeminterface.IPlatformFactory;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 暂停模式的播放控制策略
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/6.
+ */
+public class PauseStrategyMultiChannelMediaPlayer extends BaseMultiChannelMediaPlayer {
+    private static final String TAG = BaseMultiChannelMediaPlayer.class.getSimpleName();
+
+    public PauseStrategyMultiChannelMediaPlayer(IPlatformFactory factory) {
+        super(factory);
+    }
+
+    @Override
+    protected void handlePlay(String channelName, IMediaPlayer.MediaResource mediaResource) {
+        int priority = getPriorityByChannelName(channelName);
+        LogUtil.d(TAG, "handlePlay-priority:" + priority);
+        if (priority == UNKNOWN_PRIORITY) {
+            return;
+        }
+        ChannelMediaPlayerInfo info = new ChannelMediaPlayerInfo();
+        info.mediaPlayer = getMediaPlayer(channelName);
+        info.priority = priority;
+        info.channelName = channelName;
+        info.mediaResource = mediaResource;
+        currentPlayMap.put(priority, info);
+
+        // 把比当前优先级低的播放器都暂停
+        Iterator<Map.Entry<Integer, ChannelMediaPlayerInfo>> it = currentPlayMap.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<Integer, ChannelMediaPlayerInfo> entry = it.next();
+            ChannelMediaPlayerInfo value = entry.getValue();
+            LogUtil.d(TAG, "handlePlay-value:" + value.priority);
+            if (priority > value.priority) {
+                LogUtil.d(TAG, "handlePlay-value-pause:" + value.priority);
+                value.mediaPlayer.pause();
+            }
+        }
+        findToPlay();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/AudioData.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+/**
+ * 存储音频数据
+ * <p>
+ * Created by wuruisheng on 2017/5/13.
+ */
+public class AudioData {
+    public String contentId;
+    public byte[] partBytes;
+
+    public AudioData(String contentId, byte[] partBytes) {
+        this.contentId = contentId;
+        this.partBytes = partBytes;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/BaseBlockResponseThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 单独线程阻塞控制response回调处理
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public abstract class BaseBlockResponseThread extends Thread {
+    private static final String TAG = BaseBlockResponseThread.class.getSimpleName();
+    private BlockingQueue<DcsResponseBody> responseBodyDeque;
+    private DcsResponseDispatcher.IDcsResponseHandler responseHandler;
+    private volatile boolean block;
+    private volatile boolean isStop;
+
+    public BaseBlockResponseThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+                                   DcsResponseDispatcher.IDcsResponseHandler responseHandler, String threadName) {
+        this.responseBodyDeque = responseBodyDeque;
+        this.responseHandler = responseHandler;
+        setName(threadName);
+    }
+
+    public synchronized void block() {
+        block = true;
+    }
+
+    public synchronized void unblock() {
+        block = false;
+        notify();
+    }
+
+    public synchronized void clear() {
+        responseBodyDeque.clear();
+    }
+
+    public synchronized void stopThread() {
+        clear();
+        isStop = true;
+        this.interrupt();
+    }
+
+    @Override
+    public void run() {
+        while (!isStop) {
+            try {
+                synchronized (this) {
+                    if (block) {
+                        wait();
+                    }
+                }
+
+                if (responseHandler != null) {
+                    DcsResponseBody responseBody = responseBodyDeque.take();
+                    responseHandler.onResponse(responseBody);
+
+                    if (shouldBlock(responseBody)) {
+                        block = true;
+                    }
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    abstract boolean shouldBlock(DcsResponseBody responseBody);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsJsonProcessingException.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import org.codehaus.jackson.JsonProcessingException;
+
+/**
+ * json序列化成异常对象
+ * <p>
+ * Created by wuruisheng on 2017/6/8.
+ */
+public class DcsJsonProcessingException extends JsonProcessingException {
+    private String unparsedCotent;
+
+    public DcsJsonProcessingException(String message, JsonProcessingException exception, String unparsedCotent) {
+        super(message, exception);
+        this.unparsedCotent = unparsedCotent;
+    }
+
+    public String getUnparsedCotent() {
+        return unparsedCotent;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/DcsResponseBodyEnqueue.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.message.AttachedContentPayload;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.framework.DialogRequestIdHandler;
+import com.baidu.duer.dcs.framework.message.DialogRequestIdHeader;
+import com.baidu.duer.dcs.framework.message.Directive;
+import com.baidu.duer.dcs.framework.message.Header;
+import com.baidu.duer.dcs.framework.message.Payload;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+
+/**
+ * 带有dialogRequestId response进入dependentQueue队列,否则进入independentQueue
+ * 带有attached的directive需要知道找到对应的二进制数据才放到上述队列中
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseBodyEnqueue {
+    private static final String TAG = DcsResponseBodyEnqueue.class.getSimpleName();
+    private final DialogRequestIdHandler dialogRequestIdHandler;
+    private final Queue<DcsResponseBody> dependentQueue;
+    private final Queue<DcsResponseBody> independentQueue;
+    private final Queue<DcsResponseBody> incompleteResponseQueue;
+    private final Map<String, AudioData> audioDataMap;
+
+    public DcsResponseBodyEnqueue(DialogRequestIdHandler dialogRequestIdHandler,
+                                  Queue<DcsResponseBody> dependentQueue,
+                                  Queue<DcsResponseBody> independentQueue) {
+        this.dialogRequestIdHandler = dialogRequestIdHandler;
+        this.dependentQueue = dependentQueue;
+        this.independentQueue = independentQueue;
+        incompleteResponseQueue = new LinkedList<>();
+        audioDataMap = new HashMap<>();
+    }
+
+    public synchronized void handleResponseBody(DcsResponseBody responseBody) {
+        incompleteResponseQueue.add(responseBody);
+        matchAudioDataWithResponseBody();
+    }
+
+    public synchronized void handleAudioData(AudioData audioData) {
+        audioDataMap.put(audioData.contentId, audioData);
+        matchAudioDataWithResponseBody();
+    }
+
+    private void matchAudioDataWithResponseBody() {
+        for (DcsResponseBody responseBody : incompleteResponseQueue) {
+            Directive directive = responseBody.getDirective();
+            if (directive == null) {
+                return;
+            }
+
+            Payload payload = responseBody.getDirective().payload;
+            if (payload instanceof AttachedContentPayload) {
+                AttachedContentPayload attachedContentPayload = (AttachedContentPayload) payload;
+                String contentId = attachedContentPayload.getAttachedContentId();
+                AudioData audioData = audioDataMap.remove(contentId);
+                if (audioData != null) {
+                    attachedContentPayload.setAttachedContent(contentId, audioData.partBytes);
+                }
+            }
+        }
+
+        findCompleteResponseBody();
+    }
+
+    private void findCompleteResponseBody() {
+        Iterator<DcsResponseBody> iterator = incompleteResponseQueue.iterator();
+        while (iterator.hasNext()) {
+            DcsResponseBody responseBody = iterator.next();
+            Payload payload = responseBody.getDirective().payload;
+            if (payload instanceof AttachedContentPayload) {
+                AttachedContentPayload attachedContentPayload = (AttachedContentPayload) payload;
+
+                if (!attachedContentPayload.requiresAttachedContent()) {
+                    // The front most directive IS complete.
+                    enqueueResponseBody(responseBody);
+                    iterator.remove();
+                } else {
+                    break;
+                }
+            } else {
+                // Immediately enqueue any directive which does not contain audio content
+                enqueueResponseBody(responseBody);
+                iterator.remove();
+            }
+        }
+    }
+
+    private void enqueueResponseBody(DcsResponseBody responseBody) {
+        LogUtil.d(TAG, "DcsResponseBodyEnqueue-RecordThread:" + responseBody.getDirective().rawMessage);
+        Header header = responseBody.getDirective().header;
+        DialogRequestIdHeader dialogRequestIdHeader = (DialogRequestIdHeader) header;
+        if (dialogRequestIdHeader.getDialogRequestId() == null) {
+            LogUtil.d(TAG, "DcsResponseBodyEnqueue-DialogRequestId  is null ,add to independentQueue");
+            independentQueue.add(responseBody);
+        } else if (dialogRequestIdHandler.isActiveDialogRequestId(dialogRequestIdHeader.getDialogRequestId())) {
+            LogUtil.d(TAG, "DcsResponseBodyEnqueue-DialogRequestId  not  null,add to dependentQueue");
+            dependentQueue.add(responseBody);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/MultipartParser.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+import com.baidu.duer.dcs.http.HttpConfig;
+
+import org.apache.commons.fileupload.MultipartStream;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+
+import okhttp3.Response;
+
+/**
+ * 把从服务器返回multipart中json对象和二进制解析成directive对象
+ * <p>
+ * Created by wuruisheng on 2017/5/12.
+ */
+public class MultipartParser extends Parser {
+    private static final int BUFFER_SIZE = 512;
+    private final IMultipartParserListener multipartParserListener;
+
+    public MultipartParser(IMultipartParserListener listener) {
+        this.multipartParserListener = listener;
+    }
+
+    public void parseResponse(Response response) throws IOException {
+        String boundary = getBoundary(response);
+        if (boundary != null) {
+            parseStream(response.body().byteStream(), boundary);
+        }
+    }
+
+    private void parseStream(InputStream inputStream, String boundary) throws IOException {
+        MultipartStream multipartStream = new MultipartStream(inputStream, boundary.getBytes(), BUFFER_SIZE, null);
+        parseMultipartStream(multipartStream);
+    }
+
+    private void parseMultipartStream(MultipartStream multipartStream) throws IOException {
+        try {
+            Boolean hasNextPart = multipartStream.skipPreamble();
+            while (hasNextPart) {
+                handlePart(multipartStream);
+                hasNextPart = multipartStream.readBoundary();
+            }
+        } catch (DcsJsonProcessingException exception) {
+            if (multipartParserListener != null) {
+                multipartParserListener.onParseFailed(exception.getUnparsedCotent());
+            }
+        } catch (MultipartStream.MalformedStreamException exception) {
+            // 用于处理 empty part
+        }
+    }
+
+    private void handlePart(MultipartStream multipartStream) throws IOException {
+        Map<String, String> headers = getPartHeaders(multipartStream);
+        if (headers != null) {
+            byte[] partBytes = getPartBytes(multipartStream);
+            Boolean isJsonData = isPartJSON(headers);
+            if (isJsonData) {
+                handleJsonData(partBytes);
+            } else {
+                handleAudio(headers, partBytes);
+            }
+        }
+    }
+
+    private void handleJsonData(byte[] partBytes) throws IOException {
+        final DcsResponseBody responseBody = parse(partBytes, DcsResponseBody.class);
+        if (multipartParserListener != null) {
+            multipartParserListener.onResponseBody(responseBody);
+        }
+    }
+
+    private void handleAudio(Map<String, String> headers, byte[] partBytes) {
+        String contentId = getMultipartContentId(headers);
+        final AudioData audioData = new AudioData(contentId, partBytes);
+        if (multipartParserListener != null) {
+            multipartParserListener.onAudioData(audioData);
+        }
+    }
+
+    private byte[] getPartBytes(MultipartStream multipartStream) throws IOException {
+        ByteArrayOutputStream data = new ByteArrayOutputStream();
+        multipartStream.readBodyData(data);
+        return data.toByteArray();
+    }
+
+    private Map<String, String> getPartHeaders(MultipartStream multipartStream) throws IOException {
+        String headers = multipartStream.readHeaders();
+        BufferedReader reader = new BufferedReader(new StringReader(headers));
+        Map<String, String> headerMap = new HashMap<>();
+        try {
+            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+                line = line.trim();
+                if (!StringUtils.isBlank(line) && line.contains(":")) {
+                    int colon = line.indexOf(":");
+                    String headerName = line.substring(0, colon).trim();
+                    String headerValue = line.substring(colon + 1).trim();
+                    headerMap.put(headerName.toLowerCase(), headerValue);
+                }
+            }
+        } catch (Exception e) {
+            throw e;
+        }
+
+        return headerMap;
+    }
+
+    private String getMultipartHeaderValue(Map<String, String> headers, String searchHeader) {
+        return headers.get(searchHeader.toLowerCase());
+    }
+
+    private String getMultipartContentId(Map<String, String> headers) {
+        String contentId = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_ID);
+        contentId = contentId.substring(1, contentId.length() - 1);
+        return contentId;
+    }
+
+    private boolean isPartJSON(Map<String, String> headers) {
+        String contentType = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_TYPE);
+        return StringUtils.contains(contentType, HttpConfig.ContentTypes.JSON);
+    }
+
+    private static String getBoundary(Response response) {
+        String headerValue = response.header(HttpConfig.HttpHeaders.CONTENT_TYPE);
+        String boundary = getHeaderParameter(headerValue, HttpConfig.Parameters.BOUNDARY);
+        return boundary;
+    }
+
+    private static String getHeaderParameter(final String headerValue, final String key) {
+        if ((headerValue == null) || (key == null)) {
+            return null;
+        }
+
+        String[] parts = headerValue.split(";");
+        for (String part : parts) {
+            part = part.trim();
+            if (part.startsWith(key)) {
+                return part.substring(key.length() + 1).replaceAll("(^\")|(\"$)", "").trim();
+            }
+        }
+
+        return null;
+    }
+
+    public interface IMultipartParserListener {
+        void onResponseBody(DcsResponseBody responseBody);
+
+        void onAudioData(AudioData audioData);
+
+        void onParseFailed(String unParseMessage);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/Parser.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.JsonProcessingException;
+
+import java.io.IOException;
+
+/**
+ * 字节数据转换成对象
+ * <p>
+ * Created by wuruisheng on 2017/5/12.
+ */
+public class Parser {
+    protected <T> T parse(byte[] bytes, Class<T> clazz) throws IOException {
+        try {
+            return ObjectMapperUtil.instance().getObjectReader().withType(clazz).readValue(bytes);
+        } catch (JsonProcessingException e) {
+            String unparsedContent = new String(bytes, "UTF-8");
+            String message = String.format("failed to parse %1$s", clazz.getSimpleName());
+            throw new DcsJsonProcessingException(message, e, unparsedContent);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithDialogIdBlockThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants;
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 服务器返回的指令header中有dialogRequestId调度线程
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/12.
+ */
+public class WithDialogIdBlockThread extends BaseBlockResponseThread {
+
+    public WithDialogIdBlockThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+                                   DcsResponseDispatcher.IDcsResponseHandler responseHandler,
+                                   String threadName) {
+        super(responseBodyDeque, responseHandler, threadName);
+    }
+
+    @Override
+    boolean shouldBlock(DcsResponseBody responseBody) {
+        // 如果是speak指令就立马阻塞
+        String directiveName = responseBody.getDirective().getName();
+        return directiveName != null && directiveName.length() > 0
+                && directiveName.equals(ApiConstants.Directives.Speak.NAME);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/WithoutDialogIdBlockThread.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.dispatcher;
+
+import com.baidu.duer.dcs.framework.DcsResponseDispatcher;
+import com.baidu.duer.dcs.framework.message.DcsResponseBody;
+
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * 服务器返回的指令header中没有dialogRequestId调度线程
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/12.
+ */
+public class WithoutDialogIdBlockThread extends BaseBlockResponseThread {
+    public WithoutDialogIdBlockThread(BlockingQueue<DcsResponseBody> responseBodyDeque,
+                                      DcsResponseDispatcher.IDcsResponseHandler responseHandler,
+                                      String threadName) {
+        super(responseBodyDeque, responseHandler, threadName);
+    }
+
+    @Override
+    boolean shouldBlock(DcsResponseBody responseBody) {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/heartbeat/HeartBeat.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.heartbeat;
+
+import com.baidu.duer.dcs.http.HttpConfig;
+import com.baidu.duer.dcs.http.HttpRequestInterface;
+import com.baidu.duer.dcs.http.callback.ResponseCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * 用于检测Directives 是否正常
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/17.
+ */
+public class HeartBeat {
+    private static final String TAG = HeartBeat.class.getSimpleName();
+    // 设置ping成功后的(ping成功即代表directive请求成功了)请求的时间间隔
+    // 修改成270s原因:国内网关保持一个连接时间一般都是300s
+    private static final long PING_TIME_SUCCEED = 30 * 1000;
+    // 设置ping失败后的(ping失败即代表directive请求失败了)请求的时间间隔
+    private static final long PING_TIME_FAILED = 5 * 1000;
+    private final HttpRequestInterface httpRequest;
+    private Timer timer;
+    private PingTask pingTask;
+    private IHeartbeatListener listener;
+    // 连接状态
+    private ConnectState connectState;
+
+    private enum ConnectState {
+        CONNECTED,
+        UNCONNECTED
+    }
+
+    public HeartBeat(HttpRequestInterface httpRequest) {
+        this.httpRequest = httpRequest;
+        timer = new Timer();
+    }
+
+    /**
+     * 如果Directives连接成功了,调用此方法进行探测
+     */
+    public void startNormalPing() {
+        connectState = ConnectState.CONNECTED;
+        startPing(PING_TIME_SUCCEED, PING_TIME_SUCCEED);
+    }
+
+    /**
+     * 如果Directives连接异常了,调用此方法进行探测
+     */
+    public void startExceptionalPing() {
+        connectState = ConnectState.UNCONNECTED;
+        startPing(PING_TIME_FAILED, PING_TIME_FAILED);
+    }
+
+    /**
+     * 如果Events连接异常了,调用此方法进行探测
+     */
+    public void startImmediatePing() {
+        connectState = ConnectState.UNCONNECTED;
+        startPing(0, PING_TIME_FAILED);
+    }
+
+    private void fireOnConnect() {
+        if (listener != null) {
+            listener.onStartConnect();
+        }
+    }
+
+    private void startPing(long delay, long timeInterval) {
+        if (pingTask != null) {
+            pingTask.cancel();
+        }
+        pingTask = new PingTask();
+        if (timer != null) {
+            timer.schedule(pingTask, delay, timeInterval);
+        }
+    }
+
+    /**
+     * 停止ping探测,释放资源
+     */
+    public void release() {
+        if (pingTask != null) {
+            pingTask.cancel();
+            pingTask = null;
+        }
+
+        timer.cancel();
+        timer = null;
+        httpRequest.cancelRequest(HttpConfig.HTTP_PING_TAG);
+    }
+
+    private void ping() {
+        httpRequest.cancelRequest(HttpConfig.HTTP_PING_TAG);
+        httpRequest.doGetPingAsync(null, new ResponseCallback() {
+            @Override
+            public void onError(Call call, Exception e, int id) {
+                super.onError(call, e, id);
+                LogUtil.d(TAG, "ping onError");
+                connectState = ConnectState.UNCONNECTED;
+                fireOnConnect();
+            }
+
+            @Override
+            public void onResponse(Response response, int id) {
+                super.onResponse(response, id);
+                LogUtil.d(TAG, "ping onResponse, code :" + response.code());
+                if (response.code() == 200 || response.code() == 204) {
+                    if (connectState == ConnectState.UNCONNECTED) {
+                        fireOnConnect();
+                    }
+                } else {
+                    connectState = ConnectState.UNCONNECTED;
+                    fireOnConnect();
+                }
+            }
+        });
+    }
+
+    public void setHeartbeatListener(IHeartbeatListener listener) {
+        this.listener = listener;
+    }
+
+    /**
+     * ping 回调接口
+     */
+    public interface IHeartbeatListener {
+        /**
+         * 需要建立长连接时回调
+         */
+        void onStartConnect();
+    }
+
+    private final class PingTask extends TimerTask {
+        @Override
+        public void run() {
+            ping();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/AttachedContentPayload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 语音输出speak指令附加内容
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public interface AttachedContentPayload {
+    boolean requiresAttachedContent();
+    boolean hasAttachedContent();
+    String getAttachedContentId();
+    byte[] getAttachedContent();
+    void setAttachedContent(String contentId, byte[] attachmentContent);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/BaseMessage.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 带有header和payload的消息体基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/1.
+ */
+public class BaseMessage {
+    private Header header;
+    private Payload payload;
+
+    public BaseMessage(Header header, Payload payload) {
+        this.header = header;
+        this.payload = payload;
+    }
+
+    public void setHeader(Header header) {
+        this.header = header;
+    }
+
+    public Header getHeader() {
+        return header;
+    }
+
+    public void setPayload(Payload payload) {
+        this.payload = payload;
+    }
+
+    public Payload getPayload() {
+        return payload;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/ClientContext.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 端状态:服务端在处理某些事件时,需要了解在请求当时设备端各模块所处的状态。比如端上是否正在播放音乐,
+ * 是否有闹钟在响,是否正在播报等等
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class ClientContext extends BaseMessage {
+    public ClientContext(Header header, Payload payload) {
+        super(header, payload);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsRequestBody.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.util.ArrayList;
+
+/**
+ * 网络请求的消息体
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public class DcsRequestBody {
+    private ArrayList<ClientContext> clientContext;
+    private Event event;
+
+    public DcsRequestBody(Event event) {
+        this.event = event;
+    }
+
+    public void setClientContext(ArrayList<ClientContext> clientContexts) {
+        this.clientContext = clientContexts;
+    }
+
+    public ArrayList<ClientContext> getClientContext() {
+        return clientContext;
+    }
+
+    public void setEvent(Event event) {
+        this.event = event;
+    }
+
+    public Event getEvent() {
+        return event;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsResponseBody.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 服务器端返回应答
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsResponseBody {
+    // 指令
+    private Directive directive;
+
+    public Directive getDirective() {
+        return directive;
+    }
+
+    public void setDirective(Directive directive) {
+        this.directive = directive;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DcsStreamRequestBody.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.http.OkHttpMediaType;
+
+import java.io.IOException;
+
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+import okio.BufferedSink;
+import okio.Okio;
+import okio.Pipe;
+
+/**
+ * 流请求消息体
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class DcsStreamRequestBody extends RequestBody {
+    private final Pipe pipe = new Pipe(8192);
+    private final BufferedSink mSink = Okio.buffer(pipe.sink());
+
+    public BufferedSink sink() {
+        return mSink;
+    }
+
+    @Override
+    public MediaType contentType() {
+        return OkHttpMediaType.MEDIA_STREAM_TYPE;
+    }
+
+    @Override
+    public void writeTo(BufferedSink bufferedSink) throws IOException {
+        bufferedSink.writeAll(pipe.source());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/DialogRequestIdHeader.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 带请求会话Id头部
+ * <p>
+ * Created by wuruisheng@baidu.com on 2017/5/31.
+ */
+public class DialogRequestIdHeader extends MessageIdHeader {
+    // 请求会话id
+    private String dialogRequestId;
+
+    public DialogRequestIdHeader() {
+
+    }
+
+    public DialogRequestIdHeader(String nameSpace, String name, String dialogRequestId) {
+        super(nameSpace, name);
+        this.dialogRequestId = dialogRequestId;
+    }
+
+    public final String getDialogRequestId() {
+        return dialogRequestId;
+    }
+
+    public final void setDialogRequestId(String dialogRequestId) {
+        this.dialogRequestId = dialogRequestId;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%1$s dialogRequestId:%2$s", super.toString(), dialogRequestId);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Directive.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.map.DeserializationContext;
+import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.annotate.JsonDeserialize;
+import org.codehaus.jackson.node.ObjectNode;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 指令类:服务端下发给设备端去执行
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+@JsonDeserialize(using = Directive.DirectiveDeserializer.class)
+public class Directive {
+    public Header header;
+    public Payload payload;
+
+    @JsonIgnore
+    public String rawMessage;
+
+
+    public Directive(Header header, JsonNode payload, String rawMessage) throws IOException {
+        this.header = header;
+        String namespace = header.getNamespace();
+        String name = header.getName();
+        Class<?> payloadType = PayloadConfig.getInstance().findPayloadClass(namespace, name);
+        if (null != payloadType) {
+            this.payload = ObjectMapperUtil.instance().getObjectReader().withType(payloadType).readValue(payload);
+        } else {
+            this.payload = new Payload();
+        }
+
+        this.rawMessage = rawMessage;
+    }
+
+    /**
+     * jackson反序列化directive对象
+     */
+    public static class DirectiveDeserializer extends JsonDeserializer<Directive> {
+        @Override
+        public Directive deserialize(JsonParser jp, DeserializationContext ctx)
+                throws IOException {
+            ObjectReader reader = ObjectMapperUtil.instance().getObjectReader();
+            ObjectNode obj = (ObjectNode) reader.readTree(jp);
+            Iterator<Map.Entry<String, JsonNode>> elementsIterator = obj.getFields();
+
+            String rawMessage = obj.toString();
+            DialogRequestIdHeader header = null;
+            JsonNode payloadNode = null;
+            ObjectReader headerReader =
+                    ObjectMapperUtil.instance().getObjectReader(DialogRequestIdHeader.class);
+            while (elementsIterator.hasNext()) {
+                Map.Entry<String, JsonNode> element = elementsIterator.next();
+                if (element.getKey().equals("header")) {
+                    header = headerReader.readValue(element.getValue());
+                }
+                if (element.getKey().equals("payload")) {
+                    payloadNode = element.getValue();
+                }
+            }
+            if (header == null) {
+                throw ctx.mappingException("Missing header");
+            }
+            if (payloadNode == null) {
+                throw ctx.mappingException("Missing payload");
+            }
+
+            return createDirective(header, payloadNode, rawMessage);
+        }
+
+        private Directive createDirective(Header header, JsonNode payload, String rawMessage)
+                throws JsonParseException, JsonMappingException, IOException {
+            return new Directive(header, payload, rawMessage);
+        }
+    }
+
+    @JsonIgnore
+    public String getName() {
+        return header.getName();
+    }
+
+    public Payload getPayload() {
+        return payload;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Event.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * 事件:设备端上发生任何事情,需要通过事件来通知服务端
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class Event extends BaseMessage {
+    public Event(Header header, Payload payload) {
+        super(header, payload);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Header.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * header类
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class Header {
+    private String namespace;
+    private String name;
+
+    public Header() {
+    }
+
+    public Header(String namespace, String name) {
+        setNamespace(namespace);
+        setName(name);
+    }
+
+    public final void setNamespace(String namespace) {
+        if (namespace == null) {
+            throw new IllegalArgumentException("Header namespace must not be null");
+        }
+        this.namespace = namespace;
+    }
+
+    public final void setName(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Header name must not be null");
+        }
+        this.name = name;
+    }
+
+    public final String getNamespace() {
+        return namespace;
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    @Override
+    public String toString() {
+        return "Header{"
+                + "namespace='"
+                + namespace
+                + '\''
+                + ", name='"
+                + name
+                + '\''
+                + '}';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/MessageIdHeader.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+import java.util.UUID;
+
+/**
+ * 带有MessageId的Header
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class MessageIdHeader extends Header {
+    private String messageId;
+
+    public MessageIdHeader() {
+        super();
+    }
+
+    public MessageIdHeader(String nameSpace, String name) {
+        super(nameSpace, name);
+
+        messageId = UUID.randomUUID().toString();
+    }
+
+    public final void setMessageId(String messageId) {
+        this.messageId = messageId;
+    }
+
+    public final String getMessageId() {
+        return messageId;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%1$s id:%2$s", super.toString(), messageId);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/Payload.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+/**
+ * Payload基类
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public class Payload {
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/message/PayloadConfig.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.framework.message;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.DeleteAlertPayload;
+import com.baidu.duer.dcs.devicemodule.alerts.message.SetAlertPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.ClearQueuePayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.PlayPayload;
+import com.baidu.duer.dcs.devicemodule.audioplayer.message.StopPayload;
+import com.baidu.duer.dcs.devicemodule.screen.message.HtmlPayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.AdjustVolumePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetMutePayload;
+import com.baidu.duer.dcs.devicemodule.speakcontroller.message.SetVolumePayload;
+import com.baidu.duer.dcs.devicemodule.system.message.SetEndPointPayload;
+import com.baidu.duer.dcs.devicemodule.system.message.ThrowExceptionPayload;
+import com.baidu.duer.dcs.devicemodule.voiceinput.message.ListenPayload;
+import com.baidu.duer.dcs.devicemodule.voiceoutput.message.SpeakPayload;
+
+import java.util.HashMap;
+
+/**
+ * 利用namespace和name做为key存储不同payload子类class并且find
+ * <p>
+ * Created by wuruisheng on 2017/6/1.
+ */
+public class PayloadConfig {
+    private final HashMap<String, Class<?>> payloadClass;
+
+    private static class PayloadConfigHolder {
+        private static final PayloadConfig instance = new PayloadConfig();
+    }
+
+    public static PayloadConfig getInstance() {
+        return PayloadConfigHolder.instance;
+    }
+
+    private PayloadConfig() {
+        payloadClass = new HashMap<>();
+
+        // AudioInputImpl
+        String namespace = com.baidu.duer.dcs.devicemodule.voiceinput.ApiConstants.NAMESPACE;
+        String name = com.baidu.duer.dcs.devicemodule.voiceinput.ApiConstants.Directives.Listen.NAME;
+        insertPayload(namespace, name, ListenPayload.class);
+
+        // VoiceOutput
+        namespace = com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.voiceoutput.ApiConstants.Directives.Speak.NAME;
+        insertPayload(namespace, name, SpeakPayload.class);
+
+        // audio
+        namespace = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.Play.NAME;
+        insertPayload(namespace, name, PlayPayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.Stop.NAME;
+        insertPayload(namespace, name, StopPayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.audioplayer.ApiConstants.Directives.ClearQueue.NAME;
+        insertPayload(namespace, name, ClearQueuePayload.class);
+
+        //  alert
+        namespace = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.Directives.SetAlert.NAME;
+        insertPayload(namespace, name, SetAlertPayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.alerts.ApiConstants.Directives.DeleteAlert.NAME;
+        insertPayload(namespace, name, DeleteAlertPayload.class);
+
+        // SpeakController
+        namespace = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.SetVolume.NAME;
+        insertPayload(namespace, name, SetVolumePayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.AdjustVolume.NAME;
+        insertPayload(namespace, name, AdjustVolumePayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.speakcontroller.ApiConstants.Directives.SetMute.NAME;
+        insertPayload(namespace, name, SetMutePayload.class);
+
+        // System
+        namespace = com.baidu.duer.dcs.devicemodule.system.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.system.ApiConstants.Directives.SetEndpoint.NAME;
+        insertPayload(namespace, name, SetEndPointPayload.class);
+
+        name = com.baidu.duer.dcs.devicemodule.system.ApiConstants.Directives.ThrowException.NAME;
+        insertPayload(namespace, name, ThrowExceptionPayload.class);
+
+        // Screen
+        namespace = com.baidu.duer.dcs.devicemodule.screen.ApiConstants.NAMESPACE;
+        name = com.baidu.duer.dcs.devicemodule.screen.ApiConstants.Directives.HtmlView.NAME;
+        insertPayload(namespace, name, HtmlPayload.class);
+    }
+
+    void insertPayload(String namespace, String name, Class<?> type) {
+        final String key = namespace + name;
+        payloadClass.put(key, type);
+    }
+
+    Class<?> findPayloadClass(String namespace, String name) {
+        final String key = namespace + name;
+        return payloadClass.get(key);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/DcsHttpManager.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.http.builder.GetBuilder;
+import com.baidu.duer.dcs.http.builder.PostMultipartBuilder;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.http.intercepter.LoggingInterceptor;
+import com.baidu.duer.dcs.http.request.RequestCall;
+import com.baidu.duer.dcs.http.utils.Platform;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+
+/**
+ * 网络请求-单例
+ * <p>
+ * Created by zhangyan@baidu.com on 2017/5/15.
+ */
+public class DcsHttpManager {
+    // 默认时间,比如超时时间
+    public static final long DEFAULT_MILLISECONDS = 60 * 1000L;
+    private OkHttpClient mOkHttpClient;
+    private Platform mPlatform;
+
+    private static class DcsHttpManagerHolder {
+        private static final DcsHttpManager INSTANCE = new DcsHttpManager();
+    }
+
+    public static DcsHttpManager getInstance() {
+        return DcsHttpManagerHolder.INSTANCE;
+    }
+
+    private DcsHttpManager() {
+        if (mOkHttpClient == null) {
+            // http数据log,日志中打印出HTTP请求&响应数据
+            // HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
+            // 包含header、body数据
+            mOkHttpClient = new OkHttpClient.Builder()
+                    .retryOnConnectionFailure(false)
+                    .readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+                    .writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+                    .connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS)
+                    // .addInterceptor(new RetryInterceptor(3))
+                    .addInterceptor(new LoggingInterceptor())
+                    // .connectionPool(new ConnectionPool(0, 1, TimeUnit.NANOSECONDS))
+                    .build();
+        }
+        mPlatform = Platform.get();
+    }
+
+    public OkHttpClient getOkHttpClient() {
+        return mOkHttpClient;
+    }
+
+    public static GetBuilder get() {
+        return new GetBuilder();
+    }
+
+    public static PostMultipartBuilder post() {
+        return new PostMultipartBuilder();
+    }
+
+    public void execute(final RequestCall requestCall, DcsCallback dcsCallback) {
+
+        if (dcsCallback == null) {
+            dcsCallback = DcsCallback.backDefaultCallBack;
+        }
+        final DcsCallback finalDCSCallback = dcsCallback;
+        final int id = requestCall.getOkHttpRequest().getId();
+
+        requestCall.getCall().enqueue(new okhttp3.Callback() {
+            @Override
+            public void onFailure(Call call, final IOException e) {
+                sendFailResultCallback(call, e, finalDCSCallback, id);
+            }
+
+            @Override
+            public void onResponse(final Call call, final Response response) {
+                try {
+                    if (call.isCanceled()) {
+                        sendFailResultCallback(call, new IOException("Canceled!"), finalDCSCallback, id);
+                        return;
+                    }
+                    if (!finalDCSCallback.validateResponse(response, id)) {
+                        IOException exception = new IOException("request failed , response's code is : "
+                                + response.code());
+                        sendFailResultCallback(call, exception, finalDCSCallback, id);
+                        return;
+                    }
+                    sendSuccessResultCallback(response, finalDCSCallback, id);
+                    Object o = finalDCSCallback.parseNetworkResponse(response, id);
+                } catch (Exception e) {
+                    sendFailResultCallback(call, e, finalDCSCallback, id);
+                } finally {
+                    if (response.body() != null) {
+                        response.body().close();
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * 网络请求失败处理
+     *
+     * @param call        okhttp的请求call
+     * @param e           异常信息
+     * @param dcsCallback 回调
+     * @param id          请求标识
+     */
+    private void sendFailResultCallback(final Call call,
+                                        final Exception e,
+                                        final DcsCallback dcsCallback,
+                                        final int id) {
+        if (dcsCallback == null) {
+            return;
+        }
+        mPlatform.execute(new Runnable() {
+            @Override
+            public void run() {
+                dcsCallback.onError(call, e, id);
+                dcsCallback.onAfter(id);
+            }
+        });
+    }
+
+    /**
+     * 网络请求成功处理
+     *
+     * @param object      object 返回的对象
+     * @param dcsCallback dcsCallback 回调
+     * @param id          id 请求标识
+     */
+    private void sendSuccessResultCallback(final Object object,
+                                           final DcsCallback dcsCallback,
+                                           final int id) {
+        if (dcsCallback == null) {
+            return;
+        }
+        mPlatform.execute(new Runnable() {
+            @Override
+            public void run() {
+                dcsCallback.onResponse(object, id);
+                dcsCallback.onAfter(id);
+            }
+        });
+    }
+
+    /**
+     * 取消请求
+     *
+     * @param tag 请求的时候设置的tag
+     */
+    public void cancelTag(Object tag) {
+        for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
+            if (tag.equals(call.request().tag())) {
+                call.cancel();
+            }
+        }
+        for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
+            if (tag.equals(call.request().tag())) {
+                call.cancel();
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpConfig.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.util.CommonUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HttpConfig
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public class HttpConfig {
+    // 请求https
+    public static final String HTTP_PREFIX = "https://";
+    // 请求host
+    public static final String HOST = "dueros-h2.baidu.com";
+    public static String endpoint = null;
+    // 请求event事件
+    public static final String EVENTS = "/dcs/v1/events";
+    // 请求directives事件
+    public static final String DIRECTIVES = "/dcs/v1/directives";
+    // ping
+    public static final String PING = "/dcs/v1/ping";
+    // 请求event事件TAG
+    public static final String HTTP_EVENT_TAG = "event";
+    // 请求directives事件TAG
+    public static final String HTTP_DIRECTIVES_TAG = "directives";
+    // 请求ping的TAG
+    public static final String HTTP_PING_TAG = "ping";
+
+    public static String getEndpoint() {
+        if (null == endpoint || "".equals(endpoint)) {
+            endpoint = HTTP_PREFIX + HOST;
+        }
+        return endpoint;
+    }
+
+    public static void setEndpoint(String endpoint) {
+        HttpConfig.endpoint = endpoint;
+    }
+
+    public static String getEventsUrl() {
+        return getEndpoint() + EVENTS;
+    }
+
+    public static String getDirectivesUrl() {
+        return getEndpoint() + DIRECTIVES;
+    }
+
+    public static String getPingUrl() {
+        return getEndpoint() + PING;
+    }
+
+    public static class HttpHeaders {
+        public static final String CONTENT_TYPE = "Content-Type";
+        public static final String DUEROS_DEVICE_ID = "dueros-device-id";
+        public static final String AUTHORIZATION = "Authorization";
+        public static final String CONTENT_ID = "Content-ID";
+        public static final String BEARER = "Bearer ";
+        public static final String DEBUG = "debug";
+        public static final String DEBUG_PARAM = "0";
+    }
+
+    public static class ContentTypes {
+        public static final String JSON = "application/json";
+        public static final String FORM_MULTIPART = "multipart/form-data boundary=dumi-boundory";
+        public static final String APPLICATION_JSON = JSON + ";" + " charset=UTF-8";
+        public static final String APPLICATION_AUDIO = "application/octet-stream";
+    }
+
+    public static class Parameters {
+        public static final String BOUNDARY = "boundary";
+        public static final String DATA_METADATA = "metadata";
+        public static final String DATA_AUDIO = "audio";
+    }
+
+    public static String accessToken = "";
+
+    public static String getAccessToken() {
+        return accessToken;
+    }
+
+    public static void setAccessToken(String accessToken) {
+        HttpConfig.accessToken = accessToken;
+    }
+
+    /**
+     * 获取dcs的headers
+     *
+     * @return header集合
+     */
+    public static Map<String, String> getDCSHeaders() {
+        Map<String, String> headers = new HashMap<>();
+        headers.put(HttpConfig.HttpHeaders.AUTHORIZATION,
+                HttpConfig.HttpHeaders.BEARER + getAccessToken());
+        headers.put(HttpConfig.HttpHeaders.CONTENT_TYPE,
+                HttpConfig.ContentTypes.FORM_MULTIPART);
+        headers.put(HttpConfig.HttpHeaders.DUEROS_DEVICE_ID,
+                CommonUtil.getDeviceUniqueID());
+        headers.put(HttpConfig.HttpHeaders.DEBUG,
+                HttpConfig.HttpHeaders.DEBUG_PARAM);
+        return headers;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/HttpRequestInterface.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+
+/**
+ * 网络请求工具接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public interface HttpRequestInterface {
+    /**
+     * 异步Post EventString请求
+     *
+     * @param requestBody 请求信息体
+     * @param dcsCallback 结果回调接口
+     */
+    void doPostEventStringAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+    /**
+     * 异步PostMultipart请求
+     *
+     * @param requestBody       请求信息体
+     * @param streamRequestBody 请求信息体stream
+     * @param dcsCallback       结果回调接口
+     */
+    void doPostEventMultipartAsync(DcsRequestBody requestBody,
+                                   DcsStreamRequestBody streamRequestBody,
+                                   DcsCallback dcsCallback);
+
+    /**
+     * 异步Get Directives请求
+     *
+     * @param requestBody 请求信息体
+     * @param dcsCallback 结果回调接口
+     */
+    void doGetDirectivesAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+    /**
+     * 异步Get Ping请求
+     *
+     * @param requestBody 请求信息体
+     * @param dcsCallback 结果回调接口
+     */
+    void doGetPingAsync(DcsRequestBody requestBody, DcsCallback dcsCallback);
+
+    /**
+     * 取消请求
+     *
+     * @param requestTag 请求标识
+     */
+    void cancelRequest(Object requestTag);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpMediaType.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http;
+
+import okhttp3.MediaType;
+
+import static com.baidu.duer.dcs.http.HttpConfig.ContentTypes.APPLICATION_AUDIO;
+import static com.baidu.duer.dcs.http.HttpConfig.ContentTypes.APPLICATION_JSON;
+
+/**
+ * okhttp media_type
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/1.
+ */
+public class OkHttpMediaType {
+    // json类型
+    public static final MediaType MEDIA_JSON_TYPE = MediaType.parse(APPLICATION_JSON);
+    // 数据流类型
+    public static final MediaType MEDIA_STREAM_TYPE = MediaType.parse(APPLICATION_AUDIO);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/OkHttpRequestImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http;
+
+import com.baidu.duer.dcs.framework.message.DcsRequestBody;
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.util.LogUtil;
+import com.baidu.duer.dcs.util.ObjectMapperUtil;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import okhttp3.RequestBody;
+
+/**
+ * 请求实现
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public class OkHttpRequestImpl implements HttpRequestInterface {
+    private static final String TAG = "OkHttpRequestImpl";
+    private final DcsHttpManager dcsHttpManager;
+
+    public OkHttpRequestImpl() {
+        dcsHttpManager = DcsHttpManager.getInstance();
+    }
+
+    @Override
+    public void doPostEventStringAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+        String bodyJson = ObjectMapperUtil.instance().objectToJson(requestBody);
+        LogUtil.d(TAG, "doPostEventStringAsync-bodyJson:" + bodyJson);
+        Map<String, RequestBody> multiParts = new LinkedHashMap<>();
+        multiParts.put(HttpConfig.Parameters.DATA_METADATA,
+                RequestBody.create(OkHttpMediaType.MEDIA_JSON_TYPE, bodyJson));
+        DcsHttpManager.post()
+                .url(HttpConfig.getEventsUrl())
+                .headers(HttpConfig.getDCSHeaders())
+                .multiParts(multiParts)
+                .tag(HttpConfig.HTTP_EVENT_TAG)
+                .build()
+                .execute(dcsCallback);
+    }
+
+    @Override
+    public void doPostEventMultipartAsync(DcsRequestBody requestBody,
+                                          DcsStreamRequestBody streamRequestBody,
+                                          DcsCallback dcsCallback) {
+        String bodyJson = ObjectMapperUtil.instance().objectToJson(requestBody);
+        LogUtil.d(TAG, "doPostEventMultipartAsync-bodyJson:" + bodyJson);
+        Map<String, RequestBody> multiParts = new LinkedHashMap<>();
+        multiParts.put(HttpConfig.Parameters.DATA_METADATA,
+                RequestBody.create(OkHttpMediaType.MEDIA_JSON_TYPE, bodyJson));
+        multiParts.put(HttpConfig.Parameters.DATA_AUDIO, streamRequestBody);
+        DcsHttpManager.post()
+                .url(HttpConfig.getEventsUrl())
+                .headers(HttpConfig.getDCSHeaders())
+                .multiParts(multiParts)
+                .tag(HttpConfig.HTTP_EVENT_TAG)
+                .build()
+                .execute(dcsCallback);
+    }
+
+    @Override
+    public void doGetDirectivesAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+        LogUtil.d(TAG, "doGetDirectivesAsync");
+        final long time = 60 * 60 * 1000L;
+        DcsHttpManager.get()
+                .url(HttpConfig.getDirectivesUrl())
+                .headers(HttpConfig.getDCSHeaders())
+                .tag(HttpConfig.HTTP_DIRECTIVES_TAG)
+                .build()
+                .connTimeOut(time)
+                .readTimeOut(time)
+                .writeTimeOut(time)
+                .execute(dcsCallback);
+    }
+
+    @Override
+    public void doGetPingAsync(DcsRequestBody requestBody, DcsCallback dcsCallback) {
+        LogUtil.d(TAG, "doGetPingAsync");
+        DcsHttpManager.get()
+                .url(HttpConfig.getPingUrl())
+                .headers(HttpConfig.getDCSHeaders())
+                .tag(HttpConfig.HTTP_PING_TAG)
+                .build()
+                .execute(dcsCallback);
+    }
+
+    @Override
+    public void cancelRequest(Object requestTag) {
+        dcsHttpManager.cancelTag(requestTag);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/GetBuilder.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.builder;
+
+import android.net.Uri;
+
+import com.baidu.duer.dcs.http.request.GetRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * get请求构建
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class GetBuilder extends OkHttpRequestBuilder<GetBuilder> implements HasParamInterface {
+    @Override
+    public RequestCall build() {
+        if (params != null) {
+            url = appendParams(url, params);
+        }
+        return new GetRequest(url, tag, params, headers, id).build();
+    }
+
+    /**
+     * 添加参数到url上
+     *
+     * @param url    url 请求的url
+     * @param params params 参数集合
+     * @return url   拼接后的url
+     */
+    protected String appendParams(String url, Map<String, String> params) {
+        if (url == null || params == null || params.isEmpty()) {
+            return url;
+        }
+        Uri.Builder builder = Uri.parse(url).buildUpon();
+        Set<String> keys = params.keySet();
+        Iterator<String> iterator = keys.iterator();
+        while (iterator.hasNext()) {
+            String key = iterator.next();
+            builder.appendQueryParameter(key, params.get(key));
+        }
+        return builder.build().toString();
+    }
+
+
+    @Override
+    public GetBuilder params(Map<String, String> params) {
+        this.params = params;
+        return this;
+    }
+
+    @Override
+    public GetBuilder addParams(String key, String val) {
+        if (this.params == null) {
+            params = new LinkedHashMap<>();
+        }
+        params.put(key, val);
+        return this;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/HasParamInterface.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.builder;
+
+import java.util.Map;
+
+/**
+ * 请求是否包含参数
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public interface HasParamInterface {
+    /**
+     * 构建请求参数
+     *
+     * @param params 请求参数
+     * @return OkHttpRequestBuilder
+     */
+    OkHttpRequestBuilder params(Map<String, String> params);
+
+    /**
+     * @param key 请求参数的key
+     * @param val 请求参数的值
+     * @return OkHttpRequestBuilder
+     */
+    OkHttpRequestBuilder addParams(String key, String val);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/OkHttpRequestBuilder.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 请求构建基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public abstract class OkHttpRequestBuilder<T extends OkHttpRequestBuilder> {
+    // 请求url
+    protected String url;
+    // 请求tag
+    protected Object tag;
+    // 请求的headers
+    protected Map<String, String> headers;
+    // 请求的参数集合
+    protected Map<String, String> params;
+    // 请求的表识id
+    protected int id;
+
+    public T id(int id) {
+        this.id = id;
+        return (T) this;
+    }
+
+    public T url(String url) {
+        this.url = url;
+        return (T) this;
+    }
+
+
+    public T tag(Object tag) {
+        this.tag = tag;
+        return (T) this;
+    }
+
+    public T headers(Map<String, String> headers) {
+        this.headers = headers;
+        return (T) this;
+    }
+
+    public T addHeader(String key, String val) {
+        if (this.headers == null) {
+            headers = new LinkedHashMap<>();
+        }
+        headers.put(key, val);
+        return (T) this;
+    }
+
+    /**
+     * 构建请求
+     *
+     * @return RequestCall
+     */
+    public abstract RequestCall build();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostMultipartBuilder.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.PostMultipartRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import okhttp3.RequestBody;
+
+/**
+ * post请求多part构建
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class PostMultipartBuilder extends OkHttpRequestBuilder<PostMultipartBuilder>
+        implements HasParamInterface {
+    private LinkedList<Multipart> multiParts = new LinkedList<>();
+
+    @Override
+    public RequestCall build() {
+        return new PostMultipartRequest(url, tag, params, headers, multiParts, id).build();
+    }
+
+    @Override
+    public PostMultipartBuilder params(Map<String, String> params) {
+        this.params = params;
+        return this;
+    }
+
+    @Override
+    public PostMultipartBuilder addParams(String key, String val) {
+        if (this.params == null) {
+            params = new LinkedHashMap<>();
+        }
+        params.put(key, val);
+        return this;
+    }
+
+    /**
+     * 添加多个Multipart
+     *
+     * @param map map集合
+     * @return 当前对象
+     */
+    public PostMultipartBuilder multiParts(Map<String, RequestBody> map) {
+        if (map != null) {
+            multiParts = new LinkedList<>();
+        }
+        for (String k : map.keySet()) {
+            this.multiParts.add(new Multipart(k, map.get(k)));
+        }
+        return this;
+    }
+
+    /**
+     * 添加一个Multipart
+     *
+     * @param name name
+     * @param body body
+     * @return 当前对象
+     */
+    public PostMultipartBuilder addMultiPart(String name, RequestBody body) {
+        multiParts.add(new Multipart(name, body));
+        return this;
+    }
+
+    /**
+     * 请求体body-Multipart
+     */
+    public static final class Multipart implements Serializable {
+        // body的key
+        public String key;
+        // body的内容
+        public RequestBody requestBody;
+
+        public Multipart(String name, RequestBody requestBody) {
+            this.key = name;
+            this.requestBody = requestBody;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/builder/PostStringBuilder.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.builder;
+
+import com.baidu.duer.dcs.http.request.PostStringRequest;
+import com.baidu.duer.dcs.http.request.RequestCall;
+
+import okhttp3.MediaType;
+
+/**
+ * post请求的构建类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class PostStringBuilder extends OkHttpRequestBuilder<PostStringBuilder> {
+    // 内容
+    private String content;
+    // 类型
+    private MediaType mediaType;
+
+    public PostStringBuilder content(String content) {
+        this.content = content;
+        return this;
+    }
+
+    public PostStringBuilder mediaType(MediaType mediaType) {
+        this.mediaType = mediaType;
+        return this;
+    }
+
+    @Override
+    public RequestCall build() {
+        return new PostStringRequest(url, tag, params, headers, content, mediaType, id).build();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/DcsCallback.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.callback;
+
+import okhttp3.Call;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * 网络回调基类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class DcsCallback<T> {
+    /**
+     * UI线程
+     *
+     * @param request 请求
+     * @param id      请求id
+     */
+    public void onBefore(Request request, int id) {
+    }
+
+    /**
+     * UI线程
+     *
+     * @param id 请求id
+     */
+    public void onAfter(int id) {
+    }
+
+    public static DcsCallback backDefaultCallBack = new DcsCallback() {
+
+        @Override
+        public Object parseNetworkResponse(Response response, int id) throws Exception {
+            return null;
+        }
+
+        @Override
+        public void onError(Call call, Exception e, int id) {
+
+        }
+
+        @Override
+        public void onResponse(Object response, int id) {
+
+        }
+    };
+
+    public boolean validateResponse(Response response, int id) {
+        return response.isSuccessful();
+    }
+
+    /**
+     * 非UI线程
+     *
+     * @param response response
+     */
+    public abstract T parseNetworkResponse(Response response, int id) throws Exception;
+
+    /**
+     * 错误处理,UI线程
+     *
+     * @param call call
+     * @param e    e  错误异常信息
+     * @param id   id 请求id
+     */
+    public abstract void onError(Call call, Exception e, int id);
+
+    /**
+     * 数据回调,UI线程
+     *
+     * @param response response
+     * @param id       id
+     */
+    public abstract void onResponse(T response, int id);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/ResponseCallback.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.callback;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import okhttp3.Call;
+import okhttp3.Response;
+
+/**
+ * framework 返回数据类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public class ResponseCallback extends DcsCallback<Response> {
+    private static final String TAG = "ResponseCallback";
+
+    @Override
+    public Response parseNetworkResponse(Response response, int id) throws Exception {
+        return response;
+    }
+
+    @Override
+    public void onError(Call call, Exception e, int id) {
+        LogUtil.d(TAG, "onError:" + e.getMessage());
+    }
+
+    @Override
+    public void onResponse(Response response, int id) {
+        LogUtil.d(TAG, "onResponse:" + response.code());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StreamDcsCallback.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.callback;
+
+import java.io.InputStream;
+
+import okhttp3.Response;
+
+/**
+ * 数据流回调
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class StreamDcsCallback extends DcsCallback<InputStream> {
+    @Override
+    public InputStream parseNetworkResponse(Response response, int id) throws Exception {
+        return response.body().byteStream();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/callback/StringDcsCallback.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.callback;
+
+import okhttp3.Response;
+
+/**
+ * String类型回调
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/2.
+ */
+public abstract class StringDcsCallback extends DcsCallback<String> {
+    @Override
+    public String parseNetworkResponse(Response response, int id) throws Exception {
+        return response.body().string();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/exceptions/Exceptions.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.exceptions;
+
+/**
+ * 网络模块的异常处理,比如参数检查
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class Exceptions {
+    public static void illegalArgument(String msg, Object... params) {
+        throw new IllegalArgumentException(String.format(msg, params));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/LoggingInterceptor.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.intercepter;
+
+import com.baidu.duer.dcs.util.LogUtil;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * http Interceptor 拦截打印http-log
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/25.
+ */
+public class LoggingInterceptor implements Interceptor {
+    private static final String TAG = "HttpLog";
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        long t1 = System.nanoTime();
+        LogUtil.d(TAG, String.format("request: %s [%s] %s%n%s",
+                request.method(), request.url(), chain.connection(), request.headers()));
+
+        Response response = chain.proceed(request);
+        long t2 = System.nanoTime();
+        LogUtil.d(TAG, String.format(Locale.CANADA, "response: %d [%s] %.1fms%n%s",
+                response.code(), response.request().url(), (t2 - t1) / 1e6d, response.headers()));
+        return response;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/intercepter/RetryInterceptor.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.intercepter;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+/**
+ * 重试拦截器
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/20.
+ */
+public class RetryInterceptor implements Interceptor {
+    // 最大重试次数,假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试)
+    private int maxRetry;
+    private int retryNum = 0;
+
+    public RetryInterceptor(int maxRetry) {
+        this.maxRetry = maxRetry;
+    }
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        Response response = chain.proceed(request);
+        while (!response.isSuccessful() && retryNum < maxRetry) {
+            retryNum++;
+            response = chain.proceed(request);
+        }
+        return response;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/GetRequest.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.request;
+
+import java.util.Map;
+
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 普通GetRequest
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class GetRequest extends OkHttpRequest {
+    public GetRequest(String url,
+                      Object tag,
+                      Map<String, String> params,
+                      Map<String, String> headers,
+                      int id) {
+        super(url, tag, params, headers, id);
+    }
+
+    @Override
+    protected RequestBody buildRequestBody() {
+        return null;
+    }
+
+    @Override
+    protected Request buildRequest(RequestBody requestBody) {
+        return builder.get().build();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/OkHttpRequest.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+import com.baidu.duer.dcs.http.exceptions.Exceptions;
+
+import java.util.Map;
+
+import okhttp3.Headers;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 请求基类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public abstract class OkHttpRequest {
+    // url
+    protected String url;
+    // 用于取消请求的tag
+    protected Object tag;
+    // 请求参数
+    protected Map<String, String> params;
+    // 请求header
+    protected Map<String, String> headers;
+    // 请求的标识id
+    protected int id;
+    // okhttp的请求构建类
+    protected Request.Builder builder = new Request.Builder();
+
+    protected OkHttpRequest(String url, Object tag,
+                            Map<String, String> params,
+                            Map<String, String> headers,
+                            int id) {
+        this.url = url;
+        this.tag = tag;
+        this.params = params;
+        this.headers = headers;
+        this.id = id;
+        if (url == null) {
+            Exceptions.illegalArgument("url can not be null.");
+        }
+        initBuilder();
+    }
+
+    /**
+     * 初始化okhttp的请求builder
+     */
+    private void initBuilder() {
+        builder.url(url).tag(tag);
+        appendHeaders();
+    }
+
+    /**
+     * 拼接请求的Header
+     */
+    protected void appendHeaders() {
+        Headers.Builder headerBuilder = new Headers.Builder();
+        if (headers == null || headers.isEmpty()) {
+            return;
+        }
+        for (String key : headers.keySet()) {
+            headerBuilder.add(key, headers.get(key));
+        }
+        builder.headers(headerBuilder.build());
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public RequestCall build() {
+        return new RequestCall(this);
+    }
+
+    public Request generateRequest(DcsCallback dcsCallback) {
+        RequestBody requestBody = buildRequestBody();
+        RequestBody wrappedRequestBody = wrapRequestBody(requestBody, dcsCallback);
+        Request request = buildRequest(wrappedRequestBody);
+        return request;
+    }
+
+    protected RequestBody wrapRequestBody(RequestBody requestBody, final DcsCallback dcsCallback) {
+        return requestBody;
+    }
+
+    protected abstract RequestBody buildRequestBody();
+
+    protected abstract Request buildRequest(RequestBody requestBody);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostMultipartRequest.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.builder.PostMultipartBuilder;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import okhttp3.Headers;
+import okhttp3.MultipartBody;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 用于post multipart请求
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class PostMultipartRequest extends OkHttpRequest {
+    private List<PostMultipartBuilder.Multipart> multiParts;
+
+    public PostMultipartRequest(String url,
+                                Object tag,
+                                Map<String, String> params,
+                                Map<String, String> headers,
+                                LinkedList<PostMultipartBuilder.Multipart> multiParts,
+                                int id) {
+        super(url, tag, params, headers, id);
+        this.multiParts = multiParts;
+    }
+
+    @Override
+    protected RequestBody buildRequestBody() {
+        MultipartBody.Builder builder = new MultipartBody.Builder()
+                .setType(MultipartBody.FORM);
+        addParams(builder);
+        return builder.build();
+    }
+
+    @Override
+    protected Request buildRequest(RequestBody requestBody) {
+        return builder.post(requestBody).build();
+    }
+
+    private void addParams(MultipartBody.Builder builder) {
+        if (multiParts != null && !multiParts.isEmpty()) {
+            for (int i = 0; i < multiParts.size(); i++) {
+                PostMultipartBuilder.Multipart part = multiParts.get(i);
+                builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + part.key + "\""),
+                        part.requestBody);
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/PostStringRequest.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.exceptions.Exceptions;
+
+import java.util.Map;
+
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+
+/**
+ * 用于发送字符串请求
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/16.
+ */
+public class PostStringRequest extends OkHttpRequest {
+    private static MediaType MEDIA_TYPE_PLAIN = MediaType.parse("text/plain;charset=utf-8");
+    private String content;
+    private MediaType mediaType;
+
+    public PostStringRequest(String url,
+                             Object tag,
+                             Map<String, String> params,
+                             Map<String, String> headers,
+                             String content,
+                             MediaType mediaType,
+                             int id) {
+        super(url, tag, params, headers, id);
+        this.content = content;
+        this.mediaType = mediaType;
+        if (this.content == null) {
+            Exceptions.illegalArgument("the content can not be null !");
+        }
+        if (this.mediaType == null) {
+            this.mediaType = MEDIA_TYPE_PLAIN;
+        }
+    }
+
+    @Override
+    protected RequestBody buildRequestBody() {
+        return RequestBody.create(mediaType, content);
+    }
+
+    @Override
+    protected Request buildRequest(RequestBody requestBody) {
+        return builder.post(requestBody).build();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/request/RequestCall.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.request;
+
+import com.baidu.duer.dcs.http.DcsHttpManager;
+import com.baidu.duer.dcs.http.callback.DcsCallback;
+
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+/**
+ * 请求设置
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class RequestCall {
+    private OkHttpRequest okHttpRequest;
+    private Request request;
+    private Call call;
+    private OkHttpClient clone;
+    // 读取超时时间
+    private long readTimeOut;
+    // 写入数据超时时间
+    private long writeTimeOut;
+    // 连接超时时间
+    private long connTimeOut;
+
+    public RequestCall(OkHttpRequest request) {
+        this.okHttpRequest = request;
+    }
+
+    public RequestCall readTimeOut(long readTimeOut) {
+        this.readTimeOut = readTimeOut;
+        return this;
+    }
+
+    public RequestCall writeTimeOut(long writeTimeOut) {
+        this.writeTimeOut = writeTimeOut;
+        return this;
+    }
+
+    public RequestCall connTimeOut(long connTimeOut) {
+        this.connTimeOut = connTimeOut;
+        return this;
+    }
+
+    /**
+     * 构建请求
+     *
+     * @param dcsCallback 回调
+     * @return Call
+     */
+    public Call buildCall(DcsCallback dcsCallback) {
+        request = generateRequest(dcsCallback);
+        if (readTimeOut > 0 || writeTimeOut > 0 || connTimeOut > 0) {
+            readTimeOut = readTimeOut > 0 ? readTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+            writeTimeOut = writeTimeOut > 0 ? writeTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+            connTimeOut = connTimeOut > 0 ? connTimeOut : DcsHttpManager.DEFAULT_MILLISECONDS;
+            clone = DcsHttpManager.getInstance().getOkHttpClient().newBuilder()
+                    .readTimeout(readTimeOut, TimeUnit.MILLISECONDS)
+                    .writeTimeout(writeTimeOut, TimeUnit.MILLISECONDS)
+                    .connectTimeout(connTimeOut, TimeUnit.MILLISECONDS)
+                    .build();
+
+            call = clone.newCall(request);
+        } else {
+            call = DcsHttpManager.getInstance().getOkHttpClient().newCall(request);
+        }
+        return call;
+    }
+
+    private Request generateRequest(DcsCallback dcsCallback) {
+        return okHttpRequest.generateRequest(dcsCallback);
+    }
+
+    public void execute(DcsCallback dcsCallback) {
+        buildCall(dcsCallback);
+        if (dcsCallback != null) {
+            dcsCallback.onBefore(request, getOkHttpRequest().getId());
+        }
+        DcsHttpManager.getInstance().execute(this, dcsCallback);
+    }
+
+    public OkHttpRequest getOkHttpRequest() {
+        return okHttpRequest;
+    }
+
+    public Call getCall() {
+        return call;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/http/utils/Platform.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.http.utils;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * 请求回调处理类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/15.
+ */
+public class Platform {
+    private static final Platform PLATFORM = findPlatform();
+
+    public static Platform get() {
+        return PLATFORM;
+    }
+
+    private static Platform findPlatform() {
+        return new Android();
+    }
+
+    public Executor defaultCallbackExecutor() {
+        return Executors.newCachedThreadPool();
+    }
+
+    public void execute(Runnable runnable) {
+        defaultCallbackExecutor().execute(runnable);
+    }
+
+    /**
+     * android 平台下用于回调到UI线程的辅助类
+     */
+    private static final class Android extends Platform {
+        @Override
+        public Executor defaultCallbackExecutor() {
+            return new MainThreadExecutor();
+        }
+
+        static class MainThreadExecutor implements Executor {
+            private final Handler handler = new Handler(Looper.getMainLooper());
+
+            @Override
+            public void execute(Runnable r) {
+                handler.post(r);
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/AccessTokenManager.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import static com.baidu.duer.dcs.oauth.api.OauthPreferenceUtil.BAIDU_OAUTH_CONFIG;
+
+/**
+ * 对Token相关信息的管理类,包括初始化、存储、清除相应的token信息
+ * 由于AccessTokenManager涉及到在多个Activity中传递的,所以实现了Parcelable接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class AccessTokenManager implements Parcelable {
+    // accessToken信息
+    private String accessToken;
+    // token过期时间
+    private long expireTime = 0;
+    // 当前的上下文环境
+    private Context context;
+
+    /**
+     * 构建AccessTokenManager类
+     *
+     * @param context 当前的上下文环境,通常为××Activity.this等
+     */
+    public AccessTokenManager(Context context) {
+        this.context = context;
+        compareWithConfig();
+    }
+
+    /**
+     * 通过Parcel流构建AccessTokenManager,主要用在Parcelable.Creator中
+     *
+     * @param source Parcel 流信息
+     */
+    public AccessTokenManager(Parcel source) {
+        Bundle bundle = Bundle.CREATOR.createFromParcel(source);
+        if (bundle != null) {
+            this.accessToken = bundle.getString(OauthConfig.BundleKey.KEY_ACCESS_TOKEN);
+            this.expireTime = bundle.getLong(OauthConfig.BundleKey.KEY_EXPIRE_TIME);
+        }
+        compareWithConfig();
+    }
+
+    /**
+     * 检查当token信息与配置文件是否保持一致,若不一致则对当前的token信息进行初始化
+     */
+    private void compareWithConfig() {
+        if (this.context == null) {
+            return;
+        }
+
+        /**
+         * 对配置的权限信息进行监控,保持多个AccessTokenManager对象之间的,权限信息一致。
+         */
+        final SharedPreferences sp = this.context.getSharedPreferences(BAIDU_OAUTH_CONFIG, Context.MODE_PRIVATE);
+        sp.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
+
+            @Override
+            public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+                String acToken = sp.getString(OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, null);
+                if (accessToken != null && !accessToken.equals(acToken)) {
+                    initToken();
+                }
+            }
+        });
+    }
+
+    /**
+     * 从SharedPreference中读取token数据,并初步判断数据的有效性
+     */
+    protected void initToken() {
+        this.accessToken = OauthPreferenceUtil.getAccessToken(context);
+        long expires = OauthPreferenceUtil.getExpires(context);
+        long createTime = OauthPreferenceUtil.getCreateTime(context);
+        long current = System.currentTimeMillis();
+        this.expireTime = createTime + expires;
+        if (expireTime != 0 && expireTime < current) {
+            clearToken();
+        }
+    }
+
+    /**
+     * 清楚SharedPreference中的所有数据
+     */
+    protected void clearToken() {
+        OauthPreferenceUtil.clearAllOauth(context);
+        this.accessToken = null;
+        this.expireTime = 0;
+    }
+
+    /**
+     * 将token信息存储到SharedPreference中
+     *
+     * @param values token信息的key-value形式
+     */
+    protected void storeToken(Bundle values) {
+        if (values == null || values.isEmpty()) {
+            return;
+        }
+        this.accessToken = values.getString("access_token");
+        // expires_in 返回值为秒
+        long expiresIn = Long.parseLong(values.getString("expires_in")) * 1000;
+        this.expireTime = System.currentTimeMillis() + expiresIn;
+        OauthPreferenceUtil.setAccessToken(context, this.accessToken);
+        OauthPreferenceUtil.setCreateTime(context, System.currentTimeMillis());
+        OauthPreferenceUtil.setExpires(context, expiresIn);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        Bundle bundle = new Bundle();
+        if (this.accessToken != null) {
+            bundle.putString(OauthConfig.BundleKey.KEY_ACCESS_TOKEN, this.accessToken);
+        }
+        if (this.expireTime != 0) {
+            bundle.putLong(OauthConfig.BundleKey.KEY_EXPIRE_TIME, this.expireTime);
+        }
+        bundle.writeToParcel(dest, flags);
+    }
+
+    public static final Creator<AccessTokenManager> CREATOR = new Creator<AccessTokenManager>() {
+        @Override
+        public AccessTokenManager createFromParcel(Parcel source) {
+            return new AccessTokenManager(source);
+        }
+
+        @Override
+        public AccessTokenManager[] newArray(int size) {
+            return new AccessTokenManager[size];
+        }
+
+    };
+
+    /**
+     * 判断当前的token信息是否有效
+     *
+     * @return true/false
+     */
+    protected boolean isSessionValid() {
+        if (this.accessToken == null || this.expireTime == 0) {
+            initToken();
+        }
+        return this.accessToken != null && this.expireTime != 0 && System.currentTimeMillis() < this.expireTime;
+    }
+
+    /**
+     * 获取AccessToken信息
+     *
+     * @return accessToken
+     */
+    public String getAccessToken() {
+        if (this.accessToken == null) {
+            initToken();
+        }
+        return this.accessToken;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialog.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+
+import com.baidu.duer.dcs.androidsystemimpl.webview.BaseWebView;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 自定义的Dialog UI类,用来展示WebView界面,即用户登录和授权的页面
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduDialog extends Dialog {
+    private static final FrameLayout.LayoutParams MATCH = new FrameLayout.LayoutParams(
+            ViewGroup.LayoutParams.MATCH_PARENT,
+            ViewGroup.LayoutParams.MATCH_PARENT);
+    private static final String LOG_TAG = "BaiduDialog";
+    private final String mUrl;
+    private final BaiduDialogListener mListener;
+    private ProgressDialog mSpinner;
+    private BaseWebView mWebView;
+    private FrameLayout mContent;
+    private RelativeLayout webViewContainer;
+
+    /**
+     * 构造BaiduDialog
+     *
+     * @param context  展示Dialog UI的上下文环境,通常是XXActivity.this
+     * @param url      用户请求的url地址
+     * @param listener 用于对请求回调的Listener对象
+     */
+    public BaiduDialog(Context context, String url, BaiduDialogListener listener) {
+        super(context, android.R.style.Theme_Translucent_NoTitleBar);
+        mUrl = url;
+        mListener = listener;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        mListener.onCancel();
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        // 设置ProgressDialog的样式
+        mSpinner = new ProgressDialog(getContext());
+        mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        mSpinner.setMessage("登录中...");
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        mContent = new FrameLayout(getContext());
+        setUpWebView();
+        addContentView(mContent, MATCH);
+    }
+
+    private void setUpWebView() {
+        webViewContainer = new RelativeLayout(getContext());
+        mWebView = new BaseWebView(getContext().getApplicationContext());
+        mWebView.setWebViewClient(new BdWebViewClient());
+        mWebView.loadUrl(mUrl);
+        mWebView.setLayoutParams(MATCH);
+        mWebView.setVisibility(View.INVISIBLE);
+        webViewContainer.addView(mWebView);
+        mContent.addView(webViewContainer, MATCH);
+    }
+
+    private class BdWebViewClient extends WebViewClient {
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            LogUtil.d(LOG_TAG, "Redirect URL: " + url);
+            /*
+             * 如果url的地址为bdconnect://success,即使用User-Agent方式获取用户授权的redirct
+             * url,则截取url中返回的各种token参数,
+             * 如果出错,则通过listener的相应处理方式回调
+             */
+            if (url.startsWith(BaiduOauthImplicitGrant.SUCCESS_URI)) {
+                Bundle values = OauthNetUtil.parseUrl(url);
+                if (values != null && !values.isEmpty()) {
+                    String error = values.getString("error");
+                    // 用户取消授权返回error=access_denied
+                    if ("access_denied".equals(error)) {
+                        mListener.onCancel();
+                        BaiduDialog.this.dismiss();
+                        return true;
+                    }
+                    // 请求出错时返回error=1100&errorDesp=error_desp
+                    String errorDesp = values.getString("error_description");
+                    if (error != null && errorDesp != null) {
+                        mListener.onBaiduException(new BaiduException(error, errorDesp));
+                        BaiduDialog.this.dismiss();
+                        return true;
+                    }
+                    mListener.onComplete(values);
+                    BaiduDialog.this.dismiss();
+                    return true;
+                }
+            } else if (url.startsWith(BaiduOauthImplicitGrant.CANCEL_URI)) {
+                mListener.onCancel();
+                BaiduDialog.this.dismiss();
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void onReceivedError(WebView view, int errorCode, String description,
+                                    String failingUrl) {
+            super.onReceivedError(view, errorCode, description, failingUrl);
+            mListener.onError(new BaiduDialogError(description, errorCode, failingUrl));
+            BaiduDialog.this.dismiss();
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            LogUtil.d(LOG_TAG, "Webview loading URL: " + url);
+            super.onPageStarted(view, url, favicon);
+            mSpinner.show();
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            mSpinner.dismiss();
+            mContent.setBackgroundColor(Color.TRANSPARENT);
+            mWebView.setVisibility(View.VISIBLE);
+        }
+    }
+
+    @Override
+    public void dismiss() {
+        super.dismiss();
+        webViewContainer.removeView(mWebView);
+        mWebView.removeAllViews();
+        mWebView.destroy();
+    }
+
+    /**
+     * 用于BaiduDialog回调接口
+     */
+    public interface BaiduDialogListener {
+        /**
+         * BaiduDailog请求成功时,执行该法方法,实现逻辑包括存储value信息,跳转activity的过程
+         *
+         * @param values token信息的key-value存储
+         */
+        void onComplete(Bundle values);
+
+        /**
+         * 当BaiduDialog执行发生BaiduException时执行的方法。
+         *
+         * @param e BaiduException信息
+         */
+        void onBaiduException(BaiduException e);
+
+        /**
+         * 发生DialogError时执行的方法
+         *
+         * @param e BaiduDialogError异常类
+         */
+        void onError(BaiduDialogError e);
+
+        /**
+         * 当BaiduDialog执行取消操作时,执行该方法
+         */
+        void onCancel();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduDialogError.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 封装Dialog UI的错误异常信息类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduDialogError extends Exception {
+    private static final long serialVersionUID = 1529106452635370329L;
+    private int errorCode;
+    private String failingUrl;
+
+    public BaiduDialogError(String message, int errorCode, String failingUrl) {
+        super(message);
+        this.errorCode = errorCode;
+        this.failingUrl = failingUrl;
+    }
+
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    public String getFailingUrl() {
+        return failingUrl;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduException.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 封装了oauth授权和api请求的异常信息
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class BaiduException extends Exception {
+    private static final long serialVersionUID = -8309515227501598366L;
+    private String errorCode;
+    private String errorMsg;
+
+    public BaiduException() {
+        super();
+    }
+
+    public BaiduException(String detailMessage, Throwable throwable) {
+        super(detailMessage, throwable);
+    }
+
+    public BaiduException(String detailMessage) {
+        super(detailMessage);
+    }
+
+    public BaiduException(Throwable throwable) {
+        super(throwable);
+    }
+
+    public BaiduException(String errorCode, String errorDesp) {
+        this.errorCode = errorCode;
+        this.errorMsg = errorDesp;
+    }
+
+    public String getErrorCode() {
+        return errorCode;
+    }
+
+    public void setErrorCode(String errorCode) {
+        this.errorCode = errorCode;
+    }
+
+    public String getErrorDesp() {
+        return errorMsg;
+    }
+
+    public void setErrorDesp(String errorDesp) {
+        this.errorMsg = errorDesp;
+    }
+
+    @Override
+    public String toString() {
+        return "BaiduException [errorCode=" + errorCode + ", errorDesp=" + errorMsg + "]";
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/BaiduOauthImplicitGrant.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.webkit.CookieSyncManager;
+
+import com.baidu.duer.dcs.oauth.api.BaiduDialog.BaiduDialogListener;
+import com.baidu.duer.dcs.util.CommonUtil;
+import com.baidu.duer.dcs.util.LogUtil;
+
+/**
+ * 封装了oauth2授权,我们采用的是百度Oauth的implicit grant的方式
+ * 该方式的地址:http://developer.baidu.com/wiki/index.php?title=docs/oauth/implicit
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ * TODO: 百度Oauth2授权方式完善
+ */
+public class BaiduOauthImplicitGrant implements Parcelable {
+    private static final String LOG_TAG = "BaiduOauth";
+    public static final String CANCEL_URI = "bdconnect://cancel";
+    // 百度Oauth授权回调需要在DUEROS开放平台的控制平台
+    // 应用编辑-->>OAUTH CONFIG URL的链接地址-->>授权回调页-->>安全设置-->>授权回调页
+    // 需要注意
+    public static final String SUCCESS_URI = "bdconnect://success";
+    private static final String OAUTHORIZE_URL = "https://openapi.baidu.com/oauth/2.0/authorize";
+    private static final String DISPLAY_STRING = "mobile";
+    private static final String[] DEFAULT_PERMISSIONS = {"basic"};
+    private static final String KEY_CLIENT_ID = "clientId";
+    // 应用注册的api key信息
+    private String cliendId;
+    private AccessTokenManager accessTokenManager;
+
+    /**
+     * 使用应用的基本信息构建Baidu对象
+     *
+     * @param clientId 应用注册的api key信息
+     * @param context  当前应用的上下文环境
+     */
+    public BaiduOauthImplicitGrant(String clientId, Context context) {
+        if (clientId == null) {
+            throw new IllegalArgumentException("apiKey信息必须提供!");
+        }
+        this.cliendId = clientId;
+        init(context);
+    }
+
+    /**
+     * 使用Parcel流构建Baidu对象
+     *
+     * @param in Parcel流信息
+     */
+    public BaiduOauthImplicitGrant(Parcel in) {
+        Bundle bundle = Bundle.CREATOR.createFromParcel(in);
+        this.cliendId = bundle.getString(KEY_CLIENT_ID);
+        this.accessTokenManager = AccessTokenManager.CREATOR.createFromParcel(in);
+    }
+
+    /**
+     * 初始化accesTokenManager等信息
+     *
+     * @param context 当前执行的上下文环境
+     */
+    public void init(Context context) {
+        if (context.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE)
+                != PackageManager.PERMISSION_GRANTED) {
+            Log.w(LOG_TAG, "App miss permission android.permission.ACCESS_NETWORK_STATE! "
+                    + "Some mobile's WebView don't display page!");
+        }
+        this.accessTokenManager = new AccessTokenManager(context);
+        this.accessTokenManager.initToken();
+    }
+
+    /**
+     * 完成登录并获取token信息(User-Agent Flow),该方法使用默认的用户权限
+     *
+     * @param activity       需要展示Dialog UI的Activity
+     * @param isForceLogin   是否强制登录,如果该参数为true的话,会强制用户进行登录。
+     * @param isConfirmLogin 是否确认登录,如果该参数为true的话,如果用户当前为登录状态,
+     *                       则会显示用户的登录头像,点击头像后完成登录操作
+     * @param listener       Dialog回调接口如Activity跳转
+     */
+    public void authorize(Activity activity,
+                          boolean isForceLogin,
+                          boolean isConfirmLogin,
+                          final BaiduDialogListener listener) {
+        this.authorize(activity, null, isForceLogin, isConfirmLogin, listener);
+    }
+
+    /**
+     * 根据相应的permissions信息,完成登录并获取token信息(User-Agent Flow)
+     *
+     * @param activity     需要展示Dialog UI的Activity
+     * @param permissions  需要获得的授权权限信息
+     * @param isForceLogin 是否强制登录,如果该参数为true的话,会强制用户进行登录。
+     * @param listener     回调的listener接口,如Activity跳转等
+     */
+    private void authorize(Activity activity,
+                           String[] permissions,
+                           boolean isForceLogin,
+                           boolean isConfirmLogin,
+                           final BaiduDialogListener listener) {
+        if (this.isSessionValid()) {
+            listener.onComplete(new Bundle());
+            return;
+        }
+
+        // 使用匿名的BaiduDialogListener对listener进行了包装,并进行一些存储token信息和当前登录用户的逻辑,
+        // 外部传进来的listener信息不需要在进行存储相关的逻辑
+        this.authorize(activity,
+                permissions,
+                isForceLogin,
+                isConfirmLogin,
+                new BaiduDialogListener() {
+                    @Override
+                    public void onError(BaiduDialogError e) {
+                        LogUtil.d(LOG_TAG, "DialogError " + e);
+                        listener.onError(e);
+                    }
+
+                    @Override
+                    public void onComplete(Bundle values) {
+                        // 存储相应的token信息
+                        getAccessTokenManager().storeToken(values);
+                        // 完成授权操作,使用listener进行回调,eg。跳转到其他的activity
+                        listener.onComplete(values);
+                    }
+
+                    @Override
+                    public void onCancel() {
+                        LogUtil.d(LOG_TAG, "login cancel");
+                        listener.onCancel();
+                    }
+
+                    @Override
+                    public void onBaiduException(BaiduException e) {
+                        Log.d(LOG_TAG, "BaiduException : " + e);
+                        listener.onBaiduException(e);
+                    }
+                }, SUCCESS_URI, "token");
+    }
+
+    /**
+     * 通过Dialog UI展示用户登录、授权页
+     *
+     * @param activity     需要展示Dialog UI的Activity
+     * @param permissions  需要请求的环境
+     * @param listener     用于回调的listener接口方法
+     * @param redirectUrl  回调地址
+     * @param responseType 授权请求的类型
+     */
+    private void authorize(Activity activity,
+                           String[] permissions,
+                           boolean isForceLogin,
+                           boolean isConfirmLogin,
+                           final BaiduDialogListener listener,
+                           String redirectUrl, String responseType) {
+        CookieSyncManager.createInstance(activity);
+        Bundle params = new Bundle();
+        params.putString("client_id", this.cliendId);
+        params.putString("redirect_uri", redirectUrl);
+        params.putString("response_type", responseType);
+        params.putString("display", DISPLAY_STRING);
+        if (isForceLogin) {
+            params.putString("force_login", "1");
+        }
+        if (isConfirmLogin) {
+            params.putString("confirm_login", "1");
+        }
+        if (permissions == null) {
+            permissions = DEFAULT_PERMISSIONS;
+        }
+        if (permissions != null && permissions.length > 0) {
+            String scope = TextUtils.join(" ", permissions);
+            params.putString("scope", scope);
+        }
+        String url = OAUTHORIZE_URL + "?" + CommonUtil.encodeUrl(params);
+        LogUtil.d(LOG_TAG, "url:" + url);
+        if (activity.checkCallingOrSelfPermission(Manifest.permission.INTERNET)
+                != PackageManager.PERMISSION_GRANTED) {
+            CommonUtil.showAlert(activity, "没有权限", "应用需要访问互联网的权限");
+        } else {
+            new BaiduDialog(activity, url, listener).show();
+        }
+    }
+
+    /**
+     * 将清除存储的token信息
+     */
+    public void clearAccessToken() {
+        if (this.accessTokenManager != null) {
+            this.accessTokenManager.clearToken();
+            this.accessTokenManager = null;
+        }
+    }
+
+    /**
+     * 判断token信息是否有效。
+     *
+     * @return boolean true/false
+     */
+    public boolean isSessionValid() {
+        return this.accessTokenManager.isSessionValid();
+    }
+
+    /**
+     * 获取AccessTokenManager对象
+     *
+     * @return accessTokenManager对象
+     */
+    public AccessTokenManager getAccessTokenManager() {
+        return this.accessTokenManager;
+    }
+
+    /**
+     * 获取AccessToken信息
+     *
+     * @return accessToken信息
+     */
+    public String getAccessToken() {
+        return this.accessTokenManager.getAccessToken();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see android.os.Parcelable#describeContents()
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_CLIENT_ID, this.cliendId);
+        bundle.writeToParcel(dest, flags);
+        this.accessTokenManager.writeToParcel(dest, flags);
+    }
+
+    public static final Creator<BaiduOauthImplicitGrant> CREATOR = new Creator<BaiduOauthImplicitGrant>() {
+        public BaiduOauthImplicitGrant createFromParcel(Parcel in) {
+            return new BaiduOauthImplicitGrant(in);
+        }
+
+        public BaiduOauthImplicitGrant[] newArray(int size) {
+            return new BaiduOauthImplicitGrant[size];
+        }
+    };
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/IOauth.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+/**
+ * 百度认证接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/8.
+ */
+public interface IOauth {
+    /**
+     * 获取accessToken
+     *
+     * @return String
+     */
+    String getAccessToken();
+
+    /**
+     * 用户认证
+     */
+    void authorize();
+
+    /**
+     * 判断当前的token信息是否有效
+     *
+     * @return true/false
+     */
+    boolean isSessionValid();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthConfig.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+/**
+ * OauthConfig
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/3.
+ */
+public class OauthConfig {
+    public static class BundleKey {
+        // 在多个Activity中传递AccessTokenManager的键值
+        public static final String KEY_ACCESS_TOKEN = "baidu_token_manager_access_token";
+        public static final String KEY_EXPIRE_TIME = "baidu_token_manager_expire_time";
+    }
+
+    public static class PrefenenceKey {
+        // 持久化token信息的各种监制
+        public static final String SP_ACCESS_TOKEN = "baidu_oauth_config_prop_access_token";
+        public static final String SP_CREATE_TIME = "baidu_oauth_config_prop_create_time";
+        public static final String SP_EXPIRE_SECONDS = "baidu_oauth_config_prop_expire_secends";
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthImpl.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+import com.baidu.duer.dcs.androidapp.DcsSampleApplication;
+import com.baidu.duer.dcs.androidapp.DcsSampleOAuthActivity;
+
+/**
+ * 用户认证接口
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/8.
+ */
+public class OauthImpl implements IOauth {
+    @Override
+    public String getAccessToken() {
+        return OauthPreferenceUtil.getAccessToken(DcsSampleApplication.getInstance());
+    }
+
+    @Override
+    public void authorize() {
+        Intent intent = new Intent(DcsSampleApplication.getInstance(), DcsSampleOAuthActivity.class);
+        intent.putExtra("START_TAG", "RESTART");
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+        DcsSampleApplication.getInstance().startActivity(intent);
+    }
+
+    @Override
+    public boolean isSessionValid() {
+        String accessToken = getAccessToken();
+        long createTime = OauthPreferenceUtil.getCreateTime(DcsSampleApplication.getInstance());
+        long expires = OauthPreferenceUtil.getExpires(DcsSampleApplication.getInstance()) + createTime;
+        return !TextUtils.isEmpty(accessToken) && expires != 0 && System.currentTimeMillis() < expires;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthNetUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.os.Bundle;
+
+import com.baidu.duer.dcs.util.CommonUtil;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Util类封装了一些基本的方法
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/19.
+ */
+public class OauthNetUtil {
+    /**
+     * 提取回调url中的token信息,用于User-Agent Flow中的授权操作
+     *
+     * @param url 回调的url,包括token信息
+     * @return 返回bundle类型的token信息
+     */
+    public static Bundle parseUrl(String url) {
+        Bundle ret;
+        url = url.replace("bdconnect", "http");
+        try {
+            URL urlParam = new URL(url);
+            ret = CommonUtil.decodeUrl(urlParam.getQuery());
+            ret.putAll(CommonUtil.decodeUrl(urlParam.getRef()));
+            return ret;
+        } catch (MalformedURLException e) {
+            return new Bundle();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/oauth/api/OauthPreferenceUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.oauth.api;
+
+import android.content.Context;
+
+import com.baidu.duer.dcs.util.PreferenceUtil;
+
+/**
+ * 用户认证保存Preference工具类
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/6/3.
+ */
+public class OauthPreferenceUtil extends PreferenceUtil {
+    public static final String BAIDU_OAUTH_CONFIG = "baidu_oauth_config";
+
+    /**
+     * 保存数据的方法,拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+     *
+     * @param context 上下文
+     * @param key     key
+     * @param object  value
+     */
+    public static void put(Context context, String key, Object object) {
+        put(context, BAIDU_OAUTH_CONFIG, key, object);
+    }
+
+    /**
+     * 得到保存数据的方法,
+     * 根据默认值得到保存的数据的具体类型,
+     * 然后调用相对于的方法获取值
+     *
+     * @param context       上下文
+     * @param key           key
+     * @param defaultObject default-value
+     */
+    public static Object get(Context context, String key, Object defaultObject) {
+        return get(context, BAIDU_OAUTH_CONFIG, key, defaultObject);
+    }
+    
+    public static void clear(Context context) {
+        clear(context, BAIDU_OAUTH_CONFIG);
+    }
+
+    public static void setAccessToken(Context context, String value) {
+        put(context, OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, value);
+    }
+
+    public static String getAccessToken(Context context) {
+        return (String) get(context, OauthConfig.PrefenenceKey.SP_ACCESS_TOKEN, "");
+    }
+
+    public static void setExpires(Context context, long value) {
+        put(context, OauthConfig.PrefenenceKey.SP_EXPIRE_SECONDS, value);
+    }
+
+    public static long getExpires(Context context) {
+        return (long) get(context, OauthConfig.PrefenenceKey.SP_EXPIRE_SECONDS, 0L);
+    }
+
+    public static void setCreateTime(Context context, long value) {
+        put(context, OauthConfig.PrefenenceKey.SP_CREATE_TIME, value);
+    }
+
+    public static long getCreateTime(Context context) {
+        return (long) get(context, OauthConfig.PrefenenceKey.SP_CREATE_TIME, 0L);
+    }
+
+    public static void clearAllOauth(Context context) {
+        clear(context);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAlertsDataStore.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
+
+import java.util.List;
+
+/**
+ * alert存储的回调接口
+ *
+ * Created by guxiuzhong@baidu.com on 2017/5/18.
+ */
+public interface IAlertsDataStore {
+
+    void readFromDisk(ReadResultListener listener);
+
+    void writeToDisk(List<Alert> alerts, WriteResultListener listener);
+
+    /**
+     * 读取回调
+     */
+    interface ReadResultListener {
+        void onSucceed(List<Alert> alerts);
+
+        void onFailed(String errMsg);
+    }
+
+    /**
+     * 写入回调
+     */
+    interface WriteResultListener {
+        void onSucceed();
+
+        void onFailed(String errMsg);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioInput.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.framework.message.DcsStreamRequestBody;
+
+/**
+ * 语音输入接口
+ * <p>
+ * Created by wuruisheng on 2017/5/31.
+ */
+public interface IAudioInput {
+    /**
+     * 处理开始录音的逻辑
+     */
+    void startRecord();
+
+    /**
+     * 处理停止录音的逻辑
+     */
+    void stopRecord();
+
+    void registerAudioInputListener(IAudioInputListener audioInputListener);
+
+    interface IAudioInputListener {
+        void onStartRecord(DcsStreamRequestBody dcsStreamRequestBody);
+        void onStopRecord();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IAudioRecord.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 录音采集接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/26.
+ */
+public interface IAudioRecord {
+    /**
+     * 开始录音,采集音频数据
+     */
+    void startRecord();
+
+    /**
+     * 停止录音
+     */
+    void stopRecord();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IHandler.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+/**
+ * handler接口
+ * <p>
+ * Created by wuruisheng on 2017/6/7.
+ */
+public interface IHandler {
+    boolean post(Runnable runnable);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IMediaPlayer.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+import java.io.InputStream;
+
+/**
+ * 播放器接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public interface IMediaPlayer {
+    /**
+     * 播放状态
+     */
+    enum PlayState {
+        ERROR(-1),          // 播放错误
+        IDLE(0),            // 播放未开始
+        PREPARING(1),       // 播放准备中
+        PREPARED(2),        // 播放准备就绪
+        PLAYING(3),         // 正在播放
+        PAUSED(4),          // 暂停播放
+        STOPPED(5),         // 停止状态
+        COMPLETED(6);       // 播放完成
+
+        private int state;
+
+        PlayState(int state) {
+            this.state = state;
+        }
+
+        public int getState() {
+            return state;
+        }
+    }
+
+    /**
+     * 获取当前的播放状态
+     *
+     * @return PlayState
+     */
+    PlayState getPlayState();
+
+    /**
+     * 播放
+     *
+     * @param mediaResource mediaResource
+     */
+    void play(MediaResource mediaResource);
+
+    /**
+     * 暂停
+     */
+    void pause();
+
+    /**
+     * 停止播放
+     */
+    void stop();
+
+    /**
+     * 调用pause暂停后重新播放
+     */
+    void resume();
+
+    /**
+     * 从milliseconds位置开始播放
+     *
+     * @param milliseconds 毫秒
+     */
+    void seekTo(int milliseconds);
+
+    /**
+     * 释放,销毁播放器
+     */
+    void release();
+
+    /**
+     * 设置音量 volume:0-1
+     *
+     * @param volume 音量(0-1之间的浮点数)
+     */
+    void setVolume(float volume);
+
+    float getVolume();
+
+    /**
+     * 设置静音
+     *
+     * @param mute 静音开关
+     */
+    void setMute(boolean mute);
+
+    boolean getMute();
+
+    /**
+     * 获取当前的播放位置
+     *
+     * @return 当前的播放位置
+     */
+    long getCurrentPosition();
+
+    /**
+     * 获取当前音频文件/流的总时长,单位:ms
+     *
+     * @return ms
+     */
+    long getDuration();
+
+    /**
+     * 获取当前缓冲到多少 0-100f
+     *
+     * @return 0-100f
+     */
+    float getBufferPercentage();
+
+    /**
+     * 添加播放器状态回调
+     *
+     * @param listener listener
+     */
+    void addMediaPlayerListener(IMediaPlayerListener listener);
+
+    void removeMediaPlayerListener(IMediaPlayerListener listener);
+
+    /**
+     * 设置播放通道是否处在活跃状态,比如:当用户在语音请求时,对话通道进入活跃状态
+     *
+     * @param isActive 是否处在活跃状态
+     */
+    void setActive(boolean isActive);
+
+    boolean isActive();
+
+    /**
+     * 播放器播放状态回调接口
+     */
+    interface IMediaPlayerListener {
+
+        /**
+         * 调用完play方法后回调此方法
+         */
+        void onInit();
+
+        /**
+         * 播放器准备完成后回调
+         */
+        void onPrepared();
+
+        /**
+         * 播放器销毁后回调
+         */
+        void onRelease();
+
+        /**
+         * 正在播放时回调
+         */
+        void onPlaying();
+
+        /**
+         * 暂停后回调
+         */
+        void onPaused();
+
+        void onStopped();
+
+        /**
+         * 播放完成后回调
+         */
+        void onCompletion();
+
+        /**
+         * 播放出错
+         */
+        void onError(String error, ErrorType errorType);
+
+        /**
+         * 播放器缓冲回调
+         *
+         * @param percent 缓冲的进度 0-100
+         */
+        void onBufferingUpdate(int percent);
+
+        /**
+         * 开始缓冲时回调
+         */
+        void onBufferingStart();
+
+        /**
+         * 结束缓冲时回调
+         */
+        void onBufferingEnd();
+
+    }
+
+    /**
+     * 播放错误类型信息
+     */
+    enum ErrorType {
+        MEDIA_ERROR_UNKNOWN("An unknown error occurred"),
+        MEDIA_ERROR_INVALID_REQUEST(
+                "The server recognized the request as being malformed "
+                        + "(bad request, unauthorized, forbidden, not found, etc)"),
+        MEDIA_ERROR_SERVICE_UNAVAILABLE("The device was unavailable to reach the service"),
+        MEDIA_ERROR_INTERNAL_SERVER_ERROR(
+                "The server accepted the request, but was unable to process it as expected"),
+        MEDIA_ERROR_INTERNAL_DEVICE_ERROR("There was an internal error on the device");
+
+        private final String message;
+
+        ErrorType(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+    }
+
+    /**
+     * 内部空实现的IMediaPlayerListener,如果你只关心onCompletion,可以用这个
+     */
+    class SimpleMediaPlayerListener implements IMediaPlayerListener {
+        @Override
+        public void onInit() {
+
+        }
+
+        @Override
+        public void onPrepared() {
+
+        }
+
+        @Override
+        public void onRelease() {
+
+        }
+
+        @Override
+        public void onPlaying() {
+
+        }
+
+        @Override
+        public void onPaused() {
+
+        }
+
+        @Override
+        public void onStopped() {
+
+        }
+
+        @Override
+        public void onCompletion() {
+
+        }
+
+        @Override
+        public void onError(String error, ErrorType errorType) {
+
+        }
+
+        @Override
+        public void onBufferingUpdate(int percent) {
+
+        }
+
+        @Override
+        public void onBufferingStart() {
+
+        }
+
+        @Override
+        public void onBufferingEnd() {
+
+        }
+    }
+
+    /**
+     * 需要播放的音频类型
+     */
+    final class MediaResource {
+        public InputStream stream;  // 流类型
+        public String url;          // url类型
+        public boolean isStream;    // 是否值流类型
+
+        public MediaResource(InputStream stream) {
+            this.stream = stream;
+            this.isStream = true;
+        }
+
+        public MediaResource(String url) {
+            this.url = url;
+            this.isStream = false;
+        }
+
+        @Override
+        public String toString() {
+            if (isStream) {
+                return "stream";
+            } else {
+                return url;
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlatformFactory.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 定义平台相关工厂类
+ *
+ * Created by wuruisheng on 2017/6/7.
+ */
+public interface IPlatformFactory {
+    IHandler createHandler();
+    IHandler getMainHandler();
+    IAudioRecord getAudioRecord();
+    IWakeUp getWakeUp();
+    IAudioInput getVoiceInput();
+    IMediaPlayer createMediaPlayer();
+    IAlertsDataStore createAlertsDataStore();
+    IWebView getWebView();
+    void setWebView(IWebView webView);
+    IPlaybackController getPlayback();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IPlaybackController.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+import com.baidu.duer.dcs.framework.IResponseListener;
+
+/**
+ * PlaybackController接口
+ * <p>
+ * Created by zhoujianliang01 on 2017/6/17.
+ */
+public interface IPlaybackController {
+    void play(IResponseListener responseListener);
+
+    void pause(IResponseListener responseListener);
+
+    void previous(IResponseListener responseListener);
+
+    void next(IResponseListener responseListener);
+
+    void registerPlaybackListener(IPlaybackListener listener);
+
+    interface IPlaybackListener {
+        void onPlay(IResponseListener responseListener);
+
+        void onPause(IResponseListener responseListener);
+
+        void onPrevious(IResponseListener responseListener);
+
+        void onNext(IResponseListener responseListener);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWakeUp.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,58 @@
+/*
+ * *
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.systeminterface;
+
+/**
+ * 唤醒接口
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/25.
+ */
+public interface IWakeUp {
+    /**
+     * 开始唤醒
+     * 1.初始化唤醒词
+     * 2.打开麦克风,并开始音频唤醒的解码
+     */
+    void startWakeUp();
+
+    /**
+     * 停止唤醒,调用停止录音
+     */
+    void stopWakeUp();
+
+    /**
+     * 释放资源,比如调用底层库释放资源等
+     */
+    void releaseWakeUp();
+
+    /**
+     * 唤醒结果的回调监听
+     *
+     * @param listener 监听实现
+     */
+    void addWakeUpListener(IWakeUpListener listener);
+
+    /**
+     * 唤醒结果的回调接口
+     */
+    interface IWakeUpListener {
+        /**
+         * 唤醒成功后回调
+         */
+        void onWakeUpSucceed();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/systeminterface/IWebView.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.systeminterface;
+
+/**
+ * WebView接口
+ * <p>
+ * Created by zhoujianliang01 on 2017/6/17.
+ */
+public interface IWebView {
+    void loadUrl(String url);
+    void linkClicked(String url);
+
+    void addWebViewListener(IWebViewListener listener);
+
+    interface IWebViewListener {
+        void onLinkClicked(String url);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/CommonUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.UUID;
+
+/**
+ * 辅助工具类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/17.
+ */
+public class CommonUtil {
+    private static final int JSON_INDENT = 4;
+
+    public static String getCurrentTime() {
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
+                Locale.CHINESE);
+        return format.format(new Date());
+    }
+
+    /**
+     * 将毫秒格式转化为yyyy-MM-dd HH:mm:ss
+     *
+     * @param milliSeconds 毫秒
+     * @return 格式化后的字符串结果
+     */
+    public static String formatToDataTime(long milliSeconds) {
+        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
+        return sd.format(milliSeconds);
+    }
+
+    /**
+     * 将key1=value1&key2=value2格式的query转换成key-value形式的参数串
+     *
+     * @param query key1=value1&key2=value2格式的query
+     * @return key-value形式的bundle
+     */
+    public static Bundle decodeUrl(String query) {
+        Bundle ret = new Bundle();
+        if (query != null) {
+            String[] pairs = query.split("&");
+            for (String pair : pairs) {
+                String[] keyAndValues = pair.split("=");
+                if (keyAndValues != null && keyAndValues.length == 2) {
+                    String key = keyAndValues[0];
+                    String value = keyAndValues[1];
+                    if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
+                        ret.putString(URLDecoder.decode(key), URLDecoder.decode(value));
+                    }
+                }
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * 将key-value形式的参数串,转换成key1=value1&key2=value2格式的query
+     *
+     * @param params key-value参数
+     * @return key1=value1&key2=value2格式的query
+     */
+    public static String encodeUrl(Bundle params) {
+        if (params == null || params.isEmpty()) {
+            return null;
+        }
+        boolean first = true;
+        StringBuilder sb = new StringBuilder();
+        for (String key : params.keySet()) {
+            String paramValue = params.getString(key);
+            if (paramValue == null) {
+                continue;
+            }
+            if (first) {
+                first = false;
+            } else {
+                sb.append("&");
+            }
+            sb.append(URLEncoder.encode(key)).append("=").append(URLEncoder.encode(paramValue));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 展示一个通用的弹出框UI
+     *
+     * @param context 展示弹出框的上下文环境
+     * @param title   警告的title信息
+     * @param text    警告信息
+     */
+    public static void showAlert(Context context, String title, String text) {
+        AlertDialog alertDialog = new Builder(context).create();
+        alertDialog.setTitle(title);
+        alertDialog.setMessage(text);
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.show();
+    }
+
+    private static long lastClickTime;
+
+    /**
+     * 是否是双击
+     *
+     * @return true 是,false 否
+     */
+    public static boolean isFastDoubleClick() {
+        long time = System.currentTimeMillis();
+        if (time - lastClickTime < 500) {
+            return true;
+        }
+        lastClickTime = time;
+        return false;
+    }
+
+    /**
+     * json 格式化输出
+     *
+     * @param json json字符串
+     * @return 用四个空格缩进后的json字符串结果
+     */
+    public static String formatJson(String json) {
+        String formatted = "";
+        if (json == null || json.length() == 0) {
+            return formatted;
+        }
+        try {
+            if (json.startsWith("{")) {
+                JSONObject jo = new JSONObject(json);
+                formatted = jo.toString(JSON_INDENT);
+            } else if (json.startsWith("[")) {
+                JSONArray ja = new JSONArray(json);
+                formatted = ja.toString(JSON_INDENT);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return formatted;
+    }
+
+    /**
+     * 关闭流
+     *
+     * @param closeables closeables
+     */
+    public static void closeQuietly(Closeable... closeables) {
+        for (Closeable c : closeables) {
+            try {
+                if (c != null) {
+                    c.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * Android设备物理唯一标识符
+     *
+     * @return String 设备唯一标识
+     */
+    public static String getDeviceUniqueID() {
+        String devIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            devIDShort += (Build.SUPPORTED_ABIS[0].length() % 10);
+        } else {
+            devIDShort += (Build.CPU_ABI.length() % 10);
+        }
+        devIDShort += (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10)
+                + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
+        String serial;
+        try {
+            serial = Build.class.getField("SERIAL").get(null).toString();
+            return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
+        } catch (Exception e) {
+            serial = "Dueros000";
+        }
+        return new UUID(devIDShort.hashCode(), serial.hashCode()).toString();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/DateFormatterUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * iso8601string 时间格式转换
+ * <p>
+ * Created by zhoujianliang01@baidu.com on 2017/6/5.
+ */
+public class DateFormatterUtil {
+    private static final String TAG = "ISO8601DateFormatter";
+    private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.CHINESE);
+    private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat("yyyy-MM-dd'T'HHmmssZ", Locale.CHINESE);
+    private static final String UTC_PLUS = "+";
+    private static final String UTC_MINUS = "-";
+
+    /**
+     * 将iso8601string格式字符串时间转为Date
+     *
+     * @param iso8601string iso8601格式的时间字符串
+     * @return Date Date类型表示的结果
+     * @throws ParseException ParseException
+     */
+    public static Date toDate(String iso8601string) throws ParseException {
+        iso8601string = iso8601string.trim();
+        if (iso8601string.toUpperCase().indexOf("Z") > 0) {
+            iso8601string = iso8601string.toUpperCase().replace("Z", "+0000");
+        } else if (((iso8601string.indexOf(UTC_PLUS)) > 0)) {
+            iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_PLUS));
+            iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_PLUS), UTC_PLUS);
+        } else if (((iso8601string.indexOf(UTC_MINUS)) > 0)) {
+            iso8601string = replaceColon(iso8601string, iso8601string.indexOf(UTC_MINUS));
+            iso8601string = appendZeros(iso8601string, iso8601string.indexOf(UTC_MINUS), UTC_MINUS);
+        }
+        LogUtil.d(TAG, "iso8601string:" + iso8601string);
+        Date date;
+        if (iso8601string.contains(":")) {
+            date = DATE_FORMAT_1.parse(iso8601string);
+        } else {
+            date = DATE_FORMAT_2.parse(iso8601string);
+        }
+        return date;
+    }
+
+    public static String toISO8601String(Date date) {
+        return DATE_FORMAT_1.format(date);
+    }
+
+    private static String replaceColon(String sourceStr, int offsetIndex) {
+        if (sourceStr.substring(offsetIndex).contains(":")) {
+            return sourceStr.substring(0, offsetIndex) + sourceStr.substring(offsetIndex).replace(":", "");
+        }
+        return sourceStr;
+    }
+
+    private static String appendZeros(String sourceStr, int offsetIndex, String offsetChar) {
+        if ((sourceStr.length() - 1) - sourceStr.indexOf(offsetChar, offsetIndex) <= 2) {
+            return sourceStr + "00";
+        }
+        return sourceStr;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/FileUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import android.os.Environment;
+import android.text.TextUtils;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+/**
+ * FileUtil
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/31.
+ */
+public class FileUtil {
+    public static final String TEMP_POSTFIX = ".download";
+    private static final String LOG_FILE = "LogAll.txt";
+    private static final String APP_DIR = "/DCS";
+    private static final String SPEAK = APP_DIR + "/Speak";
+    private static final String ALERT = APP_DIR + "/Alert";
+    private static final String ALARM_FILE = "alarms.json";
+
+    private static String getSpeakDirPath() {
+        String dirPath = "";
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + SPEAK;
+            File dir = new File(dirPath);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+        }
+        return dirPath;
+    }
+
+    private static String getAlertDirPath() {
+        String dirPath = "";
+        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+            dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + ALERT;
+            File dir = new File(dirPath);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+        }
+        return dirPath;
+    }
+
+    public static File getSpeakFile() {
+        String dirPath = getSpeakDirPath();
+        if (TextUtils.isEmpty(dirPath)) {
+            return null;
+        }
+        return new File(dirPath,
+                "dcs_" + System.currentTimeMillis() + ".mp3" + TEMP_POSTFIX);
+    }
+
+    public static File getAlarmFile() {
+        String dirPath = getAlertDirPath();
+        if (TextUtils.isEmpty(dirPath)) {
+            return null;
+        }
+        return new File(dirPath, ALARM_FILE);
+    }
+
+    public static String getLogFilePath() {
+        return Environment.getExternalStorageDirectory().getAbsolutePath()
+                + APP_DIR + File.separator + LOG_FILE;
+    }
+
+    /**
+     * 日志追加文件
+     *
+     * @param content 追加的内容
+     */
+    public static void appendStrToFile(String content) {
+        File file = new File(getLogFilePath());
+        if (!file.isFile()) {
+            file.delete();
+        }
+        if (!file.exists()) {
+            try {
+                file.createNewFile();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        BufferedWriter out = null;
+        try {
+            out = new BufferedWriter(new OutputStreamWriter(
+                    new FileOutputStream(file, true)));
+            out.write(content);
+            out.flush();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                out.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/LogUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import android.util.Log;
+
+/**
+ * Log日志输出信息
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class LogUtil {
+    // 是否开始debug模式,日志输出
+    public static boolean DEBUG = true;
+    private static final String APPNAME = "DCS-";
+    private static boolean LOGV_ON = DEBUG;
+    private static boolean LOGD_ON = DEBUG;
+    private static boolean LOGI_ON = DEBUG;
+    private static boolean LOGW_ON = DEBUG;
+    private static boolean LOGE_ON = DEBUG;
+    // 是否log写文件
+    private static boolean isWriteFile = true;
+
+    /**
+     * 设置debug 开关
+     *
+     * @param isDebug debug开关,true为开,false为关
+     */
+    public static void setDEBUG(boolean isDebug) {
+        DEBUG = isDebug;
+        LOGV_ON = true & DEBUG;
+        LOGD_ON = true & DEBUG;
+        LOGI_ON = true & DEBUG;
+        LOGW_ON = true & DEBUG;
+        LOGE_ON = true & DEBUG;
+    }
+
+    public static boolean getDEBUG() {
+        return DEBUG;
+    }
+
+    /**
+     * 记录相应的log信息v
+     *
+     * @param tag log tag 信息
+     * @param msg log msg 信息
+     */
+    public static void v(String tag, String msg) {
+        if (LOGV_ON) {
+            tag = APPNAME + tag;
+            Log.v(tag, msg);
+            writeLog("V", tag, msg, null);
+        }
+    }
+
+    public static void v(Class<?> c, String msg) {
+        if (LOGV_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.v(tag, msg);
+            writeLog("V", tag, msg, null);
+        }
+    }
+
+    public static void d(Class<?> c, String msg) {
+        if (LOGD_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.d(tag, msg);
+            writeLog("D", tag, msg, null);
+        }
+    }
+
+    /**
+     * 记录相应的log信息d
+     *
+     * @param tag log tag 信息
+     * @param msg log msg 信息
+     */
+    public static void d(String tag, String msg) {
+        if (LOGD_ON) {
+            tag = APPNAME + tag;
+            Log.d(tag, msg);
+            writeLog("D", tag, msg, null);
+        }
+    }
+
+    public static void d(String tag, String msg, Throwable tr) {
+        if (LOGE_ON) {
+            tag = APPNAME + tag;
+            Log.d(tag, msg, tr);
+            writeLog("D", tag, msg, tr);
+        }
+    }
+
+    /**
+     * 记录相应的log信息i
+     *
+     * @param tag log tag 信息
+     * @param msg log msg 信息
+     */
+    public static void i(String tag, String msg) {
+        if (LOGI_ON) {
+            tag = APPNAME + tag;
+            Log.i(tag, msg);
+            writeLog("I", tag, msg, null);
+        }
+    }
+
+    public static void i(Class<?> c, String msg) {
+        if (LOGI_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.i(tag, msg);
+            writeLog("I", tag, msg, null);
+        }
+    }
+
+    public static void w(Class<?> c, String msg) {
+        if (LOGW_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.w(tag, msg);
+            writeLog("W", tag, msg, null);
+        }
+    }
+
+    public static void w(Class<?> c, String msg, Throwable tr) {
+        if (LOGW_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.w(tag, msg, tr);
+            writeLog("W", tag, msg, tr);
+        }
+    }
+
+    /**
+     * 记录相应的log信息w
+     *
+     * @param tag log tag 信息
+     * @param msg log msg 信息
+     */
+    public static void w(String tag, String msg) {
+        if (LOGW_ON) {
+            tag = APPNAME + tag;
+            Log.w(tag, msg);
+            writeLog("W", tag, msg, null);
+        }
+    }
+
+    public static void w(String tag, String msg, Throwable tr) {
+        if (LOGW_ON) {
+            tag = APPNAME + tag;
+            Log.w(tag, msg, tr);
+            writeLog("W", tag, msg, tr);
+        }
+    }
+
+    /**
+     * 记录相应的log信息e
+     *
+     * @param tag log tag 信息
+     * @param msg log msg 信息
+     */
+    public static void e(String tag, String msg) {
+        if (LOGE_ON) {
+            tag = APPNAME + tag;
+            Log.e(tag, msg);
+            writeLog("E", tag, msg, null);
+        }
+    }
+
+    public static void e(Class<?> c, String msg) {
+        if (LOGE_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.e(tag, msg);
+            writeLog("E", tag, msg, null);
+        }
+    }
+
+    public static void e(String tag, String msg, Throwable tr) {
+        if (LOGE_ON) {
+            tag = APPNAME + tag;
+            Log.e(tag, msg, tr);
+            writeLog("E", tag, msg, tr);
+        }
+    }
+
+    public static void e(Class<?> c, String msg, Throwable tr) {
+        if (LOGE_ON) {
+            String tag = APPNAME + c.getSimpleName();
+            Log.e(tag, msg, tr);
+            writeLog("E", tag, msg, tr);
+        }
+    }
+
+    public static void setIsWriteFile(boolean isWriteFile) {
+        LogUtil.isWriteFile = isWriteFile;
+    }
+
+    private static void writeLog(String logLev, String tag, String msg, Throwable tr) {
+        if (isWriteFile) {
+            try {
+                StringBuffer stringBuffer = new StringBuffer();
+                stringBuffer
+                        .append(CommonUtil.getCurrentTime())
+                        .append("\n")
+                        .append(tag)
+                        .append("-")
+                        .append(msg);
+                if (tr != null) {
+                    stringBuffer.append(Log.getStackTraceString(tr));
+                }
+                stringBuffer.append("\n");
+                // 写文件
+                FileUtil.appendStrToFile(stringBuffer.toString());
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/NetWorkUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+
+/**
+ * 网络检测工具类
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/5/23.
+ */
+public class NetWorkUtil {
+    public static boolean isNetworkConnected(Context context) {
+        if (context != null) {
+            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
+                    .getSystemService(Context.CONNECTIVITY_SERVICE);
+            NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
+            if (mNetworkInfo != null) {
+                return mNetworkInfo.isAvailable();
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/ObjectMapperUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import org.codehaus.jackson.map.DeserializationConfig;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectReader;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.map.SerializationConfig;
+
+import java.io.IOException;
+
+/**
+ * json序列化成对象和反序列化
+ *
+ * Created by wuruisheng on 2017/5/15.
+ */
+public class ObjectMapperUtil {
+    private static ObjectMapper objectMapper;
+
+    private static class ObjectMapperFactoryHolder {
+        private static final ObjectMapperUtil instance = new ObjectMapperUtil();
+    }
+
+    public static ObjectMapperUtil instance() {
+        return ObjectMapperFactoryHolder.instance;
+    }
+
+    private ObjectMapperUtil() {
+        objectMapper = new ObjectMapper();
+        objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
+        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
+    }
+
+    public ObjectReader getObjectReader() {
+        return objectMapper.reader();
+    }
+
+    public ObjectReader getObjectReader(Class<?> clazz) {
+        return objectMapper.reader().withType(clazz);
+    }
+
+    public ObjectWriter getObjectWriter() {
+        return objectMapper.writer();
+    }
+
+
+    public String objectToJson(Object obj) {
+        String result = "";
+        try {
+            result = getObjectWriter().writeValueAsString(obj);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/util/PreferenceUtil.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ * 
+ * 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 com.baidu.duer.dcs.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Build;
+
+import java.util.Map;
+
+/**
+ * 提供统一的Preference util方法
+ * <p>
+ * Created by zhangyan42@baidu.com on 2017/5/24.
+ */
+public class PreferenceUtil {
+    private static final String APP_SHARD = "com.baidu.duer.dcs";
+
+    /**
+     * 保存数据的方法,拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+     *
+     * @param context 上下文
+     * @param key     key
+     * @param object  value
+     */
+    public static void put(Context context, String key, Object object) {
+        put(context, APP_SHARD, key, object);
+    }
+
+    public static void put(Context context, String spName, String key, Object object) {
+        SharedPreferences sp = context.getSharedPreferences(spName,
+                Context.MODE_PRIVATE);
+        Editor editor = sp.edit();
+
+        if (object instanceof String) {
+            editor.putString(key, (String) object);
+        } else if (object instanceof Integer) {
+            editor.putInt(key, (Integer) object);
+        } else if (object instanceof Boolean) {
+            editor.putBoolean(key, (Boolean) object);
+        } else if (object instanceof Float) {
+            editor.putFloat(key, (Float) object);
+        } else if (object instanceof Long) {
+            editor.putLong(key, (Long) object);
+        } else {
+            editor.putString(key, object.toString());
+        }
+        editSubmit(editor);
+    }
+
+    private static void editSubmit(Editor editor) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+            editor.apply();
+        } else {
+            editor.commit();
+        }
+    }
+
+    /**
+     * 得到保存数据的方法,
+     * 根据默认值得到保存的数据的具体类型,
+     * 然后调用相对于的方法获取值
+     *
+     * @param context       上下文
+     * @param key           key
+     * @param defaultObject default-value
+     */
+    public static Object get(Context context, String key, Object defaultObject) {
+        return get(context, APP_SHARD, key, defaultObject);
+    }
+
+    public static Object get(Context context, String spName, String key, Object defaultObject) {
+        SharedPreferences sp = context.getSharedPreferences(spName,
+                Context.MODE_PRIVATE);
+
+        if (defaultObject instanceof String) {
+            return sp.getString(key, (String) defaultObject);
+        } else if (defaultObject instanceof Integer) {
+            return sp.getInt(key, (Integer) defaultObject);
+        } else if (defaultObject instanceof Boolean) {
+            return sp.getBoolean(key, (Boolean) defaultObject);
+        } else if (defaultObject instanceof Float) {
+            return sp.getFloat(key, (Float) defaultObject);
+        } else if (defaultObject instanceof Long) {
+            return sp.getLong(key, (Long) defaultObject);
+        }
+        return null;
+    }
+
+    /**
+     * 移除某个key值已经对应的值
+     *
+     * @param context 上下文
+     * @param key     key
+     */
+    public static void remove(Context context, String key) {
+        remove(context, APP_SHARD, key);
+    }
+
+    public static void remove(Context context, String spName, String key) {
+        SharedPreferences sp = context.getSharedPreferences(spName,
+                Context.MODE_PRIVATE);
+        Editor editor = sp.edit();
+        editor.remove(key);
+        editSubmit(editor);
+    }
+
+    /**
+     * 清除所有数据
+     *
+     * @param context 上下文
+     */
+    public static void clear(Context context) {
+        clear(context, APP_SHARD);
+    }
+
+    public static void clear(Context context, String spName) {
+        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
+        Editor editor = sp.edit();
+        editor.clear();
+        editSubmit(editor);
+    }
+
+    /**
+     * 查询某个key是否已经存在
+     *
+     * @param context 上下文
+     * @param key     key
+     */
+    public static boolean contains(Context context, String key) {
+        return contains(context, APP_SHARD, key);
+    }
+
+    public static boolean contains(Context context, String spName, String key) {
+        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
+        return sp.contains(key);
+    }
+
+    /**
+     * 返回所有的键值对
+     *
+     * @param context 上下文
+     */
+    public static Map<String, ?> getAll(Context context) {
+        return getAll(context, APP_SHARD);
+    }
+
+    public static Map<String, ?> getAll(Context context, String spName) {
+        SharedPreferences sp = context.getSharedPreferences(spName,
+                Context.MODE_PRIVATE);
+        return sp.getAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/wakeup/WakeUp.java	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
+ *
+ *  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 com.baidu.duer.dcs.wakeup;
+
+import com.baidu.duer.dcs.systeminterface.IAudioRecord;
+import com.baidu.duer.dcs.systeminterface.IWakeUp;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 本地唤醒服务
+ * <p>
+ * Created by guxiuzhong@baidu.com on 2017/6/22.
+ */
+public class WakeUp {
+    private IWakeUp iWakeUp;
+    private List<IWakeUp.IWakeUpListener> wakeUpListeners;
+    private IAudioRecord iAudioRecord;
+
+    public WakeUp(IWakeUp iWakeUp, IAudioRecord iAudioRecord) {
+        this.iWakeUp = iWakeUp;
+        this.iAudioRecord = iAudioRecord;
+        this.wakeUpListeners = Collections.synchronizedList(new LinkedList<IWakeUp.IWakeUpListener>());
+        this.iWakeUp.addWakeUpListener(new IWakeUp.IWakeUpListener() {
+            @Override
+            public void onWakeUpSucceed() {
+                fireOnWakeUpSucceed();
+            }
+        });
+        // 启动音频采集
+        this.iAudioRecord.startRecord();
+    }
+
+    private void fireOnWakeUpSucceed() {
+        for (IWakeUp.IWakeUpListener listener : wakeUpListeners) {
+            listener.onWakeUpSucceed();
+        }
+    }
+
+    /**
+     * 开始唤醒,麦克风处于打开状态,一旦检测到有音频开始唤醒解码
+     */
+    public void startWakeUp() {
+        iWakeUp.startWakeUp();
+    }
+
+    /**
+     * 停止唤醒,关闭麦克风
+     */
+    public void stopWakeUp() {
+        iWakeUp.stopWakeUp();
+    }
+
+    /**
+     * 释放资源-解码so库资源
+     */
+    public void releaseWakeUp() {
+        iAudioRecord.stopRecord();
+        iWakeUp.releaseWakeUp();
+    }
+
+    /**
+     * 添加唤醒成功后的监听
+     */
+    public void addWakeUpListener(IWakeUp.IWakeUpListener listener) {
+        wakeUpListeners.add(listener);
+    }
+
+    public void removeWakeUpListener(IWakeUp.IWakeUpListener listener) {
+        if (wakeUpListeners.contains(listener)) {
+            wakeUpListeners.remove(listener);
+        }
+    }
+}
\ No newline at end of file
Binary file dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/arm64-v8a/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi-v7a/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/armeabi/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86/libbdEasrS1MergeNormal.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEASRAndroid.so has changed
Binary file dcs-sdk-java-master/app/src/main/jniLibs/x86_64/libbdEasrS1MergeNormal.so has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/drawable/btn_bg.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false">
+        <shape>
+            <solid android:color="@color/color_ff1247c2" />
+            <corners android:radius="150dp" />
+
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape>
+            <solid android:color="@color/color_aa1247c2" />
+            <corners android:radius="150dp" />
+            <stroke android:width="1dp" android:color="@color/color_aa1247c2" />
+        </shape>
+
+    </item>
+    <item android:state_pressed="true">
+        <shape>
+            <solid android:color="@color/color_aa1247c2" />
+            <corners android:radius="150dp" />
+            <stroke android:width="1dp" android:color="@color/color_aa1247c2" />
+        </shape>
+
+    </item>
+</selector>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_main.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/color_f5f5f5"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:text="@string/wakeup_word"
+        android:textColor="@android:color/black"
+        android:textSize="18dp" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:orientation="vertical">
+
+        <ScrollView
+            android:id="@+id/id_sv_request"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <LinearLayout
+                android:id="@+id/topLinearLayout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" />
+        </ScrollView>
+    </LinearLayout>
+
+
+    <LinearLayout
+        android:id="@+id/songLinearLayout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/previousSongBtn"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/previous_audio" />
+
+        <Button
+            android:id="@+id/pauseOrPlayBtn"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/audio_default" />
+
+        <Button
+            android:id="@+id/nextSongBtn"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:text="@string/next_audio" />
+
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/id_tv_time_0"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textColor="@android:color/black"
+        android:textSize="16dp" />
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="10dp"
+        android:orientation="horizontal">
+
+        <Button
+            android:id="@+id/voiceBtn"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_margin="10dp"
+            android:layout_weight="1"
+            android:background="@drawable/btn_bg"
+            android:text="@string/stop_record"
+            android:textColor="@android:color/white"
+            android:textSize="16dp" />
+
+        <Button
+            android:id="@+id/openLogBtn"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_margin="10dp"
+            android:layout_weight="1"
+            android:background="@drawable/btn_bg"
+            android:text="@string/open_log"
+            android:textColor="@android:color/white"
+            android:textSize="16dp" />
+
+    </LinearLayout>
+
+</LinearLayout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:text="@string/client_id"
+        android:textSize="16sp" />
+
+    <EditText
+        android:id="@+id/edit_client_id"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:enabled="false" />
+
+    <Button
+        android:id="@+id/btn_login"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:background="@drawable/btn_bg"
+        android:text="@string/login"
+        android:textColor="@android:color/white" />
+
+</LinearLayout>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_oauth_login.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <RelativeLayout
+        android:id="@+id/containerLayout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <WebView
+        android:id="@+id/oauthWeb"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/layout/dcs_sample_activity_screen_html.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+
+    <RelativeLayout
+        android:id="@+id/relativeLayout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    </RelativeLayout>
+</RelativeLayout>
\ No newline at end of file
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-hdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-mdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xhdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xxhdpi/ic_launcher.png has changed
Binary file dcs-sdk-java-master/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/values/colors.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+
+    <color name="color_ff1247c2">#ff1247c2</color>
+    <color name="color_aa1247c2">#aa1247c2</color>
+    <color name="color_transparent">#00000000</color>
+    <color name="color_f5f5f5">#f5f5f5</color>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/values/strings.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,25 @@
+<resources>
+    <string name="app_name">DcsSampleApp</string>
+    <string name="err_net_msg">当前网络连接失败,请稍后重试</string>
+    <string name="voice_err_msg">识别失败,请稍后再试</string>
+    <string name="audio_paused">暂停中&#8230;</string>
+    <string name="audio_playing">播放中&#8230;</string>
+    <string name="audio_default">等待音乐</string>
+    <string name="stop_record">点击说话</string>
+    <string name="start_record">录音中&#8230;</string>
+    <string name="time_record">耗时:click->StopListen:%1$dms</string>
+    <string name="request_error">出错了,请稍后再试</string>
+    <string name="no_log">暂时没有日志</string>
+    <string name="no_directive">对不起,暂时没有收到指令</string>
+    <string name="no_audio">暂时没有歌曲了,请稍后再试</string>
+    <string name="open_file_title">选择浏览工具</string>
+    <string name="previous_audio">上一首</string>
+    <string name="next_audio">下一首</string>
+    <string name="open_log">打开日志</string>
+    <string name="login">登陆</string>
+    <string name="client_id">您应用的client_id</string>
+    <string name="client_id_empty">请输入您申请的client_id</string>
+    <string name="login_succeed">登陆成功</string>
+    <string name="wakeup_succeed">唤醒成功,您问点什么呢?</string>
+    <string name="wakeup_word">您可以说【小度小度】进行唤醒</string>
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/app/src/main/res/values/styles.xml	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,20 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+
+    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
+
+</resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/build.gradle	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:2.2.3'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/gradle.properties	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
Binary file dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/gradle/wrapper/gradle-wrapper.properties	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,6 @@
+#Mon Dec 28 10:00:20 PST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/gradlew	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/gradlew.bat	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
Binary file dcs-sdk-java-master/images/access-architecture.png has changed
Binary file dcs-sdk-java-master/images/client-id-secret.png has changed
Binary file dcs-sdk-java-master/images/login1.png has changed
Binary file dcs-sdk-java-master/images/login2.png has changed
Binary file dcs-sdk-java-master/images/modify-client-id.png has changed
Binary file dcs-sdk-java-master/images/project.png has changed
Binary file dcs-sdk-java-master/images/sdk-architecture.png has changed
Binary file dcs-sdk-java-master/images/wakeup.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcs-sdk-java-master/settings.gradle	Tue Jul 18 16:34:48 2017 +0800
@@ -0,0 +1,1 @@
+include ':app'