org.deviceconnect.android.deviceplugin.host.HostDeviceService.java Source code

Java tutorial

Introduction

Here is the source code for org.deviceconnect.android.deviceplugin.host.HostDeviceService.java

Source

/*
 HostDeviceService.java
 Copyright (c) 2014 NTT DOCOMO,INC.
 Released under the MIT license
 http://opensource.org/licenses/mit-license.php
 */
package org.deviceconnect.android.deviceplugin.host;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.http.conn.util.InetAddressUtils;
import org.deviceconnect.android.deviceplugin.host.manager.HostBatteryManager;
import org.deviceconnect.android.deviceplugin.host.profile.HostBatteryProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostConnectProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostDeviceOrientationProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostFileDescriptorProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostFileProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostMediaPlayerProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostMediaStreamingRecordingProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostNetworkServiceDiscoveryProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostNotificationProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostPhoneProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostProximityProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostSettingsProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostSystemProfile;
import org.deviceconnect.android.deviceplugin.host.profile.HostVibrationProfile;
import org.deviceconnect.android.deviceplugin.host.video.VideoConst;
import org.deviceconnect.android.deviceplugin.host.video.VideoPlayer;
import org.deviceconnect.android.event.Event;
import org.deviceconnect.android.event.EventManager;
import org.deviceconnect.android.event.cache.MemoryCacheController;
import org.deviceconnect.android.localoauth.LocalOAuth2Main;
import org.deviceconnect.android.message.DConnectMessageService;
import org.deviceconnect.android.message.MessageUtils;
import org.deviceconnect.android.profile.DeviceOrientationProfile;
import org.deviceconnect.android.profile.FileDescriptorProfile;
import org.deviceconnect.android.profile.MediaPlayerProfile;
import org.deviceconnect.android.profile.MediaStreamRecordingProfile;
import org.deviceconnect.android.profile.NetworkServiceDiscoveryProfile;
import org.deviceconnect.android.profile.SystemProfile;
import org.deviceconnect.android.provider.FileManager;
import org.deviceconnect.message.DConnectMessage;
import org.deviceconnect.message.intent.message.IntentDConnectMessage;
import org.deviceconnect.profile.FileDescriptorProfileConstants.Flag;
import org.deviceconnect.profile.MediaStreamRecordingProfileConstants;
import org.deviceconnect.profile.PhoneProfileConstants.CallState;

import android.app.ActivityManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.MediaStore;
import android.webkit.MimeTypeMap;

/**
 * Host Device Service.
 * 
 * @author NTT DOCOMO, INC.
 */
public class HostDeviceService extends DConnectMessageService implements SensorEventListener {

    /** onphoto. */
    private Map<String, Intent> mOnPhotoCallback = new HashMap<String, Intent>();

    /** ?ID. */
    private static final String DEVICE_ID = "android_camera";

    /** ondataavailable . */
    private Map<String, Intent> mOnDataAvailableCallback = new HashMap<String, Intent>();

    /** ?. */
    private FileManager mFileMgr;

    /** ????. */
    private static final String FILENAME_PREFIX = "android_camera_";

    /** ??. */
    private static final String FILE_EXTENSION = ".png";

    /** . */
    private static final int UNIQUE_ERROR_CODE = 101;

    /** ?. */
    private static final int BUFFER_SIZE = 1024;

    /** ?. */
    private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd_kkmmss", Locale.JAPAN);

    /** SensorManager. */
    private SensorManager mSensorManager;

    /** SensorManager. */
    private SensorManager mSensorManagerProximity;

    /** onClick Event. */
    private boolean onClickEventFlag = false;

    /** DeviceID. */
    private String mDeviceId;

    /** Service?List. */
    List<Bundle> services;

    /** . */
    private static final int COMPRESS_PERCENTAGE = 50;

    /** ?????. */
    private HostBatteryManager mHostBatteryManager;

    @Override
    public void onCreate() {

        super.onCreate();

        // EventManager??
        EventManager.INSTANCE.setController(new MemoryCacheController());

        // LocalOAuth??
        LocalOAuth2Main.initialize(getApplicationContext());

        // add supported profiles
        addProfile(new HostConnectProfile(BluetoothAdapter.getDefaultAdapter()));
        addProfile(new HostNotificationProfile());
        addProfile(new HostDeviceOrientationProfile());
        addProfile(new HostBatteryProfile());
        addProfile(new HostMediaStreamingRecordingProfile());
        addProfile(new HostPhoneProfile());
        addProfile(new HostSettingsProfile());
        addProfile(new HostMediaPlayerProfile());
        // ???
        mFileMgr = new FileManager(this);
        addProfile(new HostFileProfile(mFileMgr));
        addProfile(new HostFileDescriptorProfile());
        addProfile(new HostVibrationProfile());
        addProfile(new HostProximityProfile());

        // ???????
        mHostBatteryManager = new HostBatteryManager();
        mHostBatteryManager.getBatteryInfo(this.getContext());

    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {

        if (intent == null) {
            return START_STICKY;
        }

        String action = intent.getAction();

        if (Intent.ACTION_BATTERY_CHANGED.equals(action) || Intent.ACTION_BATTERY_LOW.equals(action)
                || Intent.ACTION_BATTERY_OKAY.equals(action)) {
            // ????

            mHostBatteryManager.setBatteryRequest(intent);

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, HostBatteryProfile.PROFILE_NAME,
                    null, HostBatteryProfile.ATTRIBUTE_ON_BATTERY_CHANGE);
            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent mIntent = EventManager.createEventMessage(event);

                HostBatteryProfile.setAttribute(mIntent, HostBatteryProfile.ATTRIBUTE_ON_BATTERY_CHANGE);
                Bundle battery = new Bundle();
                HostBatteryProfile.setLevel(battery, mHostBatteryManager.getBatteryLevel());
                getContext().sendBroadcast(mIntent);
            }

            return START_STICKY;
        } else if (Intent.ACTION_POWER_CONNECTED.equals(action)
                || Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
            // ????

            mHostBatteryManager.setBatteryRequest(intent);

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, HostBatteryProfile.PROFILE_NAME,
                    null, HostBatteryProfile.ATTRIBUTE_ON_CHARGING_CHANGE);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent mIntent = EventManager.createEventMessage(event);

                HostBatteryProfile.setAttribute(mIntent, HostBatteryProfile.ATTRIBUTE_ON_CHARGING_CHANGE);
                Bundle charging = new Bundle();

                if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
                    HostBatteryProfile.setCharging(charging, true);
                } else {
                    HostBatteryProfile.setCharging(charging, false);
                }

                HostBatteryProfile.setBattery(mIntent, charging);
                getContext().sendBroadcast(mIntent);
            }

            return START_STICKY;
        } else if (action.equals("android.intent.action.NEW_OUTGOING_CALL")) {
            // Phone

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, HostPhoneProfile.PROFILE_NAME, null,
                    HostPhoneProfile.ATTRIBUTE_ON_CONNECT);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent mIntent = EventManager.createEventMessage(event);

                HostPhoneProfile.setAttribute(mIntent, HostPhoneProfile.ATTRIBUTE_ON_CONNECT);
                Bundle phoneStatus = new Bundle();
                HostPhoneProfile.setPhoneNumber(phoneStatus, intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
                HostPhoneProfile.setState(phoneStatus, CallState.START);
                HostPhoneProfile.setPhoneStatus(mIntent, phoneStatus);
                getContext().sendBroadcast(mIntent);
            }

            return START_STICKY;
        } else if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)
                || WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
            // Wifi

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, HostConnectProfile.PROFILE_NAME,
                    null, HostConnectProfile.ATTRIBUTE_ON_WIFI_CHANGE);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent mIntent = EventManager.createEventMessage(event);

                HostConnectProfile.setAttribute(mIntent, HostConnectProfile.ATTRIBUTE_ON_WIFI_CHANGE);
                Bundle wifiConnecting = new Bundle();
                WifiManager wifiMgr = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
                HostConnectProfile.setEnable(wifiConnecting, wifiMgr.isWifiEnabled());
                HostConnectProfile.setConnectStatus(mIntent, wifiConnecting);
                getContext().sendBroadcast(mIntent);
            }

            return START_STICKY;

        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, HostConnectProfile.PROFILE_NAME,
                    null, HostConnectProfile.ATTRIBUTE_ON_BLUETOOTH_CHANGE);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent mIntent = EventManager.createEventMessage(event);

                HostConnectProfile.setAttribute(mIntent, HostConnectProfile.ATTRIBUTE_ON_BLUETOOTH_CHANGE);
                Bundle bluetoothConnecting = new Bundle();
                BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                HostConnectProfile.setEnable(bluetoothConnecting, mBluetoothAdapter.isEnabled());
                HostConnectProfile.setConnectStatus(mIntent, bluetoothConnecting);
                getContext().sendBroadcast(mIntent);
            }

            return START_STICKY;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected SystemProfile getSystemProfile() {
        return new HostSystemProfile(this);
    }

    @Override
    protected NetworkServiceDiscoveryProfile getNetworkServiceDiscoveryProfile() {
        return new HostNetworkServiceDiscoveryProfile();
    }

    /**
     * DeviceID.
     * 
     * @param deviceId ?ID
     */
    public void setDeviceId(final String deviceId) {
        this.mDeviceId = deviceId;
    }

    /**
     * Battery Profile<br>
     * ??.
     * 
     * @return ?
     */
    public int getBatteryLevel() {
        mHostBatteryManager.getBatteryInfo(this.getContext());
        return mHostBatteryManager.getBatteryLevel();
    }

    /**
     * Battery Profile<br>
     * ??.
     * 
     * @return ?
     */
    public int getBatteryStatus() {
        mHostBatteryManager.getBatteryInfo(this.getContext());
        return mHostBatteryManager.getBatteryStatus();
    }

    /**
     * Battery Profile<br>
     * ??.
     * 
     * @return ?
     */
    public int getBatteryScale() {
        mHostBatteryManager.getBatteryInfo(this.getContext());
        return mHostBatteryManager.getBatteryScale();
    }

    //
    // Device Orientation Profile
    //
    /**  x. */
    private static float mAccellX;

    /**  y. */
    private static float mAccellY;

    /**  z. */
    private static float mAccellZ;

    /** Gyro x. */
    private static float mGyroX;

    /** Gyro y. */
    private static float mGyroY;

    /** Gyro z. */
    private static float mGyroZ;

    /** ??. */
    private static final int INTERVAL_TIME = 200;

    /**
     * Device Orientation Profile<br>
     * ?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void registerDeviceOrientationEvent(final Intent response, final String deviceId,
            final String sessionKey) {

        mDeviceId = deviceId;
        mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);

        if (sensors.size() > 0) {
            Sensor sensor = sensors.get(0);
            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
        }

        sensors = mSensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);

        if (sensors.size() > 0) {
            Sensor sensor = sensors.get(0);
            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
        }

        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register OnDeviceOrientation event");
        sendBroadcast(response);
    }

    /**
     * Promity Profile<br>
     * ?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void registerPromityEvent(final Intent response, final String deviceId, final String sessionKey) {

        mDeviceId = deviceId;
        mSensorManagerProximity = (SensorManager) getSystemService(SENSOR_SERVICE);
        List<Sensor> sensors = mSensorManagerProximity.getSensorList(Sensor.TYPE_PROXIMITY);

        if (sensors.size() > 0) {
            Sensor sensor = sensors.get(0);
            mSensorManagerProximity.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
        }

        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register onuserproximity event");
        sendBroadcast(response);
    }

    /**
     * Promity Profile<br>
     * ?.
     * 
     * @param response ?
     */
    public void unregisterPromityEvent(final Intent response) {
        mSensorManagerProximity.unregisterListener(this);
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister onuserproximity event");
        sendBroadcast(response);
    }

    /**
     * Device Orientation Profile<br>
     * ?.
     * 
     * @param response ?
     */
    public void unregisterDeviceOrientationEvent(final Intent response) {
        mSensorManager.unregisterListener(this);
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister OnDeviceOrientation event");
        sendBroadcast(response);
    }

    /**
     * ????????.
     * 
     * @param sensorEvent .
     */
    public void onSensorChanged(final SensorEvent sensorEvent) {
        if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {

            mAccellX = sensorEvent.values[0];
            mAccellY = sensorEvent.values[1];
            mAccellZ = sensorEvent.values[2];

            Bundle orientation = new Bundle();
            Bundle a1 = new Bundle();
            a1.putDouble(DeviceOrientationProfile.PARAM_X, 0.0);
            a1.putDouble(DeviceOrientationProfile.PARAM_Y, 0.0);
            a1.putDouble(DeviceOrientationProfile.PARAM_Z, 0.0);
            Bundle a2 = new Bundle();
            a2.putDouble(DeviceOrientationProfile.PARAM_X, mAccellX);
            a2.putDouble(DeviceOrientationProfile.PARAM_Y, mAccellY);
            a2.putDouble(DeviceOrientationProfile.PARAM_Z, mAccellZ);
            Bundle r = new Bundle();
            r.putDouble(DeviceOrientationProfile.PARAM_ALPHA, mGyroX);
            r.putDouble(DeviceOrientationProfile.PARAM_BETA, mGyroY);
            r.putDouble(DeviceOrientationProfile.PARAM_GAMMA, mGyroZ);
            orientation.putBundle(DeviceOrientationProfile.PARAM_ACCELERATION, a1);
            orientation.putBundle(DeviceOrientationProfile.PARAM_ACCELERATION_INCLUDING_GRAVITY, a2);
            orientation.putBundle(DeviceOrientationProfile.PARAM_ROTATION_RATE, r);
            orientation.putLong(DeviceOrientationProfile.PARAM_INTERVAL, 0);
            DeviceOrientationProfile.setInterval(orientation, INTERVAL_TIME);

            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId,
                    DeviceOrientationProfile.PROFILE_NAME, null,
                    DeviceOrientationProfile.ATTRIBUTE_ON_DEVICE_ORIENTATION);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent intent = EventManager.createEventMessage(event);

                intent.putExtra(DeviceOrientationProfile.PARAM_ORIENTATION, orientation);
                getContext().sendBroadcast(intent);
            }

        } else if (sensorEvent.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
            mGyroX = sensorEvent.values[0];
            mGyroY = sensorEvent.values[1];
            mGyroZ = sensorEvent.values[2];
        }
    }

    //
    // File Descriptor Profile
    //

    /** File Output Stream. */
    private static FileOutputStream mFos = null;

    /** File Input Stream. */
    private static FileInputStream mFis = null;

    /**
     * File??????Flag.<br>
     * ???:true, ?????: false
     */
    private Boolean mFileOpenFlag = false;

    /** File????. */
    private String mFileName = "";

    /** Event?Flag. */
    private boolean onWatchfileEventFlag = false;

    /**
     * ??.<br>
     * ???open, write, read???
     */
    private long mFileDescriptorCurrentSystemTime;

    /** ??. */
    private String mFileDescriptorCurrentTime = "";

    /** FileDescriptor?????Path. */
    private String mFileDescriptorPath = "";

    /** FileDescripor?DeviceId. */
    private String mFileDescriptorDeviceId = "";

    /** File mode. */
    private Flag mFlag = null;

    /** ?(1). */
    private static final int AVAILABLE_REWRITE_TIME = 60000;

    /**
     * ??????.
     * 
     * @return ????true
     */
    private boolean checkUpdate() {
        return System.currentTimeMillis() - mFileDescriptorCurrentSystemTime > AVAILABLE_REWRITE_TIME;
    }

    /**
     * ??.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param path 
     * @param flag ?????????
     */
    public void openFile(final Intent response, final String deviceId, final String path, final Flag flag) {

        if (!mFileOpenFlag || checkUpdate()) {
            try {
                mFileDescriptorCurrentSystemTime = System.currentTimeMillis();
                mFileOpenFlag = true;
                File mBaseDir = mFileMgr.getBasePath();
                mFileDescriptorPath = path;
                if (!mFileDescriptorPath.startsWith("/")) {
                    mFileDescriptorPath = "/" + path;
                }

                mFos = new FileOutputStream(new File(mBaseDir + mFileDescriptorPath), true);
                mFis = new FileInputStream(new File(mBaseDir + mFileDescriptorPath));

                mFlag = flag;
                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                response.putExtra(DConnectMessage.EXTRA_VALUE,
                        "Open file:" + Environment.getExternalStorageDirectory() + path);
                sendBroadcast(response);

                mFileName = path;
            } catch (FileNotFoundException e) {
                mFileOpenFlag = false;
                MessageUtils.setUnknownError(response, "Can not open file:" + path + ":" + e);
                sendBroadcast(response);

                mFileName = "";
            }
        } else {
            MessageUtils.setError(response, UNIQUE_ERROR_CODE, "Opening another file");
            sendBroadcast(response);
            if (mFos != null) {
                try {
                    mFos.close();
                } catch (IOException e) {
                    if (BuildConfig.DEBUG) {
                        e.printStackTrace();
                    }
                }
                mFos = null;
            }
            if (mFis != null) {
                try {
                    mFis.close();
                } catch (IOException e) {
                    if (BuildConfig.DEBUG) {
                        e.printStackTrace();
                    }
                }
                mFis = null;
            }
        }
    }

    /**
     * ?????.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param path 
     * @param data 
     * @param position ????
     */
    public void writeDataToFile(final Intent response, final String deviceId, final String path, final byte[] data,
            final Long position) {
        int pos = 0;
        if (position != null) {
            pos = (int) position.longValue();
        }
        if (pos < 0 || data.length < pos) {
            MessageUtils.setInvalidRequestParameterError(response, "invalid position");
            sendBroadcast(response);
            return;
        }
        if (mFileOpenFlag && mFileName.equals(path)) {
            try {
                if (mFlag.equals(Flag.RW)) {
                    // ???
                    mFileDescriptorCurrentSystemTime = System.currentTimeMillis();
                    Date date = new Date();
                    SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy'-'MM'-'dd' 'kk':'mm':'ss'+0900'");
                    mFileDescriptorCurrentTime = mDateFormat.format(date);
                    mFos.write(data, pos, data.length - pos);
                    response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                    response.putExtra(DConnectMessage.EXTRA_VALUE, "Write data:" + path);
                    sendBroadcast(response);
                    sendFileDescriptorOnWatchfileEvent();
                } else {
                    MessageUtils.setIllegalDeviceStateError(response, "Read mode only");
                    sendBroadcast(response);
                }

            } catch (Exception e) {
                MessageUtils.setUnknownError(response, "Can not write data:" + path + e);
                sendBroadcast(response);
            }
        } else {
            response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_ERROR);
            response.putExtra(DConnectMessage.EXTRA_VALUE, "Can not write data:" + path);
            sendBroadcast(response);
        }
    }

    /**
     * File Descriptor Profile<br>
     * .
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param path 
     * @param position ????
     * @param length ?
     */
    public void readFile(final Intent response, final String deviceId, final String path, final long position,
            final long length) {
        if (position < 0) {
            MessageUtils.setInvalidRequestParameterError(response, "invalid position");
            sendBroadcast(response);
            return;
        }

        File mBaseDir = mFileMgr.getBasePath();
        if (mFileOpenFlag && mFileName.equals(path)) {
            try {
                mFileDescriptorCurrentSystemTime = System.currentTimeMillis();
                StringBuffer fileContent = new StringBuffer("");
                byte[] buffer = new byte[BUFFER_SIZE];
                int nCount = 0;
                String paths = path;
                if (!path.startsWith("/")) {
                    paths = "/" + path;
                }
                FileInputStream fis = new FileInputStream(mBaseDir + paths);
                while (((fis.read(buffer, 0, 1)) != -1) && nCount < position + length) {
                    if (nCount >= position) {
                        fileContent.append(new String(buffer, 0, 1));
                    }
                    nCount++;
                }
                fis.close();

                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                response.putExtra(FileDescriptorProfile.PARAM_SIZE, length);
                response.putExtra(FileDescriptorProfile.PARAM_FILE_DATA, fileContent.toString());
                sendBroadcast(response);

            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }
            }
        } else {
            MessageUtils.setUnknownError(response, "Can not read data:" + path);
            sendBroadcast(response);
        }
    }

    /**
     * File?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param path 
     */
    public void closeFile(final Intent response, final String deviceId, final String path) {

        // fileName???????
        if (mFileOpenFlag && mFileName.equals(path)) {
            try {
                mFileDescriptorCurrentSystemTime = 0;
                mFos.close();
                mFileOpenFlag = false;

                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                response.putExtra(DConnectMessage.EXTRA_VALUE, "Close file:" + path);
                sendBroadcast(response);
                mFileName = "";

            } catch (IOException e) {
                mFileOpenFlag = false;
                MessageUtils.setUnknownError(response, "Can not close file:" + path + e);
                sendBroadcast(response);
            }
        } else {
            mFileOpenFlag = false;
            MessageUtils.setUnknownError(response, "Can not close file:" + path);
            sendBroadcast(response);
        }
    }

    /**
     * OnWatchFileEvent?.
     * 
     * @param deviceId ?ID
     */
    public void registerFileDescriptorOnWatchfileEvent(final String deviceId) {
        onWatchfileEventFlag = true;
        mFileDescriptorDeviceId = deviceId;
    }

    /**
     * OnWatchFileEvent?.
     */
    public void unregisterFileDescriptorOnWatchfileEvent() {
        onWatchfileEventFlag = false;
    }

    /**
     * ?.
     */
    public void sendFileDescriptorOnWatchfileEvent() {
        if (onWatchfileEventFlag) {
            List<Event> events = EventManager.INSTANCE.getEventList(mFileDescriptorDeviceId,
                    HostFileDescriptorProfile.PROFILE_NAME, null,
                    HostFileDescriptorProfile.ATTRIBUTE_ON_WATCH_FILE);

            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                Intent intent = EventManager.createEventMessage(event);

                HostFileDescriptorProfile.setAttribute(intent, FileDescriptorProfile.ATTRIBUTE_ON_WATCH_FILE);
                Bundle fileDescriptor = new Bundle();
                FileDescriptorProfile.setPath(fileDescriptor, mFileDescriptorPath);
                FileDescriptorProfile.setCurr(fileDescriptor, mFileDescriptorCurrentTime);
                FileDescriptorProfile.setPrev(fileDescriptor, "");
                intent.putExtra(FileDescriptorProfile.PARAM_FILE_DATA, fileDescriptor);
                intent.putExtra(FileDescriptorProfile.PARAM_PROFILE, FileDescriptorProfile.PROFILE_NAME);
                getContext().sendBroadcast(intent);
            }
        }
    }

    /**
     * ondataavailable?.
     * 
     * @param request 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     * @return ?????true????false
     */
    public boolean onPutOnDataAvailable(final Intent request, final Intent response, final String deviceId,
            final String sessionKey) {

        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        if (deviceId == null || !deviceId.equals(DEVICE_ID)) {
            MessageUtils.setEmptyDeviceIdError(response);
        } else if (sessionKey == null) {
            MessageUtils.setInvalidRequestParameterError(response, "There is no sessionKey.");
        } else {
            if (mOnDataAvailableCallback.containsKey(sessionKey)) {
                MessageUtils.setInvalidRequestParameterError(response, "There is no sessionKey.");
            } else {
                mOnDataAvailableCallback.put(sessionKey, request);
            }
        }

        return true;
    }

    /**
     * ondataavailable?.
     * 
     * @param request 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     * @return ?????true????false
     */
    public boolean onDeleteOnDataAvailable(final Intent request, final Intent response, final String deviceId,
            final String sessionKey) {
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);

        if (deviceId == null || !deviceId.equals(DEVICE_ID)) {
            MessageUtils.setEmptyDeviceIdError(response);
        } else if (sessionKey == null) {
            MessageUtils.setInvalidRequestParameterError(response, "There is no sessionKey.");
        } else {
            if (mOnDataAvailableCallback.containsKey(sessionKey)) {
                mOnDataAvailableCallback.remove(sessionKey);
            } else {
                MessageUtils.setInvalidRequestParameterError(response, "There is no sessionKey.");
            }
        }

        return true;
    }

    /**
     * ???.
     * 
     * @param data ?????byte.
     * @return ??URI
     * @throws IOException ?????????????
     */
    public String savePhoto(final byte[] data) throws IOException {

        String filename = FILENAME_PREFIX + mSimpleDateFormat.format(new Date()) + FILE_EXTENSION;
        mFileMgr.saveFile(filename, data);

        return filename;
    }

    /**
     * ?.
     * 
     * @param mediaid ID
     */
    public void notifyTakePhoto(final String mediaid) {

        for (String key : mOnPhotoCallback.keySet()) {
            Intent response = mOnPhotoCallback.get(key);
            ComponentName receiver = (ComponentName) response.getParcelableExtra("receiver");

            Bundle photo = new Bundle();
            photo.putString("mediaid", mediaid);
            photo.putString("mimetype", "image/png");

            Intent intent = new Intent();
            intent.setAction(IntentDConnectMessage.ACTION_EVENT);
            intent.setComponent(receiver);
            intent.putExtra("deviceid", "me");
            intent.putExtra("profile", "mediastream_recording");
            intent.putExtra("callback", "onphoto");
            intent.putExtra("session_key", key);
            intent.putExtra("photo", photo);

            sendBroadcast(intent);
        }
    }

    /**
     * onClickEvent?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void registerOnClick(final Intent response, final String deviceId, final String sessionKey) {
        onClickEventFlag = true;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register onClick event");
        sendBroadcast(response);
    }

    /**
     * onClickEvent?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void unregisterOnClick(final Intent response, final String deviceId, final String sessionKey) {
        onClickEventFlag = false;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister onClick event");
        sendBroadcast(response);
    }

    /**
     * OnClickEvent??.
     * 
     * @return 
     */
    public boolean getOnClickEventFlag() {
        return onClickEventFlag;
    }

    // ----------------------------------------------
    // MediaPlayer Profile
    // ----------------------------------------------
    /** MediaPlayer?. */
    private static MediaPlayer mMediaPlayer;
    /** Media?. */
    private static int mMediaStatus = 0;
    /** Media?. */
    private static final int MEDIA_PLAYER_NODATA = 0;
    /** Media?. */
    private static final int MEDIA_PLAYER_SET = 1;
    /** Media??. */
    private static final int MEDIA_PLAYER_PLAY = 2;
    /** Media??. */
    private static final int MEDIA_PLAYER_PAUSE = 3;
    /** Media??. */
    private static final int MEDIA_PLAYER_STOP = 4;
    /** MEDIA(). */
    private static final int MEDIA_TYPE_VIDEO = 1;
    /** MEDIA(). */
    private static final int MEDIA_TYPE_MUSIC = 2;
    //    /** MEDIA(). */
    //    private static final int MEDIA_TYPE_AUDIO = 3;
    /** Media Status. */
    private static int mSetMediaType = 0;
    /** onStatusChange Event?. */
    private static boolean onStatusChangeEventFlag = false;
    /** ???. */
    private static String myCurrentFilePath = "";
    /** ???. */
    private static String myCurrentFileMIMEType = "";
    /** ???Position. */
    private int myCurrentMediaPosition = 0;
    /** Current MediaID. */
    private String mCurrentMediaId;

    /**
     * ???(Id?).
     * 
     * @param response ?
     * @param mediaId MediaID
     */
    public void putMediaId(final Intent response, final String mediaId) {
        mCurrentMediaId = mediaId;

        // Video????
        Uri mUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, Long.valueOf(mediaId));

        String filePath = getPathFromUri(mUri);

        // null??Audio????
        if (filePath == null) {
            mUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, Long.valueOf(mediaId));
            filePath = getPathFromUri(mUri);
        }

        String mMineType = getMIMEType(filePath);

        // ??
        if ("audio/mpeg".equals(mMineType) || "audio/x-wav".equals(mMineType) || "application/ogg".equals(mMineType)
                || "audio/x-ms-wma".equals(mMineType) || "audio/mp3".equals(mMineType)
                || "audio/ogg".equals(mMineType) || "audio/mp4".equals(mMineType)) {
            mMediaPlayer = new MediaPlayer();

            try {
                mSetMediaType = MEDIA_TYPE_MUSIC;
                myCurrentFilePath = filePath;
                myCurrentFileMIMEType = mMineType;
                mMediaStatus = MEDIA_PLAYER_SET;
                mMediaPlayer.setDataSource(filePath);
                mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
                    @Override
                    public void onCompletion(final MediaPlayer arg0) {
                        mMediaStatus = MEDIA_PLAYER_STOP;
                        sendOnStatusChangeEvent("stop");
                    }
                });
                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                response.putExtra(DConnectMessage.EXTRA_VALUE, "regist:" + filePath);
                sendOnStatusChangeEvent("media");
                sendBroadcast(response);
            } catch (IOException e) {
                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.EXTRA_ERROR_CODE);
                response.putExtra(DConnectMessage.EXTRA_VALUE, "can't not regist:" + filePath);
                sendBroadcast(response);
            }
        } else if ("video/3gpp".equals(mMineType) || "video/mp4".equals(mMineType) || "video/m4v".equals(mMineType)
                || "video/3gpp2".equals(mMineType) || "video/mpeg".equals(mMineType)) {

            try {

                mSetMediaType = MEDIA_TYPE_VIDEO;
                myCurrentFilePath = filePath;
                myCurrentFileMIMEType = mMineType;

                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
                response.putExtra(DConnectMessage.EXTRA_VALUE, "regist:" + filePath);
                sendOnStatusChangeEvent("media");
                sendBroadcast(response);
            } catch (Exception e) {
                response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.EXTRA_ERROR_CODE);
                response.putExtra(DConnectMessage.EXTRA_VALUE, "can't not mount:" + filePath);
                sendBroadcast(response);
            }
        } else {
            response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.EXTRA_ERROR_CODE);
            response.putExtra(DConnectMessage.EXTRA_VALUE, "can't not open:" + filePath);
            sendBroadcast(response);
        }
    }

    /**
     * onStatusChange Event?.
     * 
     * @param response ?
     * @param deviceId ?ID
     */
    public void registerOnStatusChange(final Intent response, final String deviceId) {
        mDeviceId = deviceId;
        onStatusChangeEventFlag = true;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register OnStatusChange event");
        sendBroadcast(response);
    }

    /**
     * onStatusChange Event?.
     * 
     * @param response ?
     */
    public void unregisterOnStatusChange(final Intent response) {
        onStatusChangeEventFlag = false;
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister OnStatusChange event");
        sendBroadcast(response);
    }

    /**
     * ?.
     * 
     * @param status 
     */
    public void sendOnStatusChangeEvent(final String status) {

        if (onStatusChangeEventFlag) {
            List<Event> events = EventManager.INSTANCE.getEventList(mDeviceId, MediaPlayerProfile.PROFILE_NAME,
                    null, MediaPlayerProfile.ATTRIBUTE_ON_STATUS_CHANGE);

            AudioManager manager = (AudioManager) this.getContext().getSystemService(Context.AUDIO_SERVICE);

            double maxVolume = 1;
            double mVolume = 0;

            mVolume = manager.getStreamVolume(AudioManager.STREAM_MUSIC);
            maxVolume = manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);

            double mVolumeValue = mVolume / maxVolume;

            for (int i = 0; i < events.size(); i++) {

                Event event = events.get(i);
                Intent intent = EventManager.createEventMessage(event);

                MediaPlayerProfile.setAttribute(intent, MediaPlayerProfile.ATTRIBUTE_ON_STATUS_CHANGE);
                Bundle mediaPlayer = new Bundle();
                MediaPlayerProfile.setStatus(mediaPlayer, status);
                MediaPlayerProfile.setMediaId(mediaPlayer, myCurrentFilePath);
                MediaPlayerProfile.setMIMEType(mediaPlayer, myCurrentFileMIMEType);
                MediaPlayerProfile.setPos(mediaPlayer, myCurrentMediaPosition);
                MediaPlayerProfile.setVolume(mediaPlayer, mVolumeValue);
                MediaPlayerProfile.setMediaPlayer(intent, mediaPlayer);
                getContext().sendBroadcast(intent);
            }
        }
    }

    /**
     * URI??.
     * 
     * @param mUri URI
     * @return 
     */
    private String getPathFromUri(final Uri mUri) {
        try {
            Cursor c = getContentResolver().query(mUri, null, null, null, null);
            c.moveToFirst();
            String filename = c.getString(c.getColumnIndex(MediaStore.MediaColumns.DATA));

            return filename;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Media???.
     * 
     * @return SessionID
     */
    public int resumeMedia() {
        if (mSetMediaType == MEDIA_TYPE_MUSIC) {
            try {
                mMediaStatus = MEDIA_PLAYER_PLAY;
                mMediaPlayer.prepare();
                mMediaPlayer.start();
            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }
            }
            sendOnStatusChangeEvent("play");
            return mMediaPlayer.getAudioSessionId();
        } else if (mSetMediaType == MEDIA_TYPE_VIDEO) {
            playMedia();
            return 0;
        }
        return 0;
    }

    /**
     * ??.
     * 
     * @return ID
     */
    public int playMedia() {
        if (mSetMediaType == MEDIA_TYPE_MUSIC) {
            try {
                mMediaPlayer.prepare();
                if (mMediaStatus == MEDIA_PLAYER_STOP) {
                    mMediaPlayer.seekTo(0);
                }
                mMediaPlayer.start();
                mMediaStatus = MEDIA_PLAYER_PLAY;
            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }
            }
            sendOnStatusChangeEvent("play");
            return mMediaPlayer.getAudioSessionId();
        } else if (mSetMediaType == MEDIA_TYPE_VIDEO) {
            String className = getClassnameOfTopActivity();

            if (VideoPlayer.class.getName().equals(className)) {
                mMediaStatus = MEDIA_PLAYER_PLAY;
                Intent mIntent = new Intent(VideoConst.SEND_HOSTDP_TO_VIDEOPLAYER);
                mIntent.putExtra(VideoConst.EXTRA_NAME, VideoConst.EXTRA_VALUE_VIDEO_PLAYER_PLAY);
                this.getContext().sendBroadcast(mIntent);
                sendOnStatusChangeEvent("play");

            } else {
                mMediaStatus = MEDIA_PLAYER_PLAY;
                Intent mIntent = new Intent(VideoConst.SEND_HOSTDP_TO_VIDEOPLAYER);
                mIntent.setClass(getContext(), VideoPlayer.class);
                Uri data = Uri.parse(myCurrentFilePath);
                mIntent.setDataAndType(data, myCurrentFileMIMEType);
                mIntent.putExtra(VideoConst.EXTRA_NAME, VideoConst.EXTRA_VALUE_VIDEO_PLAYER_PLAY);
                mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(mIntent);
                sendOnStatusChangeEvent("play");

            }

            return 0;
        } else {
            return 0;
        }
    }

    /**
     * ??.
     * 
     * @return ID
     */
    public int pauseMedia() {
        if (mSetMediaType == MEDIA_TYPE_MUSIC) {
            try {
                mMediaStatus = MEDIA_PLAYER_PAUSE;
                mMediaPlayer.stop();

            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }
            }
            sendOnStatusChangeEvent("pause");
            return mMediaPlayer.getAudioSessionId();

        } else if (mSetMediaType == MEDIA_TYPE_VIDEO) {
            mMediaStatus = MEDIA_PLAYER_PAUSE;
            Intent mIntent = new Intent(VideoConst.SEND_HOSTDP_TO_VIDEOPLAYER);
            mIntent.putExtra(VideoConst.EXTRA_NAME, VideoConst.EXTRA_VALUE_VIDEO_PLAYER_PAUSE);
            this.getContext().sendBroadcast(mIntent);
            sendOnStatusChangeEvent("pause");
            return 0;
        } else {
            return 0;
        }
    }

    /**
     * ??.
     * 
     * @return ???
     */
    public int getMediaPos() {
        // ToDo 
        return mMediaPlayer.getCurrentPosition();
    }

    /**
     * ??.
     * 
     * @param response ?
     * @param pos ?
     */
    public void setMediaPos(final Intent response, final int pos) {
        if (mSetMediaType == MEDIA_TYPE_MUSIC) {
            mMediaPlayer.seekTo(pos);
            myCurrentMediaPosition = pos;
        } else {
            mMediaStatus = MEDIA_PLAYER_PAUSE;
            Intent mIntent = new Intent(VideoConst.SEND_HOSTDP_TO_VIDEOPLAYER);
            mIntent.putExtra(VideoConst.EXTRA_NAME, VideoConst.EXTRA_VALUE_VIDEO_PLAYER_SEEK);
            mIntent.putExtra("pos", pos);
            this.getContext().sendBroadcast(mIntent);
            myCurrentMediaPosition = pos;
        }
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        sendBroadcast(response);
        sendOnStatusChangeEvent("seek");
    }

    /**
     * ??.
     */
    public void stopMedia() {
        if (mSetMediaType == MEDIA_TYPE_MUSIC) {
            try {
                mMediaPlayer.stop();
                mMediaStatus = MEDIA_PLAYER_STOP;
                sendOnStatusChangeEvent("stop");
            } catch (Exception e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }
            }
        } else if (mSetMediaType == MEDIA_TYPE_VIDEO) {
            mMediaStatus = MEDIA_PLAYER_PAUSE;
            Intent mIntent = new Intent(VideoConst.SEND_HOSTDP_TO_VIDEOPLAYER);
            mIntent.putExtra(VideoConst.EXTRA_NAME, VideoConst.EXTRA_VALUE_VIDEO_PLAYER_STOP);
            this.getContext().sendBroadcast(mIntent);
            sendOnStatusChangeEvent("stop");
        }
    }

    /**
     * Play Status.
     * 
     * @param response ?
     */
    public void getPlayStatus(final Intent response) {
        String mClassName = getClassnameOfTopActivity();

        // VideoRecorder??????????m
        if (mSetMediaType == MEDIA_TYPE_VIDEO) {
            response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);

            if (!VideoPlayer.class.getName().equals(mClassName)) {
                mMediaStatus = MEDIA_PLAYER_STOP;
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "stop");
            } else {
                if (mMediaStatus == MEDIA_PLAYER_STOP) {
                    response.putExtra(MediaPlayerProfile.PARAM_STATUS, "stop");
                } else if (mMediaStatus == MEDIA_PLAYER_PLAY) {
                    response.putExtra(MediaPlayerProfile.PARAM_STATUS, "play");
                } else if (mMediaStatus == MEDIA_PLAYER_PAUSE) {
                    response.putExtra(MediaPlayerProfile.PARAM_STATUS, "pause");
                } else if (mMediaStatus == MEDIA_PLAYER_NODATA) {
                    response.putExtra(MediaPlayerProfile.PARAM_STATUS, "no data");
                } else {
                    response.putExtra(MediaPlayerProfile.PARAM_STATUS, "stop");
                }
            }

            sendBroadcast(response);

        } else {
            response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
            if (mMediaStatus == MEDIA_PLAYER_STOP) {
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "stop");
            } else if (mMediaStatus == MEDIA_PLAYER_PLAY) {
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "play");
            } else if (mMediaStatus == MEDIA_PLAYER_PAUSE) {
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "pause");
            } else if (mMediaStatus == MEDIA_PLAYER_NODATA) {
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "no data");
            } else {
                response.putExtra(MediaPlayerProfile.PARAM_STATUS, "stop");
            }

            sendBroadcast(response);
        }
    }

    /**
     * Media??.
     * 
     * @param response ?
     */
    public void getMedia(final Intent response) {
        int pos = mMediaPlayer.getCurrentPosition();
        int duration = mMediaPlayer.getDuration();

        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(MediaPlayerProfile.PARAM_MEDIA_ID, mCurrentMediaId);
        response.putExtra(MediaPlayerProfile.PARAM_DURATION, duration);
        response.putExtra(MediaPlayerProfile.PARAM_DURATION, pos);
        response.putExtra(MediaPlayerProfile.PARAM_STATUS, mMediaStatus);

        sendBroadcast(response);
    }

    // ================================
    // MediaStream_Recording
    // ================================

    /** . */
    private int count = 0;

    /** ?. */
    private static final int MAX_PREVIEW = 10;

    /**
     * DeviceID.
     * 
     * @param deviceId ?ID
     */
    public void registerDeviceId(final String deviceId) {
        this.mDeviceId = deviceId;
    }

    /**
     * Camera???.
     */
    private IHostMediaStreamRecordingService.Stub mCameraService = new IHostMediaStreamRecordingService.Stub() {

        @Override
        public void sendPreviewData(final byte[] data, final int format, final int width, final int height) {

            List<Event> evts = EventManager.INSTANCE.getEventList(mDeviceId,
                    MediaStreamRecordingProfileConstants.PROFILE_NAME, null,
                    MediaStreamRecordingProfileConstants.ATTRIBUTE_ON_DATA_AVAILABLE);

            if (evts.size() > 0) {

                YuvImage yuvimage = new YuvImage(data, format, width, height, null);

                Rect rect = new Rect(0, 0, width, height);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                yuvimage.compressToJpeg(rect, COMPRESS_PERCENTAGE, baos);
                byte[] jdata = baos.toByteArray();

                String mediaId = "preview" + count + ".jpg";
                String uri;
                try {
                    uri = mFileMgr.saveFile(mediaId, jdata);
                    notifyDataAvailable(mediaId, uri);

                    count++;
                    count %= MAX_PREVIEW;
                } catch (IOException e) {
                    if (BuildConfig.DEBUG) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    /**
     * mDNS?.
     * 
     */
    public void searchDeviceByBonjour() {

        // cache?false????
        // ?,???????, Wifi?Broadcast????
        new Thread(new Runnable() {
            public void run() {

                services = new ArrayList<Bundle>();

                android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(
                        android.content.Context.WIFI_SERVICE);
                WifiManager.MulticastLock lock = wifi.createMulticastLock("deviceplugin.host");
                lock.setReferenceCounted(true);
                lock.acquire();
            }
        }).start();

    }

    /**
     * mDNS??????.
     * 
     */
    public void invokeDeviceByBonjour() {

        // cache?false????
        // ?,???????, Wifi?Broadcast????
        new Thread(new Runnable() {
            public void run() {

                services = new ArrayList<Bundle>();

                android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) getSystemService(
                        android.content.Context.WIFI_SERVICE);
                WifiManager.MulticastLock lock = wifi.createMulticastLock("deviceplugin.host");
                lock.setReferenceCounted(true);
                lock.acquire();
            }
        }).start();

    }

    /**
     * ?IP?.
     * 
     * @return ?IP
     */
    public String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en
                    .hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()
                            && InetAddressUtils.isIPv4Address(inetAddress.getHostAddress())) {

                        String ipAddr = inetAddress.getHostAddress();
                        return ipAddr;
                    }
                }
            }
        } catch (Exception e) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace();
            }
        }
        return null;
    }

    @Override
    public void onAccuracyChanged(final Sensor sensor, final int accuracy) {

    }

    @Override
    public IBinder onBind(final Intent intent) {

        if ("camera".equals(intent.getAction())) {

            return mCameraService;
        } else {

            return mStub;
        }
    }

    /**
     * Host Device Plugin?.
     */
    private IHostDeviceService.Stub mStub = new IHostDeviceService.Stub() {

        @Override
        public void registerCallback(final IHostDeviceCallback callback) throws RemoteException {
        }

        @Override
        public void unregisterCallback(final IHostDeviceCallback callback) throws RemoteException {
        }

        @Override
        public void searchHost() throws RemoteException {
            searchDeviceByBonjour();
        }

        @Override
        public int getHostStatus() throws RemoteException {
            return 0;
        }

        @Override
        public void invokeHost() throws RemoteException {
            invokeDeviceByBonjour();
        }

    };

    /**
     * onClick?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void registerOnConnect(final Intent response, final String deviceId, final String sessionKey) {
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Register onClick event");
        sendBroadcast(response);
    }

    /**
     * onClick?.
     * 
     * @param response ?
     * @param deviceId ?ID
     * @param sessionKey 
     */
    public void unregisterOnConnect(final Intent response, final String deviceId, final String sessionKey) {
        response.putExtra(DConnectMessage.EXTRA_RESULT, DConnectMessage.RESULT_OK);
        response.putExtra(DConnectMessage.EXTRA_VALUE, "Unregister onClick event");
        sendBroadcast(response);
    }

    /**
     * 3GP??Video?Audio??.
     * 
     * @param mFile ???URI
     * @return Video?true, audio?false
     */
    public static boolean checkVideo(final File mFile) {
        int height = 0;
        try {
            mMediaPlayer = new MediaPlayer();
            FileInputStream fis = null;
            FileDescriptor mFd = null;

            fis = new FileInputStream(mFile);
            mFd = fis.getFD();

            mMediaPlayer.setDataSource(mFd);
            mMediaPlayer.prepare();
            height = mMediaPlayer.getVideoHeight();
            mMediaPlayer.release();
            fis.close();
        } catch (Exception e) {
            if (BuildConfig.DEBUG) {
                e.printStackTrace();
            }
        }

        return height > 0;
    }

    /**
     * ?MIME Type?.
     * 
     * @param path 
     * @return MineType
     */
    public String getMIMEType(final String path) {

        // , , ??String?
        String mFilename = new File(path).getName();
        int dotPos = mFilename.lastIndexOf(".");
        String mFormat = mFilename.substring(dotPos, mFilename.length());

        // ??
        String mExt = MimeTypeMap.getFileExtensionFromUrl(mFormat);
        // ???
        mExt = mExt.toLowerCase();
        // MIME Type?
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(mExt);
    }

    /**
     * .
     * 
     * @param mediaId ID
     * @param uri ??URI
     */
    public void notifyDataAvailable(final String mediaId, final String uri) {
        List<Event> evts = EventManager.INSTANCE.getEventList(mDeviceId,
                MediaStreamRecordingProfileConstants.PROFILE_NAME, null,
                MediaStreamRecordingProfileConstants.ATTRIBUTE_ON_DATA_AVAILABLE);
        for (Event evt : evts) {
            Bundle media = new Bundle();
            media.putString(MediaStreamRecordingProfile.PARAM_PATH, mediaId);
            media.putString(MediaStreamRecordingProfile.PARAM_URI, uri);
            media.putString(MediaStreamRecordingProfile.PARAM_MIME_TYPE, "image/jpg");

            Intent intent = new Intent(IntentDConnectMessage.ACTION_EVENT);
            intent.setComponent(ComponentName.unflattenFromString(evt.getReceiverName()));
            intent.putExtra(DConnectMessage.EXTRA_DEVICE_ID, DEVICE_ID);
            intent.putExtra(DConnectMessage.EXTRA_PROFILE, MediaStreamRecordingProfile.PROFILE_NAME);
            intent.putExtra(DConnectMessage.EXTRA_ATTRIBUTE,
                    MediaStreamRecordingProfile.ATTRIBUTE_ON_DATA_AVAILABLE);
            intent.putExtra(DConnectMessage.EXTRA_SESSION_KEY, evt.getSessionKey());
            intent.putExtra(MediaStreamRecordingProfile.PARAM_MEDIA, media);

            sendEvent(intent, evt.getAccessToken());
        }
    }

    /**
     * ??????Activity????.
     * 
     * @return ??
     */
    private String getClassnameOfTopActivity() {

        ActivityManager mActivityManager = (ActivityManager) getContext()
                .getSystemService(Service.ACTIVITY_SERVICE);
        String mClassName = mActivityManager.getRunningTasks(1).get(0).topActivity.getClassName();

        return mClassName;
    }
}