/* UnitTestService.java Copyright (c) 2014 NTT DOCOMO,INC. Released under the MIT license http://opensource.org/licenses/mit-license.php */ package org.deviceconnect.android.deviceplugin.test.service; import android.content.ComponentName; import android.content.Intent; import org.deviceconnect.android.deviceplugin.test.profile.Util; import org.deviceconnect.android.deviceplugin.test.profile.unique.TestAllGetControlProfile; import org.deviceconnect.android.deviceplugin.test.profile.unique.TestDataProfile; import org.deviceconnect.android.deviceplugin.test.profile.unique.TestJSONConversionProfile; import org.deviceconnect.android.deviceplugin.test.profile.unique.TestUniqueProfile; import org.deviceconnect.android.message.MessageUtils; import org.deviceconnect.android.profile.AuthorizationProfile; import org.deviceconnect.android.profile.DConnectProfile; import org.deviceconnect.android.profile.ServiceDiscoveryProfile; import org.deviceconnect.android.profile.ServiceInformationProfile; import org.deviceconnect.android.profile.SystemProfile; import org.deviceconnect.android.profile.api.DConnectApi; import org.deviceconnect.android.profile.spec.DConnectApiSpec; import org.deviceconnect.android.profile.spec.DConnectPluginSpec; import org.deviceconnect.android.profile.spec.DConnectProfileSpec; import org.deviceconnect.android.service.DConnectService; import org.deviceconnect.message.DConnectMessage; import java.util.HashMap; import java.util.Map; /** * ユニットテスト用サービス. * <p> * 各プロファイルの疎通テストに使用する. * </p> * @author NTT DOCOMO, INC. */ public class UnitTestService extends DConnectService { private static final long DEFAULT_DELAY = 500; private Map<String, EventSender> mEventSenders = new HashMap<String, EventSender>(); public UnitTestService(final String id, final String name, final DConnectPluginSpec pluginSpec) { super(id); setName(name); setOnline(true); Map<String, DConnectProfileSpec> profileSpecs = pluginSpec.getProfileSpecs(); for (Map.Entry<String, DConnectProfileSpec> entry : profileSpecs.entrySet()) { final String profileName = entry.getKey(); if (AuthorizationProfile.PROFILE_NAME.equalsIgnoreCase(profileName) || ServiceDiscoveryProfile.PROFILE_NAME.equalsIgnoreCase(profileName) || ServiceInformationProfile.PROFILE_NAME.equalsIgnoreCase(profileName) || SystemProfile.PROFILE_NAME.equalsIgnoreCase(profileName)) { continue; } final DConnectProfileSpec profileSpec = entry.getValue(); final DConnectProfile profile = new DConnectProfile() { @Override public String getProfileName() { return profileName; } }; for (final DConnectApiSpec apiSpec : profileSpec.getApiSpecList()) { DConnectApi api = new DConnectApi() { @Override public Method getMethod() { return apiSpec.getMethod(); } @Override public String getInterface() { return apiSpec.getInterfaceName(); } @Override public String getAttribute() { return apiSpec.getAttributeName(); } @Override public boolean onRequest(final Intent request, final Intent response) { DConnectProfile.setResult(response, DConnectMessage.RESULT_OK); if (apiSpec.getType() == Type.EVENT) { switch (apiSpec.getMethod()) { case PUT: startEventBroadcast(request); break; case DELETE: stopEventSender(request); break; default: break; } } return true; } }; profile.addApi(api); } addProfile(profile); } addProfile(new TestUniqueProfile()); addProfile(new TestJSONConversionProfile()); addProfile(new TestAllGetControlProfile()); addProfile(new TestDataProfile()); } /** * 指定したミリ秒後に別スレッドでインテントをブロードキャストする. * * @param intent インテント * @param delay 遅延設定 (単位はミリ秒) */ public void sendBroadcast(final Intent intent, final long delay) { (new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(delay); intent.setComponent(Util.DEFAULT_MESSAGE_RECEIVER); getContext().sendBroadcast(intent); } catch (InterruptedException e) { // do nothing. } } })).start(); } /** * {@value #DEFAULT_DELAY}ミリ秒後に別スレッドでインテントをブロードキャストする. * * @param intent インテント */ public void sendBroadcast(final Intent intent) { sendBroadcast(intent, DEFAULT_DELAY); } private EventSender getEventSender(final String path) { return mEventSenders.get(path); } private EventSender removeEventSender(final String path) { return mEventSenders.remove(path); } private void putEventSender(final String path, final EventSender thread) { mEventSenders.put(path, thread); } private void startEventBroadcast(final Intent request) { EventSender sender = new EventSender(request); EventSender cache = getEventSender(sender.getPath()); if (cache != null) { return; } putEventSender(sender.getPath(), sender); new Thread(sender).start(); } private void stopEventSender(final Intent request) { EventSender cache = removeEventSender(createPath(request)); if (cache == null) { return; } cache.stop(); } private String createPath(final Intent request) { String profileName = DConnectProfile.getProfile(request); String attributeName = DConnectProfile.getAttribute(request); return "/" + profileName + "/" + attributeName; } private class EventSender implements Runnable { private final String mPath; private final String mAccessToken; private final Intent mEvent; private boolean mIsSending = true; private int mCount = 10; EventSender(final Intent request) { String profileName = DConnectProfile.getProfile(request); String attributeName = DConnectProfile.getAttribute(request); String accessToken = DConnectProfile.getAccessToken(request); String serviceId = DConnectProfile.getServiceID(request); Intent message = MessageUtils.createEventIntent(); DConnectProfile.setAccessToken(message, accessToken); DConnectProfile.setServiceID(message, serviceId); DConnectProfile.setProfile(message, profileName); DConnectProfile.setAttribute(message, attributeName); message.setComponent((ComponentName) request.getParcelableExtra(DConnectMessage.EXTRA_RECEIVER)); mEvent = message; mPath = createPath(request); mAccessToken = accessToken; } String getPath() { return mPath + mAccessToken; } void stop() { mIsSending = false; } @Override public void run() { try { while (mIsSending && mCount > 0) { sendBroadcast(mEvent); Thread.sleep(DEFAULT_DELAY); mCount--; } } catch (InterruptedException e) { mIsSending = false; } finally { removeEventSender(getPath()); } } } }