/*
WearKeyEventProfile.java
Copyright (c) 2015 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.wear.profile;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.wearable.MessageApi.SendMessageResult;
import org.deviceconnect.android.deviceplugin.wear.BuildConfig;
import org.deviceconnect.android.deviceplugin.wear.WearDeviceService;
import org.deviceconnect.android.deviceplugin.wear.WearManager;
import org.deviceconnect.android.deviceplugin.wear.WearManager.OnMessageEventListener;
import org.deviceconnect.android.deviceplugin.wear.WearManager.OnMessageResultListener;
import org.deviceconnect.android.event.Event;
import org.deviceconnect.android.event.EventError;
import org.deviceconnect.android.event.EventManager;
import org.deviceconnect.android.message.MessageUtils;
import org.deviceconnect.android.profile.KeyEventProfile;
import org.deviceconnect.android.profile.api.DConnectApi;
import org.deviceconnect.android.profile.api.DeleteApi;
import org.deviceconnect.android.profile.api.GetApi;
import org.deviceconnect.android.profile.api.PutApi;
import org.deviceconnect.message.DConnectMessage;
import java.util.List;
import static org.deviceconnect.android.deviceplugin.wear.profile.WearConst.STATE_DOWN;
import static org.deviceconnect.android.deviceplugin.wear.profile.WearConst.STATE_UP;
/**
* Key Event Profile.
*
* @author NTT DOCOMO, INC.
*/
public class WearKeyEventProfile extends KeyEventProfile {
/** Tag. */
private static final String TAG = "WEAR";
/** KeyEvent profile onDown cache. */
Bundle mOnDownCache = null;
/** KeyEvent profile onDown cache time. */
long mOnDownCacheTime = 0;
/** KeyEvent profile onDown cache. */
Bundle mOnUpCache = null;
/** KeyEvent profile onUp cache time. */
long mOnUpCacheTime = 0;
/** KeyEvent profile onKeyChange cache. */
Bundle mOnKeyChangeCache = null;
/** KeyEvent profile onKeyChange cache time. */
long mOnKeyChangeCacheTime = 0;
/** KeyEvent profile cache retention time (mSec). */
static final long CACHE_RETENTION_TIME = 10000;
/**
* Attribute: {@value} .
*/
public static final String ATTRIBUTE_ON_KEY_CHANGE = "onKeyChange";
/**
* Get KeyEvent cache data.
*
* @param attr Attribute.
* @return KeyEvent cache data.
*/
public Bundle getKeyEventCache(final String attr) {
long lCurrentTime = System.currentTimeMillis();
if (attr.equalsIgnoreCase(KeyEventProfile.ATTRIBUTE_ON_DOWN)) {
if (lCurrentTime - mOnDownCacheTime <= CACHE_RETENTION_TIME) {
return mOnDownCache;
} else {
return null;
}
} else if (attr.equalsIgnoreCase(KeyEventProfile.ATTRIBUTE_ON_UP)) {
if (lCurrentTime - mOnUpCacheTime <= CACHE_RETENTION_TIME) {
return mOnUpCache;
} else {
return null;
}
} else if (attr.equalsIgnoreCase(ATTRIBUTE_ON_KEY_CHANGE)) {
if (lCurrentTime - mOnKeyChangeCacheTime <= CACHE_RETENTION_TIME) {
return mOnKeyChangeCache;
} else {
return null;
}
} else {
return null;
}
}
/**
* Set KeyEvent data to cache.
*
* @param attr Attribute.
* @param keyeventData Touch data.
*/
public void setKeyEventCache(final String attr, final Bundle keyeventData) {
long lCurrentTime = System.currentTimeMillis();
if (attr.equalsIgnoreCase(KeyEventProfile.ATTRIBUTE_ON_DOWN)) {
mOnDownCache = keyeventData;
mOnDownCacheTime = lCurrentTime;
} else if (attr.equalsIgnoreCase(KeyEventProfile.ATTRIBUTE_ON_UP)) {
mOnUpCache = keyeventData;
mOnUpCacheTime = lCurrentTime;
} else if (attr.equalsIgnoreCase(ATTRIBUTE_ON_KEY_CHANGE)) {
mOnKeyChangeCache = keyeventData;
mOnKeyChangeCacheTime = lCurrentTime;
}
}
/**
* Receive event listener for Android Wear.
*/
private OnMessageEventListener mListener = new OnMessageEventListener() {
@Override
public void onEvent(final String nodeId, final String message) {
sendMessageToEvent(WearUtils.createServiceId(nodeId), message);
}
};
/**
* Constructor.
*
* @param mgr Android Wear management class.
*/
public WearKeyEventProfile(final WearManager mgr) {
mgr.addMessageEventListener(WearConst.WEAR_TO_DEVICE_KEYEVENT_DATA, mListener);
addApi(mGetOnKeyChange);
addApi(mGetOnDown);
addApi(mGetOnUp);
addApi(mPutOnKeyChange);
addApi(mPutOnDown);
addApi(mPutOnUp);
addApi(mDeleteOnKeyChange);
addApi(mDeleteOnDown);
addApi(mDeleteOnUp);
}
private final DConnectApi mGetOnDown = new GetApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_DOWN;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
Bundle keyevent = getKeyEventCache(KeyEventProfile.ATTRIBUTE_ON_DOWN);
if (keyevent == null) {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, "");
} else {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, keyevent);
}
setResult(response, DConnectMessage.RESULT_OK);
return true;
}
};
private final DConnectApi mGetOnUp = new GetApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_UP;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
Bundle keyEvent = getKeyEventCache(KeyEventProfile.ATTRIBUTE_ON_UP);
if (keyEvent == null) {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, "");
} else {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, keyEvent);
}
setResult(response, DConnectMessage.RESULT_OK);
return true;
}
};
private final DConnectApi mGetOnKeyChange = new GetApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_KEY_CHANGE;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
Bundle keyevent = getKeyEventCache(ATTRIBUTE_ON_KEY_CHANGE);
if (keyevent == null) {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, "");
} else {
response.putExtra(KeyEventProfile.PARAM_KEYEVENT, keyevent);
}
setResult(response, DConnectMessage.RESULT_OK);
return true;
}
};
private final DConnectApi mPutOnDown = new PutApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_DOWN;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONDOWN_REGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
if (result.getStatus().isSuccess()) {
EventError error = EventManager.INSTANCE.addEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
} else {
MessageUtils.setIllegalDeviceStateError(response);
}
sendResponse(response);
}
@Override
public void onError() {
MessageUtils.setIllegalDeviceStateError(response);
sendResponse(response);
}
});
return false;
}
};
private final DConnectApi mPutOnUp = new PutApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_UP;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONUP_REGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
if (result.getStatus().isSuccess()) {
EventError error = EventManager.INSTANCE.addEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
} else {
MessageUtils.setIllegalDeviceStateError(response);
}
sendResponse(response);
}
@Override
public void onError() {
MessageUtils.setIllegalDeviceStateError(response);
sendResponse(response);
}
});
return false;
}
};
private final DConnectApi mPutOnKeyChange = new PutApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_KEY_CHANGE;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONKEYCHANGE_REGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
if (result.getStatus().isSuccess()) {
EventError error = EventManager.INSTANCE.addEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
} else {
MessageUtils.setIllegalDeviceStateError(response);
}
sendResponse(response);
}
@Override
public void onError() {
MessageUtils.setIllegalDeviceStateError(response);
sendResponse(response);
}
});
return false;
}
};
private final DConnectApi mDeleteOnDown = new DeleteApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_DOWN;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONDOWN_UNREGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
}
@Override
public void onError() {
}
});
// Event release.
EventError error = EventManager.INSTANCE.removeEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
return true;
}
};
private final DConnectApi mDeleteOnUp = new DeleteApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_UP;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONUP_UNREGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
}
@Override
public void onError() {
}
});
// Event release.
EventError error = EventManager.INSTANCE.removeEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
return true;
}
};
private final DConnectApi mDeleteOnKeyChange = new DeleteApi() {
@Override
public String getAttribute() {
return ATTRIBUTE_ON_KEY_CHANGE;
}
@Override
public boolean onRequest(final Intent request, final Intent response) {
String nodeId = WearUtils.getNodeId(getServiceID(request));
getManager().sendMessageToWear(nodeId, WearConst.DEVICE_TO_WEAR_KEYEVENT_ONKEYCHANGE_UNREGISTER, "",
new OnMessageResultListener() {
@Override
public void onResult(final SendMessageResult result) {
}
@Override
public void onError() {
}
});
// Event release.
EventError error = EventManager.INSTANCE.removeEvent(request);
if (error == EventError.NONE) {
setResult(response, DConnectMessage.RESULT_OK);
} else {
setResult(response, DConnectMessage.RESULT_ERROR);
}
return true;
}
};
/**
* Send a message to the registration event.
*
* @param nodeId node id
* @param data Received Strings.
*/
private void sendMessageToEvent(final String nodeId, final String data) {
if (BuildConfig.DEBUG) {
Log.i(TAG, "@@@@@@SUCCESS");
}
String[] mDataArray = data.split(",", 0);
String attr = null;
String state = null;
if (mDataArray[0].equals(WearConst.PARAM_KEYEVENT_DOWN)) {
attr = ATTRIBUTE_ON_DOWN;
state = STATE_DOWN;
} else if (mDataArray[0].equals(WearConst.PARAM_KEYEVENT_UP)) {
attr = ATTRIBUTE_ON_UP;
state = STATE_UP;
} else {
return;
}
List<Event> events = EventManager.INSTANCE.getEventList(nodeId, PROFILE_NAME, null, attr);
List<Event> keyEvents = EventManager.INSTANCE.getEventList(nodeId, PROFILE_NAME, null, ATTRIBUTE_ON_KEY_CHANGE);
Bundle keyevent = new Bundle();
keyevent.putInt(KeyEventProfile.PARAM_ID, Integer.parseInt(mDataArray[1]));
keyevent.putString(KeyEventProfile.PARAM_CONFIG, mDataArray[2]);
synchronized (events) {
for (Event event : events) {
String eventAttr = event.getAttribute();
Intent intent = EventManager.createEventMessage(event);
intent.putExtra(KeyEventProfile.PARAM_KEYEVENT, keyevent);
((WearDeviceService) getContext()).sendEvent(intent, event.getAccessToken());
setKeyEventCache(eventAttr, keyevent);
}
}
synchronized (keyEvents) {
for (Event event : keyEvents) {
String eventAttr = event.getAttribute();
keyevent.putString("state", state);
Intent intent = EventManager.createEventMessage(event);
intent.putExtra(KeyEventProfile.PARAM_KEYEVENT, keyevent);
((WearDeviceService) getContext()).sendEvent(intent, event.getAccessToken());
setKeyEventCache(eventAttr, keyevent);
}
}
}
/**
* Get Android Wear management class.
*
* @return WearManager management class.
*/
private WearManager getManager() {
return ((WearDeviceService) getContext()).getManager();
}
}