diff --git a/.gitmodules b/.gitmodules index f9ecabc0..6aa63c6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "android/libs/armeabi"] path = android/libs/armeabi url = https://github.com/SKKU-ESLAB/ant-android-libs-armeabi.git +[submodule "subprojects/selective-connection"] + path = subprojects/selective-connection + url = https://github.com/SKKU-ESLAB/selective-connection diff --git a/subprojects/sc/.gitignore b/subprojects/sc/.gitignore deleted file mode 100644 index cafe80e5..00000000 --- a/subprojects/sc/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -tags -cscope -cscope.out -.vscode -*.o -bin/* -dhcpd.conf -!bin/.git_empty_file -SelectiveConnection.IAB -SelectiveConnection.IAD -SelectiveConnection.IMB -SelectiveConnection.IMD -SelectiveConnection.PFI -SelectiveConnection.PO -SelectiveConnection.PR -SelectiveConnection.PRI -SelectiveConnection.PS -*.iml -.gradle -android/local.properties -android/.idea -.DS_Store -android/build -android/captures -.externalNativeBuild -*.swp diff --git a/subprojects/sc/README.md b/subprojects/sc/README.md deleted file mode 100644 index 6807cfa2..00000000 --- a/subprojects/sc/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# P2PForYourThings -C++ APIs for you to easily setup and communicate via smart P2P (using available p2p modules among Wi-Fi Direct / Bluetooth / Bluetooth LE) - -## Supported Devices -* Raspberry-pi 3 -* NVIDIA Jetson-TX1 - -# Android -[P2PForYourThings-android](https://github.com/sinban04/P2PForYourThings-android) - - -# Quick Start -## How to Get the Source Code -``` -$ git clone https://github.com/sinban04/P2PForYourThings.git -$ cd P2PForYourThings -``` - -## Pre-requisite -- Install Bluetooth library -``` -$ sudo apt-get install libbluetooth-dev -``` - -Check your bluetooth version and if it is equal to or higher than 5.0, then -``` -$ sudo vi /etc/systemd/system/dbus-org.bluez.service - -ExecStart=/usr/lib/bluetooth/bluetoothd --compat - -$ sudo systemctl daemon-reload -$ sudo systemctl restart bluetooth -$ sudo chmod 777 /var/run/sdp -``` - -- Check the wifi module support p2p -``` -$ iw list -``` - -- Modify the wpa_supplicant.conf (```/etc/wpa_supplicant/wpa_supplicant.conf```) -Add two parameters - -> update_config=1 -> -> driver_param=p2p_device=1 - -- Install UDHCPD for wifi-direct -``` -$ sudo apt-get install udhcpd -$ sudo touch /var/lib/misc/udhcpd.leases -``` - -- Set ```wpa_supplicant``` configuration -``` -sudo wpa_supplicant -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf -``` - - -## How to Build the Source Code -``` -// No need to make the new directories now (Already exists) -$ mkdir bin obj ./device/obj -$ make -``` -Then you can find the binary file of the communicator test example, -which is in the ```tests/``` directory. - -## How to Run -``` -$ sudo ./bin/test -``` - -# Notes -## Bluetooth Issues -### Bluetooth Version Compatibility -Check your bluetooth version using -``` -$ sudo vi /etc/systemd/system/dbus-org.bluez.service - -ExecStart=/usr/lib/bluetooth/bluetoothd --compat - -$ sudo systemctl daemon-reload -$ sudo systemctl restart bluetooth -$ sudo chmod 777 /var/run/sdp -``` - -### Check the bluetooth HCI interface -``` -$ hciconfig -a -``` - -### Change hci0 interface to Scan Mode -Set page scan and inquiry can (Discoverable) -``` -$ sudo hciconfig hci0 piscan -``` - -### Change the hci0 interface name -e.g., change the name of the bluetooth interface to ```pi``` -``` -$ sudo hciconfig hci0 name pi -``` - -### Turn on the interface -``` -$ sudo hciconfig hci0 up -``` - -### Turn on the bluetoothd (For the case, it's off) -``` -sudo service bluetooth start -``` -When the bluetooth.target is masked, unmask it -``` -$ sudo systemctl unmask bluetooth -``` -Check the bluetoothd exists -``` -$ ps -ef | grep bluetooth -``` - -## Wifi-Direct Issues -### Remove the P2P group (Wifi-direct) on the wifi interface -remove group ```p2p-wlan0-0``` on the wifi interface ```wlan0``` -``` -sudo wpa_cli -i wlan0 p2p_group_remove p2p-wlan0-0 -``` diff --git a/subprojects/sc/android/.project b/subprojects/sc/android/.project deleted file mode 100644 index 3964dd3f..00000000 --- a/subprojects/sc/android/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - android - Project android created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs b/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index e8895216..00000000 --- a/subprojects/sc/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir= -eclipse.preferences.version=1 diff --git a/subprojects/sc/android/Readme.md b/subprojects/sc/android/Readme.md deleted file mode 100644 index 98b9bfe0..00000000 --- a/subprojects/sc/android/Readme.md +++ /dev/null @@ -1 +0,0 @@ -[P2PForYourThings](https://github.com/esevan/P2PForYourThings) diff --git a/subprojects/sc/android/app/.classpath b/subprojects/sc/android/app/.classpath deleted file mode 100644 index eb19361b..00000000 --- a/subprojects/sc/android/app/.classpath +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/subprojects/sc/android/app/.gitignore b/subprojects/sc/android/app/.gitignore deleted file mode 100755 index 3543521e..00000000 --- a/subprojects/sc/android/app/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/subprojects/sc/android/app/.project b/subprojects/sc/android/app/.project deleted file mode 100644 index ac485d7c..00000000 --- a/subprojects/sc/android/app/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - app - Project app created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs b/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index b1886adb..00000000 --- a/subprojects/sc/android/app/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,2 +0,0 @@ -connection.project.dir=.. -eclipse.preferences.version=1 diff --git a/subprojects/sc/android/app/build.gradle b/subprojects/sc/android/app/build.gradle deleted file mode 100755 index ec825f69..00000000 --- a/subprojects/sc/android/app/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 25 - buildToolsVersion '27.0.3' - defaultConfig { - applicationId "com.redcarrottt.sc" - minSdkVersion 19 - targetSdkVersion 25 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - 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.0.0' - testCompile 'junit:junit:4.12' -} diff --git a/subprojects/sc/android/app/proguard-rules.pro b/subprojects/sc/android/app/proguard-rules.pro deleted file mode 100755 index fa3c8f5e..00000000 --- a/subprojects/sc/android/app/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:\Users\eslab\AppData\Local\Android\Sdk/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 *; -#} diff --git a/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java b/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java deleted file mode 100755 index 832a7b5d..00000000 --- a/subprojects/sc/android/app/src/androidTest/java/com/redcarrottt/testapp/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package kr.ac.skku.nyx.selectiveconnection; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumentation test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("kr.ac.skku.nyx.selectiveconnection", appContext.getPackageName()); - } -} diff --git a/subprojects/sc/android/app/src/main/AndroidManifest.xml b/subprojects/sc/android/app/src/main/AndroidManifest.xml deleted file mode 100755 index 992dd9fb..00000000 --- a/subprojects/sc/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/ic_launcher-web.png b/subprojects/sc/android/app/src/main/ic_launcher-web.png deleted file mode 100644 index 2321e583..00000000 Binary files a/subprojects/sc/android/app/src/main/ic_launcher-web.png and /dev/null differ diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java deleted file mode 100755 index a8dcdc22..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/API.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.Core; - -public class API { - public static void startSC(OnStartSCResult resultListener) { - Core.singleton().start(resultListener); - } - - public static void stopSC(OnStopSCResult resultListener) { - Core.singleton().stop(resultListener); - } - - public static void registerAdapter(ClientAdapter adapter) { - Core.singleton().registerAdapter(adapter); - } - - public static int send(byte[] dataBuffer, int dataLength) { - return Core.singleton().send(dataBuffer, dataLength, false); - } - - public static int receive(byte[] dataBuffer) { - return Core.singleton().receive(dataBuffer, false); - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java deleted file mode 100644 index 5646c9e5..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStartSCResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface OnStartSCResult { - public void onDoneStartSC(boolean isSuccess); -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java deleted file mode 100644 index c5a6a1ef..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/api/OnStopSCResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.api; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface OnStopSCResult { - public void onDoneStopSC(boolean isSuccess); -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java deleted file mode 100644 index ebd8110f..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapter.java +++ /dev/null @@ -1,901 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import android.util.Log; - -import com.redcarrottt.testapp.Logger; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Date; - -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_CLIENT_ADAPTER; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_RECEIVER_TIME; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_SEGMENT_DEQUEUE_CTRL; -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_SEGMENT_DEQUEUE_DATA; -import static com.redcarrottt.sc.internal.SegmentManager.kDeqSendControlData; -import static com.redcarrottt.sc.internal.SegmentManager.kSQRecvControl; -import static com.redcarrottt.sc.internal.SegmentManager.kSQRecvData; -import static com.redcarrottt.sc.internal.SegmentManager.kSegFlagControl; -import static com.redcarrottt.sc.internal.SegmentManager.kSegHeaderSize; -import static com.redcarrottt.sc.internal.SegmentManager.kSegSize; - -public class ClientAdapter { - private final String kTag = "ClientAdapter"; - private final ClientAdapter self = this; - - // Main Functions: connect, disconnect, send, receive - public void connect(ConnectResultListener listener, boolean isSendRequest) { - int state = this.getState(); - if (state != State.kDisconnected) { - Logger.ERR(kTag, "Connect Failed: Already connected or connect/disconnection is in " - + "progress: " + this.getName() + " / " + this.getState()); - listener.onConnectResult(false); - return; - } - - if (isSendRequest) { - Core.singleton().getControlMessageSender().sendRequestConnect(this.getId()); - } - - ConnectThread thread = new ConnectThread(listener); - thread.start(); - } - - public void disconnectOnCommand(DisconnectResultListener listener) { - // Check if the adapter is not sleeping - int state = this.getState(); - if (state == State.kGoingSleep) { - Logger.VERB(kTag, this.getName() + ": Disconnect - waiting for sleeping..."); - while (state != State.kSleeping) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - state = this.getState(); - } - } else if (state != State.kSleeping) { - Logger.ERR(kTag, this.getName() + ": Disconnect fail - not sleeping - " + state); - listener.onDisconnectResult(false); - return; - } - - // Set this disconnection is on purpose - this.startDisconnectingOnPurpose(); - - // Get my final seq_no - SegmentManager sm = SegmentManager.singleton(); - int my_final_seq_no_control = sm.getLastSeqNoControl(); - int my_final_seq_no_data = sm.getLastSeqNoData(); - - // Send disconnect request - Core.singleton().getControlMessageSender().sendRequestDisconnect(this.getId(), - my_final_seq_no_control, my_final_seq_no_data); - - disconnectInternal(listener); - } - - public void disconnectOnPeerCommand(DisconnectResultListener listener, int - peerFinalSeqNoControl, int peerFinalSeqNoData) { - // Check if the adapter is not sleeping - int state = this.getState(); - - // TODO: wait for sleeping should be implemented - - // Set this disconnection is on purpose - this.startDisconnectingOnPurpose(); - this.peerKnowsDisconnectingOnPurpose(); - - // Start wait receiving - SegmentManager sm = SegmentManager.singleton(); - sm.waitReceiving(peerFinalSeqNoControl, peerFinalSeqNoData); - - // Send disconnect ack - Core.singleton().getControlMessageSender().sendRequestDisconnectAck(this.getId()); - - disconnectInternal(listener); - } - - public void disconnectOnFailure(DisconnectResultListener listener) { - // Check if the adapter is not sleeping - int state = this.getState(); - if (state == State.kDisconnected || state == State.kDisconnecting) { - Logger.VERB(kTag, this.getName() + ": Disconnect - already disconnecting or " + - "disconnected - " + state); - listener.onDisconnectResult(false); - return; - } - - disconnectInternal(listener); - } - - private void disconnectInternal(DisconnectResultListener listener) { - // Spawn disconnect thread - DisconnectThread thread = new DisconnectThread(listener); - thread.start(); - } - - int send(byte[] dataBuffer, int dataLength) { - int state = this.getState(); - if (state == State.kSleeping || state == State.kGoingSleep || state == State.kWakingUp) { - if (!this.isDisconnectingOnPurpose()) { - Logger.ERR(kTag, "Send Failed: Already sleeping: " + this.getName() + " / " + - this.getState()); - } - return -1; - } else if (state != State.kActive) { - Logger.ERR(kTag, "Send Failed: Already disconnected or connect/disconnection is in " - + "progress: " + this.getName() + " / " + this.getState()); - return -1; - } - - if (this.mClientSocket == null) { - return -2; - } - - Logger.VERB(this.getName(), "Send data: length=" + dataLength); - - // Omit Implementing Statistics: SendDataSize - return this.mClientSocket.send(dataBuffer, dataLength); - } - - int receive(byte[] dataBuffer, int dataLength) { - int state = this.getState(); - if (state != State.kActive && state != State.kGoingSleep && state != State.kSleeping && - state != State.kWakingUp) { - if (!this.isDisconnectingOnPurpose()) { - Logger.ERR(kTag, "Receive Failed: Already disconnected or connect/disconnection " - + "is " + "in" + " progress: " + this.getName() + " / " + this.getState()); - } - return -1; - } - - if (this.mClientSocket == null) { - return -2; - } - - // Omit Implementing Statistics: ReceiveDataSize - return this.mClientSocket.receive(dataBuffer, dataLength); - } - - // Connect/Disconnect Threads & Callbacks - class ConnectThread extends Thread implements TurnOnResultListener, - DiscoverAndConnectResultListener { - @Override - public void run() { - this.setName(self.getName() + "/Connect"); - Logger.VERB(kTag, self.getName() + "'s Connect Thread Spawned! (id:" + this.getId() + - ")"); - setState(ClientAdapter.State.kConnecting); - - if (self.mDevice == null || self.mP2PClient == null || self.mClientSocket == null) { - this.onFail(); - return; - } - - // Turn on device - self.mDevice.turnOn(this); - } - - @Override - public void onTurnOnResult(boolean isSuccess) { - int deviceState = self.mDevice.getState(); - if (!isSuccess || deviceState != Device.State.kOn) { - Logger.ERR(kTag, "Cannot connect the server adapter - turn-on fail: " + self - .getName()); - this.onFail(); - return; - } - - Logger.VERB(kTag, "Turn on success: " + self.getName()); - - // Discover and connect to server - self.mP2PClient.discoverAndConnect(this); - } - - @Override - public void onDiscoverAndConnectResult(boolean isSuccess) { - // Check the result of "Discover and connect" - int p2pClientState = self.mP2PClient.getState(); - if (!isSuccess || p2pClientState != P2PClient.State.kConnected) { - Logger.ERR(kTag, "Cannot connect the server adapter - discover fail:" + self - .getName()); - self.mDevice.turnOff(null); - this.onFail(); - return; - } - - Logger.VERB(kTag, "P2P connect success: " + self.getName()); - - this.mSocketOpenThread = new SocketOpenThread(); - this.mSocketOpenThread.start(); - } - - private SocketOpenThread mSocketOpenThread; - - class SocketOpenThread extends Thread { - @Override - public void run() { - // Open client socket - this.setName(self.getName() + "/SocketOpen"); - int socketState = self.mClientSocket.getState(); - if (socketState != ClientSocket.State.kOpened) { - boolean res = self.mClientSocket.open(); - - socketState = self.mClientSocket.getState(); - if (!res || socketState != ClientSocket.State.kOpened) { - Logger.ERR(kTag, "Cannot connect the server adapter - socket open fail: " - + self.getName()); - self.mP2PClient.disconnect(null); - self.mDevice.turnOff(null); - onFail(); - return; - } - } - - Logger.VERB(kTag, "Socket connect success: " + self.getName()); - - // Run sender & receiver threads - if (self.mSenderThread != null && !self.mSenderThread.isOn()) { - self.mSenderThread.start(); - } - - if (self.mReceiverThread != null && !self.mReceiverThread.isOn()) { - self.mReceiverThread.start(); - } - - // Report result success - self.setState(ClientAdapter.State.kActive); - if (mResultListener != null) { - mResultListener.onConnectResult(true); - mResultListener = null; - } - } - } - - private void onFail() { - self.setState(ClientAdapter.State.kDisconnected); - - // Report result fail - if (this.mResultListener != null) { - this.mResultListener.onConnectResult(false); - this.mResultListener = null; - } - } - - private ConnectResultListener mResultListener; - - ConnectThread(ConnectResultListener resultListener) { - this.mResultListener = resultListener; - } - } - - class DisconnectThread extends Thread implements com.redcarrottt.sc.internal - .DisconnectResultListener, TurnOffResultListener { - @Override - public void run() { - this.setName(self.getName() + "/Disconnect"); - Logger.VERB(kTag, self.getName() + "'s Disconnect Thread Spawned! (id:" + this.getId - () + ")"); - int oldState = self.getState(); - setState(ClientAdapter.State.kDisconnecting); - - if (isDisconnectingOnPurpose() && !isDisconnectingOnPurposePeer()) { - waitForDisconnectingOnPurposePeer(); - } - - boolean res = this.__disconnect_thread(oldState); - - finishDisconnectingOnPurpose(); - - if (!res) { - this.onFail(); - } - - Logger.VERB(kTag, self.getName() + "'s Disconnect Thread Finished. (id:" + this.getId - () + ")"); - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private boolean __disconnect_thread(int oldState) { - // Finish sender & receiver threads - if (self.mSenderThread != null) { - self.mSenderThread.finish(); - if (oldState == ClientAdapter.State.kSleeping) { - self.wakeUpInternal(); - } - } - if (self.mReceiverThread != null) { - self.mReceiverThread.finish(); - } - - // Wake up sender thread waiting segment queue - SegmentManager sm = SegmentManager.singleton(); - sm.wakeUpDequeueWaiting(kDeqSendControlData); - - // Close client socket - if (self.mClientSocket == null) { - return false; - } - int socketState = self.mClientSocket.getState(); - if (socketState != ClientSocket.State.kClosed) { - boolean res = self.mClientSocket.close(); - - socketState = self.mClientSocket.getState(); - if (!res || socketState != ClientSocket.State.kClosed) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - socket " + "close " - + "fail: " + "" + "" + self.getName()); - return false; - } - } - - // P2P Disconnect - self.mP2PClient.disconnect(this); - - // Wait for sender/receiver thread - try { - synchronized (self.mWaitSenderThread) { - if (self.mSenderThread.isOn()) { - Logger.DEBUG(kTag, "Waiting for sender thread... " + mName); - synchronized (self.mIsWaitSenderThread) { - self.mIsWaitSenderThread = true; - } - self.mWaitSenderThread.wait(); - } - Logger.DEBUG(kTag, "Sender thread's end is detected... " + mName); - } - synchronized (self.mWaitReceiverThread) { - if (self.mReceiverThread.isOn()) { - Logger.DEBUG(kTag, "Waiting for receiver thread..." + mName); - synchronized (self.mIsWaitReceiverThread) { - self.mIsWaitReceiverThread = true; - } - self.mWaitReceiverThread.wait(); - } - Logger.DEBUG(kTag, "Receiver thread's end is detected... " + mName); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - return true; - } - - @Override - public void onDisconnectResult(boolean isSuccess) { - // Check the result of "P2P Disconnect" - int p2pClientState = self.mP2PClient.getState(); - if (!isSuccess) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - " + "disconnect P2P " + - "client fail: " + self.getName()); - this.onFail(); - return; - } - - // Turn off device - self.mDevice.turnOff(this); - } - - @Override - public void onTurnOffResult(boolean isSuccess) { - int deviceState = self.mDevice.getState(); - if (!isSuccess) { - Logger.ERR(kTag, "Cannot disconnect the server adapter - turn-off " + "fail:" + - "" + " " + self.getName()); - this.onFail(); - return; - } - - // Report result success - self.setState(ClientAdapter.State.kDisconnected); - if (this.mResultListener != null) { - this.mResultListener.onDisconnectResult(true); - this.mResultListener = null; - } - } - - private void onFail() { - self.setState(ClientAdapter.State.kActive); - - // Report result fail - if (this.mResultListener != null) { - this.mResultListener.onDisconnectResult(false); - this.mResultListener = null; - } - } - - private DisconnectResultListener mResultListener; - - DisconnectThread(DisconnectResultListener resultListener) { - this.mResultListener = resultListener; - } - } - - interface ConnectResultListener { - void onConnectResult(boolean isSuccess); - } - - interface DisconnectResultListener { - void onDisconnectResult(boolean isSuccess); - } - - // Sender/Receiver Threads - @SuppressWarnings("SynchronizeOnNonFinalField") - class SenderThread extends Thread { - @Override - public void run() { - this.setName(self.getName() + "/Sender"); - synchronized (this.mIsOn) { - this.mIsOn = true; - } - synchronized (this.mIsSuspended) { - this.mIsSuspended = false; - } - - synchronized (self.mIsWaitSenderThread) { - self.mIsWaitSenderThread = false; - } - - this.senderThreadLoop(); - -// NetworkSwitcher.singleton().reconnectAdapter(ClientAdapter.this); - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Sender thread ends"); - - synchronized (self.mIsWaitSenderThread) { - if (self.mIsWaitSenderThread) { - self.mWaitSenderThread.notifyAll(); - } - } - } - - private void senderThreadLoop() { - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Sender thread starts"); - while (this.mIsOn) { - SegmentManager sm = SegmentManager.singleton(); - Segment segmentToSend; - - // If this sender is set to be suspended, wait until it wakes up - { - boolean sender_suspended; - do { - synchronized (mSenderSuspended) { - sender_suspended = mSenderSuspended; - } - if (!sender_suspended) { - break; - } - Logger.VERB(kTag, "Sender thread suspended: " + this.getName()); - setState(ClientAdapter.State.kSleeping); - synchronized (mSenderSuspended) { - try { - mSenderSuspended.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - setState(ClientAdapter.State.kActive); - } while (true); - } - - // Dequeue from a queue (one of the three queues) - // Priority 1. Failed sending queue - segmentToSend = sm.get_failed_sending(); - // Priority 2. Send control queue - // Priority 3. Send data queue - if (segmentToSend == null) { - segmentToSend = sm.dequeue(kDeqSendControlData); - } - - if (segmentToSend == null) { - // Nothing to send. - // SegmentManager::wake_up_dequeue_waiting() function may make this case - continue; - } - - int state = self.getState(); - if (state == ClientAdapter.State.kDisconnecting || state == ClientAdapter.State - .kDisconnected || isDisconnectingOnPurpose()) { - sm.failed_sending(segmentToSend); - continue; - } - - // If it is suspended, push the segment to the send-fail queue - { - boolean sender_suspended; - synchronized (mSenderSuspended) { - sender_suspended = mSenderSuspended; - } - if (sender_suspended) { - Logger.VERB(kTag, "Sending segment is pushed to failed queue at " + this - .getName() + " (suspended)"); - sm.failed_sending(segmentToSend); - continue; - } - } - - Logger.DEBUG(ClientAdapter.this.getName(), "SEND Segment " + segmentToSend.seq_no - + " / " + segmentToSend.len + "" + " / " + segmentToSend.flag); - - int res = send(segmentToSend.data, kSegHeaderSize + kSegSize); - if (res < 0) { - Logger.WARN(kTag, "Sending failed at " + ClientAdapter.this.getName()); - sm.failed_sending(segmentToSend); - break; - } - sm.free_segment(segmentToSend); - } - } - - public void finish() { - synchronized (this.mIsOn) { - this.mIsOn = false; - } - synchronized (this.mIsSuspended) { - this.mIsSuspended = false; - } - } - - SenderThread() { - this.mIsOn = false; - this.mIsSuspended = false; - } - - public boolean isOn() { - return this.mIsOn; - } - - private Boolean mIsOn; - private Boolean mIsSuspended; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - class ReceiverThread extends Thread { - @Override - public void run() { - this.setName(self.getName() + "/Receiver"); - synchronized (this.mIsOn) { - this.mIsOn = true; - } - synchronized (self.mIsWaitReceiverThread) { - self.mIsWaitReceiverThread = false; - } - - this.receiverThreadLoop(self); - - synchronized (self.mIsWaitReceiverThread) { - if (self.mIsWaitReceiverThread) { - self.mWaitReceiverThread.notifyAll(); - } - } - } - - private int mReceiveCount = 0; - private Date mDates[] = new Date[5]; - private long mIntervals[] = new long[4]; - - public void receiverThreadLoop(ClientAdapter adapter) { - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Receiver thread starts"); - byte prevData[] = new byte[SegmentManager.kSegSize + SegmentManager.kSegHeaderSize]; - - while (this.isOn()) { - if (VERBOSE_RECEIVER_TIME) this.mDates[0] = new Date(); - - SegmentManager sm = SegmentManager.singleton(); - Segment segmentToReceive = sm.get_free_segment(); - int len = kSegSize + kSegHeaderSize; - - if (VERBOSE_RECEIVER_TIME) this.mDates[1] = new Date(); - - if (VERBOSE_CLIENT_ADAPTER) { - Logger.DEBUG(kTag, adapter.getName() + ": Receiving..."); - } - int res = adapter.receive(segmentToReceive.data, len); - if (res < len) { - Logger.WARN(kTag, "Receiving failed at " + adapter.getName()); - break; - } - - if (VERBOSE_RECEIVER_TIME) this.mDates[2] = new Date(); - - // Read segment metadata - ByteBuffer buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 0, 4); - segmentToReceive.seq_no = buffer.getInt(0); - - buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 4, 4); - segmentToReceive.len = buffer.getInt(0); - - buffer = ByteBuffer.allocate(4); - buffer.put(segmentToReceive.data, 8, 4); - segmentToReceive.flag = buffer.getInt(0); - - //Logger.DEBUG(kTag, "RECEIVE " + segmentToReceive.seq_no + " / " + - // segmentToReceive.len + " / " + segmentToReceive.flag); - - if (VERBOSE_RECEIVER_TIME) this.mDates[3] = new Date(); - - boolean is_control = ((segmentToReceive.flag & kSegFlagControl) != 0); - - if (VERBOSE_SEGMENT_DEQUEUE_CTRL && is_control) { - Logger.DEBUG(getName(), "Receive Segment: seqno=" + segmentToReceive.seq_no + - " / type=ctrl"); - } - if (VERBOSE_SEGMENT_DEQUEUE_DATA && !is_control) { - Logger.DEBUG(getName(), "Receive Segment: seqno=" + segmentToReceive.seq_no + - " / type=data"); - } - - if (is_control) { - sm.enqueue(kSQRecvControl, segmentToReceive); - } else { - sm.enqueue(kSQRecvData, segmentToReceive); - } - - if (VERBOSE_RECEIVER_TIME) this.mDates[4] = new Date(); - - if (VERBOSE_RECEIVER_TIME) { - this.mReceiveCount++; - for (int i = 0; i < 4; i++) { - this.mIntervals[i] += this.mDates[i + 1].getTime() - this.mDates[i] - .getTime(); - } - if (this.mReceiveCount % 500 == 0) { - Log.d(kTag, "Receive Time " + this.mIntervals[0] + " / " + this - .mIntervals[1] + " / " + this.mIntervals[2] + " / " + this - .mIntervals[3]); - for (int i = 0; i < 4; i++) { - this.mIntervals[i] = 0; - } - } - } - } - -// NetworkSwitcher.singleton().reconnectAdapter(ClientAdapter.this); - Logger.VERB(kTag, ClientAdapter.this.getName() + "'s Receiver thread ends"); - } - - public void finish() { - synchronized (this.mIsOn) { - this.mIsOn = false; - } - } - - ReceiverThread() { - this.mIsOn = false; - } - - public boolean isOn() { - return this.mIsOn; - } - - private Boolean mIsOn; - } - - private SenderThread mSenderThread; - private ReceiverThread mReceiverThread; - private Boolean mSenderSuspended; - - private Boolean mIsWaitSenderThread; - private Boolean mIsWaitReceiverThread; - private Object mWaitSenderThread = new Object(); - private Object mWaitReceiverThread = new Object(); - - @SuppressWarnings("SynchronizeOnNonFinalField") - public boolean sleep(boolean isSendRequest) { - int state = this.getState(); - if (state != State.kActive) { - Logger.ERR(kTag, "Failed to sleep: " + this.getName() + "(state: " + state + ")"); - return false; - } - - synchronized (this.mSenderSuspended) { - if (this.mSenderSuspended) { - Logger.ERR(kTag, "Sender has already been suspended!: " + this.getName()); - return false; - } else { - if (isSendRequest) { - // Send Request - Core.singleton().getControlMessageSender().sendRequestSleep(this.getId()); - } - - // Sleep - this.setState(State.kGoingSleep); - this.mSenderSuspended = true; - - // Wake up sender thread waiting segment queue - SegmentManager sm = SegmentManager.singleton(); - sm.wakeUpDequeueWaiting(kDeqSendControlData); - return true; - } - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - public boolean wakeUp(boolean isSendRequest) { - int state = this.getState(); - if (state != State.kSleeping) { - Logger.ERR(kTag, "Failed to wake up: " + this.getName() + "(state: " + state + ")"); - return false; - } - boolean sender_suspended; - synchronized (this.mSenderSuspended) { - sender_suspended = this.mSenderSuspended; - } - if (sender_suspended) { - // Send Request - Core.singleton().getControlMessageSender().sendRequestWakeup(this.getId()); - - // Wake up - this.setState(State.kWakingUp); - this.wakeUpInternal(); - - return true; - } else { - Logger.ERR(kTag, "Sender has not been suspended!: " + this.getName()); - return false; - } - } - - private void wakeUpInternal() { - synchronized (this.mSenderSuspended) { - this.mSenderSuspended = false; - this.mSenderSuspended.notifyAll(); - } - } - - // Initialize - public ClientAdapter(int id, String name) { - this.mId = id; - this.mName = name; - this.mState = State.kDisconnected; - this.mListeners = new ArrayList<>(); - this.mSenderSuspended = false; - this.mIsDisconnectingOnPurpose = false; - this.mIsDisconnectingOnPurposePeer = false; - this.mIsWaitReceiverThread = false; - this.mIsWaitSenderThread = false; - - this.mSenderThread = new SenderThread(); - this.mReceiverThread = new ReceiverThread(); - } - - protected void initialize(Device device, P2PClient p2pClient, ClientSocket clientSocket) { - this.mDevice = device; - this.mP2PClient = p2pClient; - this.mClientSocket = clientSocket; - } - - // Attribute getters - public int getId() { - return this.mId; - } - - public String getName() { - return this.mName; - } - - public boolean isDisconnectingOnPurpose() { - return this.mIsDisconnectingOnPurpose; - } - - public boolean isDisconnectingOnPurposePeer() { - return this.mIsDisconnectingOnPurposePeer; - } - - // Attribute setters - public void startDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurpose = true; - } - - public void waitForDisconnectingOnPurposePeer() { - synchronized (mWaitForDisconnectAck) { - try { - mWaitForDisconnectAck.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void peerKnowsDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurposePeer = true; - synchronized (this.mWaitForDisconnectAck) { - this.mWaitForDisconnectAck.notifyAll(); - } - } - - private void finishDisconnectingOnPurpose() { - this.mIsDisconnectingOnPurpose = false; - this.mIsDisconnectingOnPurposePeer = false; - } - - // Attributes - private int mId; - private String mName; - - // Disconnecting on purpose by a device - private boolean mIsDisconnectingOnPurpose; - private boolean mIsDisconnectingOnPurposePeer; - private Object mWaitForDisconnectAck = new Object(); - - // State - class State { - public static final int kDisconnected = 0; - public static final int kConnecting = 1; - public static final int kActive = 2; - public static final int kDisconnecting = 3; - public static final int kGoingSleep = 4; - public static final int kSleeping = 5; - public static final int kWakingUp = 6; - public static final int kASNum = 7; - } - - public static String stateToString(int state) { - final String[] stateStr = {"Disconnected", "Connecting", "Active", "Disconnecting", - "GoingSleep", "Sleeping", "WakingUp"}; - if (state >= State.kASNum || state < 0) { - return ""; - } else { - return stateStr[state]; - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - public int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - int oldState; - synchronized (this.mState) { - oldState = this.mState; - this.mState = newState; - } - - Logger.DEBUG(this.getName(), "State(" + stateToString(oldState) + "->" + stateToString - (newState) + ")"); - - for (ClientAdapterStateListener listener : this.mListeners) { - listener.onUpdateClientAdapterState(this, oldState, newState); - } - } - - public void listenState(ClientAdapterStateListener listener) { - synchronized (this.mListeners) { - this.mListeners.add(listener); - } - } - - // State - private Integer mState; - - // State Listener - private final ArrayList mListeners; - - // Main Components : Device, P2PClient, ClientSocket - private Device mDevice; - private P2PClient mP2PClient; - - private ClientSocket mClientSocket; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java deleted file mode 100644 index c12efee6..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientAdapterStateListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public interface ClientAdapterStateListener { - void onUpdateClientAdapterState(ClientAdapter adapter, int oldState, int newState); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java deleted file mode 100644 index 8fe485c9..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ClientSocket.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -public abstract class ClientSocket { - private final String kTag = "ClientSocket"; - - // Main Functions - public boolean open() { - if (this.getState() != State.kClosed) { - Logger.ERR(kTag, "It's already opened or opening/closing is in progress"); - return false; - } - - this.setState(State.kOpening); - boolean res = this.openImpl(); - if (!res) { - this.setState(State.kClosed); - } else { - this.setState(State.kOpened); - } - return res; - } - - public boolean close() { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "It's already closed or opening/closing is in progress"); - return false; - } - - this.setState(State.kClosing); - boolean res = this.closeImpl(); - this.setState(State.kClosed); - - return res; - } - - public int send(byte[] dataBuffer, int dataLength) { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "Socket is not opened"); - return -1; - } - - int res = this.sendImpl(dataBuffer, dataLength); - if (res < 0) { - this.setState(State.kClosed); - } - return res; - } - - public int receive(byte[] dataBuffer, int dataLength) { - if (this.getState() != State.kOpened) { - Logger.ERR(kTag, "Socket is not opened"); - return -1; - } - - int res = this.receiveImpl(dataBuffer, dataLength); - if (res < 0) { - this.setState(State.kClosed); - } - return res; - } - - // Implemented by child classes - protected abstract boolean openImpl(); - - protected abstract boolean closeImpl(); - - protected abstract int sendImpl(byte[] dataBuffer, int dataLength); - - protected abstract int receiveImpl(byte[] dataBuffer, int dataLength); - - // State - class State { - public static final int kClosed = 0; - public static final int kOpening = 1; - public static final int kOpened = 2; - public static final int kClosing = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - protected ClientSocket() { - } - - // Attributes - - // State - private Integer mState = State.kClosed; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java deleted file mode 100644 index a5ab60cd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ - -// Control Message Listener -public interface ControlMessageListener { - void onReceiveControlMessage(int privateType, String privateMessage); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java deleted file mode 100644 index 7b4c16c6..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageProtocol.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageProtocol { - // Control Request Code - class CMCode { - public static final char kConnect = 1; - public static final char kSleep = 2; - public static final char kWakeup = 3; - public static final char kDisconnect = 4; - public static final char kPriv = 10; - public static final char kDisconnectAck = 24; - } - - // Priv Type Code - public class PrivType { - public static final char kWFDInfo = 1; - public static final char kWFDUnknown = 999; - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java deleted file mode 100644 index 6be22426..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageReceiver.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.redcarrottt.sc.internal; - -import android.util.Log; - -import com.redcarrottt.testapp.Logger; - -import java.util.ArrayList; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageReceiver { - private static final String kTag = "ControlMessageReceiver"; - private static final String kThreadName = "Control Message Receiving"; - - public void startReceivingThread() { - this.mReceivingThread = new ReceivingThread(); - this.mReceivingThread.start(); - } - - public void stopReceivingThread() { - this.mReceivingThread.finish(); - } - - // Thread - private class ReceivingThread extends Thread { - @Override - public void run() { - this.setName("ControlMsgReceiver"); - this.mIsOn = true; - Logger.THREAD_LAUNCH(kThreadName); - - while (this.mIsOn) { - this.loopInternal(); - } - - Logger.THREAD_FINISH(kThreadName); - this.mIsOn = false; - } - - public boolean loopInternal() { - byte[] messageBuffer = new byte[10 * 1024]; - int res = Core.singleton().receive(messageBuffer, true); - if (res <= 0) { - return false; - } - - String message = new String(messageBuffer).trim(); - - // Find separator location (between first line and other lines) - Log.d(kTag, "Control message incoming: " + message); - int separatorPos = message.indexOf('\n'); - - // Divide the message into first line & other lines - String firstLine = message.substring(0, separatorPos); - String otherLines = message.substring(separatorPos + 1); - - int controlMessageCode = Integer.parseInt(firstLine); - - switch (controlMessageCode) { - case ControlMessageProtocol.CMCode.kConnect: - case ControlMessageProtocol.CMCode.kSleep: - case ControlMessageProtocol.CMCode.kWakeup: - case ControlMessageProtocol.CMCode.kDisconnectAck: { - // Normal type - int adapterId = Integer.parseInt(otherLines); - onReceiveNormalMessage(controlMessageCode, adapterId); - break; - } - case ControlMessageProtocol.CMCode.kDisconnect: { - // Disconnect type - // Divide the message into second line, third line, fourth line - separatorPos = otherLines.indexOf('\n'); - String secondLine = otherLines.substring(0, separatorPos); - String thirdFourthLine = otherLines.substring(separatorPos + 1); - separatorPos = thirdFourthLine.indexOf('\n'); - String thirdLine = thirdFourthLine.substring(0, separatorPos); - String fourthLine = thirdFourthLine.substring(separatorPos + 1); - - int adapterId = Integer.parseInt(secondLine); - int finalSeqNoControl = Integer.parseInt(thirdLine); - int finalSeqNoData = Integer.parseInt(fourthLine); - - onReceiveDisconnectMessage(adapterId, finalSeqNoControl, finalSeqNoData); - break; - } - case ControlMessageProtocol.CMCode.kPriv: { - // Priv type - onReceivePrivateMessage(otherLines); - break; - } - default: { - Logger.ERR(kTag, "Unknown control message code (" + controlMessageCode + ")" - + "!\n" + message); - break; - } - } - - return true; - } - - public void finish() { - this.mIsOn = false; - } - - // Constructor - public ReceivingThread() { - this.mIsOn = false; - } - - // Attributes - private boolean mIsOn; - } - - private void onReceiveNormalMessage(int controlMessageCode, int adapterId) { - switch (controlMessageCode) { - case ControlMessageProtocol.CMCode.kConnect: { - Logger.VERB(kTag, "Receive(Control Msg): Request(Connect " + adapterId + ")"); - NetworkSwitcher.singleton().connectAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kSleep: { - Logger.VERB(kTag, "Receive(Control Msg): Request(Sleep " + adapterId + ")"); - NetworkSwitcher.singleton().sleepAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kWakeup: { - Logger.VERB(kTag, "Receive(Control Msg): Request(WakeUp " + adapterId + ")"); - NetworkSwitcher.singleton().wakeUpAdapterByPeer(adapterId); - break; - } - case ControlMessageProtocol.CMCode.kDisconnectAck: { - Logger.VERB(kTag, "Receive(Control Msg): Request(DisconenctAck " + adapterId + ")"); - ClientAdapter disconnectAdapter = Core.singleton().findAdapterById(adapterId); - if (disconnectAdapter == null) { - Logger.WARN(kTag, "Cannot find adapter " + adapterId); - } else { - disconnectAdapter.peerKnowsDisconnectingOnPurpose(); - } - break; - } - } - } - - private void onReceiveDisconnectMessage(int adapterId, int finalSeqNoControl, int - finalSeqNoData) { - Logger.VERB(kTag, "Receive(Control Msg): Request(Disconnect " + adapterId + " / " + - "final_seq_no_control=" + finalSeqNoControl + " / final_seq_no_data=" + - finalSeqNoData + ")"); - NetworkSwitcher.singleton().disconnectAdapterByPeer(adapterId, finalSeqNoControl, - finalSeqNoData); - } - - private void onReceivePrivateMessage(String contents) { - // Find separator location - int separatorPos = contents.indexOf('\n'); - - // Divide the message into second line & other lines - String secondLine = contents.substring(0, separatorPos); - String privateMessage = contents.substring(separatorPos + 1); - - int privateType = Integer.parseInt(secondLine); - - // Notify the private message - for (ControlMessageListener listener : mControlMessageListeners) { - listener.onReceiveControlMessage(privateType, privateMessage); - } - } - - public void addControlMessageListener(ControlMessageListener listener) { - this.mControlMessageListeners.add(listener); - } - - public ControlMessageReceiver() { - this.mReceivingThread = null; - this.mControlMessageListeners = new ArrayList<>(); - } - - // Attributes - private ReceivingThread mReceivingThread; - private ArrayList mControlMessageListeners; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java deleted file mode 100644 index 82786e39..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ControlMessageSender.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.redcarrottt.sc.internal; - -import com.redcarrottt.testapp.Logger; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ControlMessageSender { - private static final String kTag = "ControlMessageSender"; - - public void sendRequestConnect(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kConnect, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(Connect " + adapterId + ")"); - } - - public void sendRequestDisconnect(int adapterId, int final_seq_no_control, int - final_seq_no_data) { - String message = "" + ControlMessageProtocol.CMCode.kDisconnect + "\n" + adapterId + "\n" - + final_seq_no_control + "\n" + final_seq_no_data; - this.sendControlMessage(message); - Logger.VERB(kTag, "Send(Control Msg): Request(Disconnect " + adapterId + "; " + - "final_seq_no_control=" + final_seq_no_control + "; final_seq_no_data=" + - final_seq_no_data + ")"); - } - - public void sendRequestDisconnectAck(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kDisconnectAck, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(DisconnectAck " + adapterId + ")"); - } - - public void sendRequestSleep(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kSleep, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(Sleep " + adapterId + ")"); - } - - public void sendRequestWakeup(int adapterId) { - this.sendRequest(ControlMessageProtocol.CMCode.kWakeup, adapterId); - Logger.VERB(kTag, "Send(Control Msg): Request(WakeUp " + adapterId + ")"); - } - - public void sendNotiPrivateData(int privateType, String privateMessage) { - String message = "" + ControlMessageProtocol.CMCode.kPriv + "\n" + privateType + "\n" + - privateMessage; - this.sendControlMessage(message); - } - - private void sendRequest(int requestCode, int adapterId) { - String message = "" + requestCode + "\n" + adapterId; - this.sendControlMessage(message); - } - - private void sendControlMessage(String controlMessage) { - byte[] messageBuffer = controlMessage.getBytes(); - Core.singleton().send(messageBuffer, messageBuffer.length, true); - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java deleted file mode 100644 index 56e43997..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Core.java +++ /dev/null @@ -1,357 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.sc.api.OnStartSCResult; -import com.redcarrottt.sc.api.OnStopSCResult; -import com.redcarrottt.testapp.Logger; - -import java.util.ArrayList; - -public class Core { - private static final String kTag = "Core"; - - // APIs: These functions are mapped to ones in API. - public void start(OnStartSCResult resultListener) { - if (this.getState() != State.kIdle) { - Logger.ERR(kTag, "Core has already started"); - doneStart(false, resultListener); - return; - } else if (this.mAdapters.isEmpty()) { - Logger.ERR(kTag, "No adapter is registered!"); - doneStart(false, resultListener); - return; - } - this.setState(State.kStarting); - runStartCoreTx(this, resultListener); - } - - private void doneStart(boolean isSuccess, OnStartSCResult resultListener) { - if (isSuccess) { - Logger.VERB(kTag, "Succeed to start core!"); - this.setState(State.kReady); - - // Launch control message receiving thread - this.mControlMessageReceiver.startReceivingThread(); - } else { - Logger.ERR(kTag, "Failed to start core!"); - this.setState(State.kIdle); - } - if (resultListener != null) resultListener.onDoneStartSC(isSuccess); - } - - public void stop(OnStopSCResult resultListener) { - int state = this.getState(); - if (state == State.kStarting || state == State.kStopping) { - Logger.ERR(kTag, "Cannot stop core during starting/stopping!"); - doneStop(false, resultListener); - return; - } else if (state == State.kIdle) { - Logger.ERR(kTag, "Core is already idle state!"); - doneStop(false, resultListener); - return; - } else if (this.mAdapters.isEmpty()) { - Logger.ERR(kTag, "No adapter is registered!"); - doneStop(false, resultListener); - return; - } - - this.setState(State.kStopping); - runStopCoreTx(this, resultListener); - } - - private void doneStop(boolean isSuccess, OnStopSCResult resultListener) { - if (isSuccess) { - Logger.VERB(kTag, "Succeed to stop core!"); - this.setState(State.kIdle); - - // Finish control message receiving thread - this.mControlMessageReceiver.stopReceivingThread(); - } else { - Logger.ERR(kTag, "Failed to stop core!"); - this.setState(State.kReady); - } - if (resultListener != null) resultListener.onDoneStopSC(isSuccess); - } - - public void registerAdapter(ClientAdapter adapter) { - if (this.getState() != State.kIdle) { - Logger.ERR(kTag, "You can register adapter on only idle state!"); - return; - } - - synchronized (this.mAdapters) { - this.mAdapters.add(adapter); - } - } - - public int send(byte[] dataBuffer, int dataLength, boolean isControl) { - int state = this.getState(); - if (state != State.kReady) { - Logger.ERR(kTag, "Core is not started yet, so you cannot send the data"); - return -1; - } - - int currOffset = 0; - - // Attach the protocol header to the payload - ProtocolData protocolData = ProtocolManager.data_to_protocol_data(dataBuffer, dataLength); - if (protocolData == null) throw new AssertionError(); - - int packetSize = ProtocolManager.serialize(protocolData, dataBuffer, currOffset, - dataLength); - if (!(packetSize > 0)) { - Logger.ERR(kTag, "Failed to make protocol data to send(" + currOffset + "/" + - dataLength + ")"); - throw new AssertionError(); - } - - int sentBytes = ProtocolManager.send_packet(packetSize, isControl); - if (sentBytes < 0) { - Logger.ERR(kTag, "Sending stopped (" + currOffset + "/" + dataLength + ") by " + - sentBytes); - throw new AssertionError(); - } - - return sentBytes; - } - - public int receive(byte[] dataBuffer, boolean isControl) { - int state = this.getState(); - if (state != State.kReady) { - Logger.ERR(kTag, "Core is not started yet, so you cannot receive data"); - return -1; - } - - return ProtocolManager.recv_packet(dataBuffer, isControl); - } - - // State - class State { - public static final int kIdle = 0; - public static final int kStarting = 1; - public static final int kReady = 2; - public static final int kStopping = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - - // Adapters Getter - public ClientAdapter findAdapterById(int adapterId) { - for (ClientAdapter adapter : this.mAdapters) { - if (adapter.getId() == adapterId) { - return adapter; - } - } - return null; - } - - public ControlMessageReceiver getControlMessageReceiver() { - return this.mControlMessageReceiver; - } - - public ControlMessageSender getControlMessageSender() { - return this.mControlMessageSender; - } - - // Components - private final ArrayList mAdapters; - private ControlMessageReceiver mControlMessageReceiver; - private ControlMessageSender mControlMessageSender; - - // State - private Integer mState; - - // Singleton - private static Core sSingleton; - - public static Core singleton() { - if (sSingleton == null) { - sSingleton = new Core(); - } - return sSingleton; - } - - // Constructor - private Core() { - this.mState = State.kIdle; - this.mAdapters = new ArrayList<>(); - this.mControlMessageReceiver = new ControlMessageReceiver(); - this.mControlMessageSender = new ControlMessageSender(); - } - - // Transactions - // ---------------------------------------------------------------- - // Singleton runner - private static void runStartCoreTx(Core caller, OnStartSCResult resultListener) { - if (sOngoingStartCore == null) { - sOngoingStartCore = new StartCoreTransaction(caller, resultListener); - sOngoingStartCore.start(); - } else { - Logger.WARN(kTag, "Already starting core"); - doneStartCoreTx(caller, false, resultListener); - } - } - - private static void doneStartCoreTx(Core caller, boolean isSuccess, OnStartSCResult - resultListener) { - sOngoingStartCore = null; - caller.doneStart(isSuccess, resultListener); - } - - private static void runStopCoreTx(Core caller, OnStopSCResult resultListener) { - if (sOngoingStopCore == null) { - sOngoingStopCore = new StopCoreTransaction(caller, resultListener); - sOngoingStopCore.start(); - } else { - Logger.WARN(kTag, "Already stopping core"); - doneStopCoreTx(caller, false, resultListener); - } - } - - private static void doneStopCoreTx(Core caller, boolean isSuccess, OnStopSCResult - resultListener) { - sOngoingStopCore = null; - caller.doneStop(isSuccess, resultListener); - } - - private static StartCoreTransaction sOngoingStartCore = null; - private static StopCoreTransaction sOngoingStopCore = null; - - // Start Core - private static class StartCoreTransaction { - // Private Constructor - private StartCoreTransaction(Core caller, OnStartSCResult resultListener) { - this.mCaller = caller; - this.mResultListener = resultListener; - this.onConnectFirstAdapter = new OnConnectFirstAdapter(); - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void start() { - // Connect first adapter - ClientAdapter firstAdapter = this.mCaller.mAdapters.get(0); - if (firstAdapter == null) { - Logger.ERR(kTag, "Cannot find first adapter"); - doneStartCoreTx(mCaller, false, mResultListener); - return; - } - firstAdapter.connect(this.onConnectFirstAdapter, false); - } - - private OnConnectFirstAdapter onConnectFirstAdapter; - - class OnConnectFirstAdapter implements ClientAdapter.ConnectResultListener { - @SuppressWarnings("SimplifiableIfStatement") - @Override - public void onConnectResult(boolean isSuccess) { - if (isSuccess) { - // Done transaction - doneStartCoreTx(mCaller, true, mResultListener); - } else { - Logger.ERR(kTag, "Connecting first adapter is failed"); - doneStartCoreTx(mCaller, false, mResultListener); - } - } - } - - // Attributes - private Core mCaller; - private OnStartSCResult mResultListener; - } - - // Stop Core - private static class StopCoreTransaction { - private StopCoreTransaction(Core caller, OnStopSCResult resultListener) { - this.mCaller = caller; - this.mResultListener = resultListener; - this.onDisconnectAdapter = new OnDisconnectAdapter(); - this.mAdaptersCount = 0; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - void start() { - // Get active adapter count - synchronized (this.mCaller.mAdapters) { - for (ClientAdapter adapter : this.mCaller.mAdapters) { - int adapterState = adapter.getState(); - if (adapterState != ClientAdapter.State.kDisconnected && adapterState != - ClientAdapter.State.kDisconnecting) { - this.mAdaptersCount++; - } - } - } - - // Disconnect only active adapters - synchronized (this.mCaller.mAdapters) { - for (ClientAdapter adapter : this.mCaller.mAdapters) { - int adapterState = adapter.getState(); - if (adapterState != ClientAdapter.State.kDisconnected && adapterState != - ClientAdapter.State.kDisconnecting) { - adapter.disconnectOnCommand(onDisconnectAdapter); - } - } - } - } - - private OnDisconnectAdapter onDisconnectAdapter; - - class OnDisconnectAdapter implements ClientAdapter.DisconnectResultListener { - @Override - public void onDisconnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Disconnecting adapter is failed"); - doneStopCoreTx(mCaller, false, mResultListener); - return; - } - - // Check if all the active adapters are disconnected - boolean doneDisconnectAll = false; - synchronized (mAdaptersCount) { - mAdaptersCount--; - if (mAdaptersCount == 0) { - doneDisconnectAll = true; - } - } - - if (doneDisconnectAll) { - doneStopCoreTx(mCaller, true, mResultListener); - } - } - } - - // Attributes - private Core mCaller; - private Integer mAdaptersCount; - private OnStopSCResult mResultListener; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java deleted file mode 100644 index f6c41ccd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/Device.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -interface TurnOnResultListener { - void onTurnOnResult(boolean isSuccess); -} - -interface TurnOffResultListener { - void onTurnOffResult(boolean isSuccess); -} - -public abstract class Device { - private final String kTag = "Device"; - - // Main Functions - @SuppressWarnings("SynchronizeOnNonFinalField") - void turnOn(TurnOnResultListener resultListener) { - this.mTurnOnResultListener = resultListener; - - this.setState(State.kTurningOn); - this.turnOnImpl(); - } - - private TurnOnResultListener mTurnOnResultListener; - - protected void doneTurnOn(boolean isSuccess) { - if (isSuccess) { - // Proceed state - this.setState(State.kOn); - } else { - this.setState(State.kOff); - } - - if (this.mTurnOnResultListener != null) { - this.mTurnOnResultListener.onTurnOnResult(isSuccess); - } - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - void turnOff(TurnOffResultListener resultListener) { - this.mTurnOffResultListener = resultListener; - - this.setState(State.kTurningOff); - this.turnOffImpl(); - } - - private TurnOffResultListener mTurnOffResultListener; - - protected void doneTurnOff(boolean isSuccess) { - if (isSuccess) { - // Proceed state - this.setState(State.kOff); - } else { - // Recover original state - this.setState(State.kOn); - } - - if (this.mTurnOffResultListener != null) { - this.mTurnOffResultListener.onTurnOffResult(isSuccess); - } - } - - // Implemented by child classes - protected abstract void turnOnImpl(); - - protected abstract void turnOffImpl(); - - // State - class State { - public static final int kOff = 0; - public static final int kTurningOn = 1; - public static final int kOn = 2; - public static final int kTurningOff = 3; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - public Device(String name) { - this.mState = State.kOff; - this.mName = name; - } - - // Attributes - private String mName; - - // State - private Integer mState; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java deleted file mode 100644 index 90137bbd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ExpConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class ExpConfig { - public static final boolean VERBOSE_SEGMENT_DEQUEUE_CTRL = true; - public static final boolean VERBOSE_SEGMENT_DEQUEUE_DATA = false; - public static final boolean VERBOSE_RECEIVER_TIME = false; - public static final boolean VERBOSE_CLIENT_ADAPTER = false; - public static final boolean VERBOSE_BANDWIDTH_UPDATE = false; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java deleted file mode 100644 index 5e44e560..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/NetworkSwitcher.java +++ /dev/null @@ -1,306 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -public class NetworkSwitcher { - private static final String kTag = "NetworkSwitcher"; - - // Connect adapter command. - // It is called by peer through Core. - void connectAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot connect to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - runConnectRequestTx(adapterId); - } - - // Disconnect adapter command. - // It is called by peer through Core. - void disconnectAdapterByPeer(int adapterId, int finalSeqNoControl, int finalSeqNoData) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot disconnect to adapter " + adapterId); - return; - } - - Core core = Core.singleton(); - ClientAdapter adapter = core.findAdapterById(adapterId); - if (adapter == null) { - Logger.WARN(kTag, "Cannot find adapter " + adapterId); - return; - } - - this.setState(State.kSwitching); - - adapter.disconnectOnPeerCommand(onResultDisconnectAdapterByPeer, finalSeqNoControl, finalSeqNoData); - } - - ClientAdapter.DisconnectResultListener onResultDisconnectAdapterByPeer = new ClientAdapter - .DisconnectResultListener() { - @Override - public void onDisconnectResult(boolean isSuccess) { - NetworkSwitcher switcher = NetworkSwitcher.singleton(); - switcher.doneSwitch(); - } - }; - - // Sleep adapter command. - // It is called by peer through Core. - void sleepAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot sleep to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - ClientAdapter adapter = Core.singleton().findAdapterById(adapterId); - adapter.sleep(false); - this.setState(State.kReady); - } - - // Wake up adapter command. - // It is called by peer through Core. - void wakeUpAdapterByPeer(int adapterId) { - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, "It's now switching. Cannot sleep to adapter " + adapterId); - return; - } - this.setState(State.kSwitching); - ClientAdapter adapter = Core.singleton().findAdapterById(adapterId); - adapter.wakeUp(false); - this.setState(State.kReady); - } - - // Reconnect adapter command. - // It is called by Core. - void reconnectAdapter(ClientAdapter adapter) { - // If it is disconnecting on purpose, do not reconnect it. - if (adapter.isDisconnectingOnPurpose()) { - return; - } - - int state = this.getState(); - if (state == State.kSwitching) { - Logger.VERB(kTag, adapter.getName() + ": It's now switching. Cannot reconnect " + - "adapter" + "."); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - this.reconnectAdapter(adapter); - return; - } - this.setState(State.kSwitching); - runReconnectAdapterTx(adapter); - } - - // Notification of switch done event - private void doneSwitch() { - int state = this.getState(); - switch (state) { - case State.kSwitching: - this.setState(State.kReady); - break; - case State.kReady: - break; - } - } - - // State Getter/Setter - @SuppressWarnings("SynchronizeOnNonFinalField") - private int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - class State { - public static final int kReady = 0; - public static final int kSwitching = 1; - } - - // State - private Integer mState; - - // Singleton - private static NetworkSwitcher sSingleton; - - public static NetworkSwitcher singleton() { - if (sSingleton == null) { - sSingleton = new NetworkSwitcher(); - } - return sSingleton; - } - - // Constructor - private NetworkSwitcher() { - // Since there is no NetworkSwitcher for Android implementation, - // NetworkSwitcher's initial state goes to Running at beginning. - this.mState = State.kReady; - } - - // Transactions - // ---------------------------------------------------------------- - // Singleton runner - private static boolean runConnectRequestTx(int adapterId) { - if (sOngoingConnectRequest == null) { - sOngoingConnectRequest = new ConnectRequestTransaction(adapterId); - sOngoingConnectRequest.start(); - return true; - } else { - Logger.WARN(kTag, "Already connecting"); - return false; - } - } - - private static void doneConnectRequestTx(boolean isSuccess) { - sOngoingConnectRequest = null; - if (!isSuccess) { - Logger.WARN(kTag, "Connection request failed"); - } - NetworkSwitcher.singleton().doneSwitch(); - sOngoingConnectRequest = null; - } - - private static void runReconnectAdapterTx(ClientAdapter adapter) { - if (sOngoingReconnectAdapter == null) { - sOngoingReconnectAdapter = new ReconnectAdapterTransaction(adapter); - sOngoingReconnectAdapter.start(); - } else { - Logger.WARN(kTag, "Already stopping core"); - } - } - - private static void restartReconnectAdapterTx(ClientAdapter adapter) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - sOngoingReconnectAdapter = null; - runReconnectAdapterTx(adapter); - } - - private static ConnectRequestTransaction sOngoingConnectRequest = null; - private static ReconnectAdapterTransaction sOngoingReconnectAdapter = null; - - private static class ConnectRequestTransaction { - private ConnectRequestTransaction(int adapterId) { - this.mAdapterId = adapterId; - this.onConnectAdapter = new OnConnectAdapter(); - } - - void start() { - ClientAdapter adapter = Core.singleton().findAdapterById(this.mAdapterId); - if (adapter == null) { - Logger.ERR(kTag, "Connecting requested adapter is failed"); - doneConnectRequestTx(false); - return; - } - adapter.connect(onConnectAdapter, false); - } - - private OnConnectAdapter onConnectAdapter; - - class OnConnectAdapter implements ClientAdapter.ConnectResultListener { - @Override - public void onConnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Connecting requested adapter is failed"); - doneConnectRequestTx(false); - return; - } - Logger.VERB(kTag, "Connecting requested adapter is done"); - doneConnectRequestTx(true); - } - } - - private int mAdapterId; - } - - private static class ReconnectAdapterTransaction { - private ReconnectAdapterTransaction(ClientAdapter targetAdapter) { - this.onConnectAdapter = new OnConnectAdapter(); - this.onDisconnectAdapter = new OnDisconnectAdapter(); - this.mTargetAdapter = targetAdapter; - } - - private ClientAdapter mTargetAdapter; - - void start() { - if (this.mTargetAdapter == null) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - this.mTargetAdapter.disconnectOnFailure(onDisconnectAdapter); - } - - private OnDisconnectAdapter onDisconnectAdapter; - - class OnDisconnectAdapter implements ClientAdapter.DisconnectResultListener { - @Override - public void onDisconnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - if (mTargetAdapter == null) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - - mTargetAdapter.connect(onConnectAdapter, false); - } - } - - private OnConnectAdapter onConnectAdapter; - - class OnConnectAdapter implements ClientAdapter.ConnectResultListener { - @Override - public void onConnectResult(boolean isSuccess) { - if (!isSuccess) { - Logger.ERR(kTag, "Reconnecting adapter is failed: retry"); - restartReconnectAdapterTx(mTargetAdapter); - return; - } - - Logger.VERB(kTag, "Reconnecting adapter is done"); - NetworkSwitcher.singleton().doneSwitch(); - } - } - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java deleted file mode 100644 index 460aa60f..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnConnectResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnConnectResult { - public void onDoneConnect(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java deleted file mode 100644 index a6848747..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDisconnectResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnDisconnectResult { - public void onDoneDisconnect(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java deleted file mode 100644 index 767da676..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/OnDiscoverResult.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redcarrottt.sc.internal; - -public interface OnDiscoverResult { - public void onDoneDiscover(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java deleted file mode 100644 index 3a8b2af9..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/P2PClient.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -interface DiscoverAndConnectResultListener { - void onDiscoverAndConnectResult(boolean isSuccess); -} - -interface DisconnectResultListener { - void onDisconnectResult(boolean isSuccess); -} - -public abstract class P2PClient { - private final String kTag = "P2PClient"; - - // Main function 1: Discover and connect - public void discoverAndConnect(DiscoverAndConnectResultListener resultListener) { - if (this.getState() != State.kDisconnected) { - Logger.ERR(kTag, "It's already connected or discovering is in progress"); - doneDiscoverAndConnectTx(resultListener, false); - return; - } - runDiscoverAndConnectTx(resultListener); - } - - private void runDiscoverAndConnectTx(DiscoverAndConnectResultListener resultListener) { - if (sOngoingDiscoverConnectTx == null) { - sOngoingDiscoverConnectTx = new DiscoverAndConnectTransaction(); - sOngoingDiscoverConnectTx.start(resultListener); - } else { - Logger.ERR(kTag, "Discover/Connect has already been in progress."); - doneDiscoverAndConnectTx(resultListener, false); - } - } - - private void doneDiscoverAndConnectTx(DiscoverAndConnectResultListener resultListener, - boolean isSuccess) { - sOngoingDiscoverConnectTx = null; - if (isSuccess) { - this.setState(State.kConnected); - } else { - this.setState(State.kDisconnected); - } - - if (resultListener != null) { - resultListener.onDiscoverAndConnectResult(isSuccess); - } - } - - private static DiscoverAndConnectTransaction sOngoingDiscoverConnectTx = null; - - class DiscoverAndConnectTransaction { - private DiscoverAndConnectResultListener mResultListener; - - DiscoverAndConnectTransaction() { - } - - void start(DiscoverAndConnectResultListener resultListener) { - this.mResultListener = resultListener; - - setState(State.kDiscovering); - discoverImpl(onDiscoverResult); - } - - private OnDiscoverResult onDiscoverResult = new OnDiscoverResult() { - @Override - public void onDoneDiscover(boolean isSuccess) { - if (isSuccess) { - setState(State.kConnecting); - connectImpl(onConnectResult); - } else { - doneDiscoverAndConnectTx(mResultListener, false); - } - } - }; - - private OnConnectResult onConnectResult = new OnConnectResult() { - @Override - public void onDoneConnect(boolean isSuccess) { - doneDiscoverAndConnectTx(mResultListener, isSuccess); - } - }; - } - - // Main function 2: Disconnect - public void disconnect(DisconnectResultListener resultListener) { - int state = this.getState(); - if (state == State.kDisconnected || state == State.kDisconnecting) { - Logger.ERR(kTag, "It's already disconnected or disconnecting is in progress"); - doneDisconnectTx(resultListener, false); - return; - } - runDisconnectTx(resultListener); - } - - private void runDisconnectTx(DisconnectResultListener resultListener) { - if (sOngoingDisconnectTx == null) { - sOngoingDisconnectTx = new DisconnectTransaction(); - sOngoingDisconnectTx.start(resultListener); - } else { - Logger.ERR(kTag, "Disconnection has already been in progress."); - doneDisconnectTx(resultListener, false); - } - } - - private void doneDisconnectTx(DisconnectResultListener resultListener, boolean isSuccess) { - sOngoingDisconnectTx = null; - if (isSuccess) { - this.setState(State.kDisconnected); - } else { - this.setState(State.kConnected); - } - if (resultListener != null) { - resultListener.onDisconnectResult(isSuccess); - } - } - - private static DisconnectTransaction sOngoingDisconnectTx = null; - - class DisconnectTransaction { - private DisconnectResultListener mResultListener; - - DisconnectTransaction() { - } - - void start(DisconnectResultListener resultListener) { - this.mResultListener = resultListener; - - setState(State.kDisconnecting); - disconnectImpl(onDisconnectResult); - } - - private OnDisconnectResult onDisconnectResult = new OnDisconnectResult() { - @Override - public void onDoneDisconnect(boolean isSuccess) { - doneDisconnectTx(mResultListener, isSuccess); - } - }; - - } - - // Implemented by child classes - protected abstract void discoverImpl(OnDiscoverResult onDiscoverResult); - - protected abstract void connectImpl(OnConnectResult onConnectResult); - - protected abstract void disconnectImpl(OnDisconnectResult onDisconnectResult); - - // State - class State { - public static final int kDisconnected = 0; - public static final int kDiscovering = 1; - public static final int kConnecting = 2; - public static final int kConnected = 3; - public static final int kDisconnecting = 4; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - protected int getState() { - int state; - synchronized (this.mState) { - state = this.mState; - } - return state; - } - - @SuppressWarnings("SynchronizeOnNonFinalField") - private void setState(int newState) { - synchronized (this.mState) { - this.mState = newState; - } - } - - protected P2PClient() { - this.mState = State.kDisconnected; - } - - // State - private Integer mState; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java deleted file mode 100644 index df47ef4a..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/ProtocolManager.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import java.nio.ByteBuffer; - -class ProtocolData { - short id; - int len; - byte[] data; - - ProtocolData() { - id = 0; - len = 0; - data = null; - } -} - -class ProtocolManager { - static public final int kProtocolHeaderSize = 6; - - static private short sPacketId; - static private byte[] sSerializedVector = null; - - static private void serialize_header(ProtocolData pd, byte[] vec_ptr) { - if (vec_ptr == null) throw new AssertionError(); - - int vec_offset = 0; - - ByteBuffer buffer = ByteBuffer.allocate(2); - - buffer.putShort(pd.id); - byte[] net_id = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(pd.len); - byte[] net_len = buffer.array(); - - System.arraycopy(net_id, 0, vec_ptr, vec_offset, 2); - vec_offset += 2; - - System.arraycopy(net_len, 0, vec_ptr, vec_offset, 4); - } - - static public ProtocolData data_to_protocol_data(byte[] buf, int len) { - ProtocolData pd = new ProtocolData(); - - pd.id = sPacketId++; - pd.len = len; - pd.data = buf; - - return pd; - } - - static public int serialize(ProtocolData protocolData, byte[] buf, int offset, int - payload_size) { - int vec_size; - int data_offset; - - data_offset = kProtocolHeaderSize; - vec_size = data_offset + payload_size; - - sSerializedVector = new byte[vec_size]; - - serialize_header(protocolData, sSerializedVector); - System.arraycopy(buf, offset, sSerializedVector, data_offset, payload_size); - - if (sSerializedVector == null) throw new AssertionError(); - - return vec_size; - } - - static void parse_header(byte[] serialized, ProtocolData protocolData) { - if (serialized == null || protocolData == null) throw new AssertionError(); - - int vec_offset = 0; - ByteBuffer buffer = ByteBuffer.allocate(2); - - buffer.put(serialized, vec_offset, 2); - protocolData.id = buffer.getShort(0); - vec_offset += 2; - - buffer = ByteBuffer.allocate(4); - buffer.put(serialized, vec_offset, 4); - protocolData.len = buffer.getInt(0); - } - - static public int send_packet(int packetSize, boolean isControl) { - SegmentManager sm = SegmentManager.singleton(); - - return sm.send_to_segment_manager(sSerializedVector, packetSize, isControl); - } - - static public int recv_packet(byte[] buf, boolean isControl) { - if (buf == null) throw new AssertionError(); - - ProtocolData protocolData = new ProtocolData(); - SegmentManager sm = SegmentManager.singleton(); - - byte[] data = sm.recv_from_segment_manager(protocolData, isControl); - - System.arraycopy(data, 0, buf, 0, (protocolData.len < buf.length) ? protocolData.len : - buf.length); - - - return protocolData.len; - } - -// private static String kTag = "protocol manager"; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java deleted file mode 100644 index 87e8a2bd..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/SegmentManager.java +++ /dev/null @@ -1,488 +0,0 @@ -package com.redcarrottt.sc.internal; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import com.redcarrottt.testapp.Logger; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.ListIterator; - -/* - Segment is the minimum unit of the sending data through the network. - Segment header (sequence # + len + flag) is 16bytes (4bytes + 4bytes + 4bytes) - */ -class Segment { - int seq_no; - int len; - int flag; - byte[] data; - - Segment() { - seq_no = -1; - len = 0; - flag = 0; - data = new byte[SegmentManager.kSegSize + SegmentManager.kSegHeaderSize]; - } -} - -class SegmentManager { - static private SegmentManager instance = null; - static public final int kSegSize = 512; - private static final int kSegFreeThreshold = 256; - - static public final int kSegHeaderSize = 12; - - static final int kSQSendData = 0; - static final int kSQRecvData = 1; - static final int kSQSendControl = 2; - static final int kSQRecvControl = 3; - private static final int kNumSQ = 4; - static final int kSQUnknown = 999; - - static final int kDeqSendControlData = 0; - static final int kDeqRecvData = 1; - static final int kDeqRecvControl = 2; - private static final int kNumDeq = 3; - - static final int kSNData = 0; - static final int kSNControl = 1; - private static final int kNumSN = 2; - - static final short kSegFlagMF = 1; - static final short kSegFlagControl = 2; - - private int[] mNextSeqNo; - private int[] mExpectedSeqNo; - - private LinkedList[] mQueues; - private Object[] mDequeueCond; - private final LinkedList mFailedSendingQueue; - private LinkedList[] mPendingQueue; - private int[] mQueueLengths; - - private static String kTag = "SegmentManager"; - - private final LinkedList mFreeSegments; - private int mFreeSegmentsSize; - - private SegmentManager() { - this.mQueues = new LinkedList[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mQueues[i] = new LinkedList(); - } - - this.mDequeueCond = new Object[kNumDeq]; - for (int i = 0; i < kNumDeq; i++) { - this.mDequeueCond[i] = new Object(); - } - - this.mFailedSendingQueue = new LinkedList(); - this.mPendingQueue = new LinkedList[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mPendingQueue[i] = new LinkedList(); - } - - this.mQueueLengths = new int[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mQueueLengths[i] = 0; - } - - this.mExpectedSeqNo = new int[kNumSQ]; - for (int i = 0; i < kNumSQ; i++) { - this.mExpectedSeqNo[i] = 0; - } - - this.mNextSeqNo = new int[kNumSN]; - for (int i = 0; i < kNumSN; i++) { - this.mNextSeqNo[i] = 0; - } - - this.mFreeSegments = new LinkedList(); - } - - - static public SegmentManager singleton() { - if (instance == null) instance = new SegmentManager(); - - return instance; - } - - private int getNextSeqNo(int seq_num_type, int length) { - int ret = mNextSeqNo[seq_num_type]; - mNextSeqNo[seq_num_type] += length; - return ret; - } - - // Wait data before disconnection - public void waitReceiving(int wait_seq_no_control, int wait_seq_no_data) { - synchronized (this.mWaitReceiving) { - this.mIsWaitReceiving = true; - this.mWaitSeqNoControl = wait_seq_no_control; - this.mWaitSeqNoData = wait_seq_no_data; - try { - this.mWaitReceiving.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public int getLastSeqNoControl() { - return this.mNextSeqNo[kSNControl] - 1; - } - - public int getLastSeqNoData() { - return this.mNextSeqNo[kSNData] - 1; - } - - private void checkReceivingDone() { - boolean is_wakeup = false; - synchronized (this.mWaitReceiving) { - if (this.mIsWaitReceiving && this.mExpectedSeqNo[kSQRecvControl] >= this - .mWaitSeqNoControl && this.mExpectedSeqNo[kSQRecvData] >= this.mWaitSeqNoData) { - is_wakeup = true; - } - - if (is_wakeup) { - this.mWaitReceiving.notifyAll(); - this.mIsWaitReceiving = false; - } - } - } - - public void wakeUpDequeueWaiting(int dequeueType) { - synchronized (mDequeueCond[dequeueType]) { - this.mDequeueCond[dequeueType].notifyAll(); - } - } - - boolean mIsWaitReceiving = false; - int mWaitSeqNoControl = 0; - int mWaitSeqNoData = 0; - Object mWaitReceiving = new Object(); - - public int send_to_segment_manager(byte[] data, int length, boolean isControl) { - if (data == null || length <= 0) throw new AssertionError(); - - int offset = 0; - int num_of_segments = (length + kSegSize - 1) / kSegSize; - int seq_num_type = (isControl) ? kSNControl : kSNData; - int allocated_seq_no = getNextSeqNo(seq_num_type, num_of_segments); - int seg_idx; - for (seg_idx = 0; seg_idx < num_of_segments; seg_idx++) { - int seg_len = (length - offset < kSegSize) ? (length - offset) : kSegSize; - Segment seg = get_free_segment(); - - // 0~3: seq_no - seg.seq_no = allocated_seq_no++; - - // 4~7: len - seg.len = seg_len; - - // 8~11: flag - int flag = 0; - if (offset + seg_len < length) flag = flag | kSegFlagMF; - if (isControl) flag = flag | kSegFlagControl; - seg.flag = flag; - - // 12~: data - System.arraycopy(data, offset, seg.data, kSegHeaderSize, seg_len); - offset += seg_len; - - serialize_segment_header(seg); - - if (isControl) { - enqueue(kSQSendControl, seg); - } else { - enqueue(kSQSendData, seg); - } - } - - return 0; - } - - private void serialize_segment_header(Segment segment) { - ByteBuffer buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.seq_no); - byte[] net_seq_no = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.len); - byte[] net_len = buffer.array(); - - buffer = ByteBuffer.allocate(4); - buffer.putInt(segment.flag); - byte[] net_flag = buffer.array(); - - System.arraycopy(net_seq_no, 0, segment.data, 0, 4); - System.arraycopy(net_len, 0, segment.data, 4, 4); - System.arraycopy(net_flag, 0, segment.data, 8, 4); - } - - public byte[] recv_from_segment_manager(ProtocolData protocolData, boolean isControl) { - if (protocolData == null) throw new AssertionError(); - - byte[] serialized; - int offset = 0; - int data_size; - boolean cont; - - Segment seg; - do { - if (isControl) { - seg = dequeue(kDeqRecvControl); - } else { - seg = dequeue(kDeqRecvData); - } - } while (seg == null); - ProtocolManager.parse_header(Arrays.copyOfRange(seg.data, kSegHeaderSize, seg.data - .length), protocolData); - if (protocolData.len == 0) return null; - - //Logger.DEBUG(kTag, "pd.len is " + pd.len); - serialized = new byte[protocolData.len]; - - // Handle the first segment of the data bulk, because it contains protocol data - data_size = seg.len - ProtocolManager.kProtocolHeaderSize; - System.arraycopy(seg.data, kSegHeaderSize + ProtocolManager.kProtocolHeaderSize, - serialized, offset, data_size); - offset += data_size; - - cont = ((seg.flag & kSegFlagMF) != 0); - free_segment(seg); - - while (cont) { - do { - if (isControl) { - seg = dequeue(kDeqRecvControl); - } else { - seg = dequeue(kDeqRecvData); - } - } while (seg == null); - data_size = seg.len; - System.arraycopy(seg.data, kSegHeaderSize, serialized, offset, data_size); - cont = ((seg.flag & kSegFlagMF) != 0); - offset += data_size; - free_segment(seg); - } - - return serialized; - } - - @SuppressWarnings("unchecked") - public void enqueue(int queueType, Segment segment) { - if (queueType >= kNumSQ) throw new AssertionError(); - - int dequeueType; - switch (queueType) { - case kSQRecvControl: - dequeueType = kDeqRecvControl; - break; - case kSQRecvData: - dequeueType = kDeqRecvData; - break; - case kSQSendControl: - case kSQSendData: - dequeueType = kDeqSendControlData; - break; - default: - Logger.ERR(kTag, "Enqueue: Unknown queue type: " + queueType); - return; - } - - - boolean segmentEnqueued = false; - - synchronized (this.mQueues[queueType]) { - if (segment.seq_no == this.mExpectedSeqNo[queueType]) { - // Case 1. this seq no. = expected seq no. - // In-order segments -> enqueue to the target queue - this.mExpectedSeqNo[queueType]++; - - this.mQueues[queueType].offerLast(segment); - this.mQueueLengths[queueType]++; - segmentEnqueued = true; - } else if (segment.seq_no < this.mExpectedSeqNo[queueType]) { - // Case 2. this seq no. < expected seq no. - // Duplicated segments -> ignore - return; - } else { - // Case 3. this seq no. > expected seq no. - // Out-of-order segments -> insert at the proper position of pending queue - ListIterator it = this.mPendingQueue[queueType].listIterator(); - while (it.hasNext()) { - Segment walker = (Segment) it.next(); - if (walker.seq_no > segment.seq_no) break; - } - it.add(segment); - Logger.WARN(kTag, "Pending Queue: (" + queueType + ") incoming=" + segment - .seq_no + " / expected_next=" + this.mExpectedSeqNo[queueType]); - } - - // TODO: why do that? - ListIterator it = this.mPendingQueue[queueType].listIterator(); - while (it.hasNext()) { - Segment walker = (Segment) it.next(); - - if (walker.seq_no != this.mExpectedSeqNo[queueType]) break; - - this.mQueues[queueType].offerLast(walker); - this.mQueueLengths[queueType]++; - this.mExpectedSeqNo[queueType]++; - segmentEnqueued = true; - - it.remove(); - } - } - - if (segmentEnqueued) { - this.wakeUpDequeueWaiting(dequeueType); - } - - this.checkReceivingDone(); - } - - public Segment dequeue(int dequeueType) { - assert (dequeueType < kNumDeq); - synchronized (this.mDequeueCond[dequeueType]) { - // If queue is empty, wait until some segment is enqueued - boolean isWaitRequired = false; - switch (dequeueType) { - case kDeqSendControlData: - isWaitRequired = ((this.mQueueLengths[kSQSendControl] == 0) && (this - .mQueueLengths[kSQSendData] == 0)); - break; - case kDeqRecvControl: - isWaitRequired = (this.mQueueLengths[kSQRecvControl] == 0); - break; - case kDeqRecvData: - isWaitRequired = (this.mQueueLengths[kSQRecvData] == 0); - break; - } - if (isWaitRequired) { - try { - this.mDequeueCond[dequeueType].wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - // Set target queue type - int targetQueueType = kSQUnknown; - switch (dequeueType) { - case kDeqSendControlData: - if (this.mQueueLengths[kSQSendControl] != 0) { - // Priority 1. Dequeue send control queue - targetQueueType = kSQSendControl; - } else if (this.mQueueLengths[kSQSendData] != 0) { - // Priority 2. Dequeue send data queue - targetQueueType = kSQSendData; - } else { - return null; - } - break; - case kDeqRecvControl: - targetQueueType = kSQRecvControl; - break; - case kDeqRecvData: - targetQueueType = kSQRecvData; - break; - default: - Logger.ERR(kTag, "Dequeue failed: invalid dequeue type (Dequeue=" + - dequeueType + ")"); - return null; - } - - // Check queue type - if (targetQueueType >= kNumSQ) { - Logger.ERR(kTag, "Dequeue failed: invalid queue type (Dequeue=" + dequeueType + - ")"); - return null; - } - - // Dequeue from queue - synchronized (this.mQueues[targetQueueType]) { - // Check the dequeued segment - Segment segmentDequeued = (Segment) this.mQueues[targetQueueType].pollFirst(); - if (segmentDequeued == null) { -// Logger.DEBUG(kTag, "Dequeue interrupted: empty queue (queue=" + -// targetQueueType + ", dequeue=" + dequeueType + ")"); - return null; - } - mQueueLengths[targetQueueType]--; - return segmentDequeued; - } - } - } - - public Segment get_free_segment() { - Segment ret; - synchronized (mFreeSegments) { - if (mFreeSegmentsSize == 0) { - ret = new Segment(); - } else { - ret = mFreeSegments.pop(); - mFreeSegmentsSize--; - } - - if (ret == null) throw new AssertionError(); - - ret.seq_no = -1; - ret.flag = 0; - ret.len = 0; - } - return ret; - } - - public void free_segment(Segment seg) { - synchronized (mFreeSegments) { - mFreeSegments.push(seg); - mFreeSegmentsSize++; - - if (mFreeSegmentsSize > kSegFreeThreshold) { - release_segment_from_free_list(kSegFreeThreshold / 2); - } - } - } - - private void release_segment_from_free_list(int threshold) { - while (mFreeSegmentsSize > threshold) { - mFreeSegments.pop(); - mFreeSegmentsSize--; - } - } - - public void failed_sending(Segment seg) { - synchronized (mFailedSendingQueue) { - mFailedSendingQueue.offerLast(seg); - this.wakeUpDequeueWaiting(kDeqSendControlData); - } - } - - public Segment get_failed_sending() { - Segment ret; - synchronized (mFailedSendingQueue) { - ret = mFailedSendingQueue.pollFirst(); - } - - return ret; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java deleted file mode 100644 index 89c2ed19..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtClientAdapter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.app.Activity; - -import com.redcarrottt.sc.internal.ClientAdapter; - -public class BtClientAdapter extends ClientAdapter { - // Singleton - static public BtClientAdapter singleton(int id, String name, String targetMacAddr, String - serviceUuid, Activity ownerActivity) { - if (sSingleton == null) { - sSingleton = new BtClientAdapter(id, name, targetMacAddr, serviceUuid, ownerActivity); - } - return sSingleton; - } - - static private BtClientAdapter sSingleton = null; - - // Constructor - private BtClientAdapter(int id, String name, String targetMacAddr, String serviceUuid, - Activity ownerActivity) { - super(id, name); - - // Components - BtDevice device = new BtDevice(ownerActivity); - BtP2PClient p2pClient = new BtP2PClient(); - RfcommClientSocket clientSocket = new RfcommClientSocket(targetMacAddr, serviceUuid); - - // Initialize - this.initialize(device, p2pClient, clientSocket); - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java deleted file mode 100644 index bb9e7221..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtDevice.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.app.Activity; -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import com.redcarrottt.sc.internal.Device; -import com.redcarrottt.testapp.Logger; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -class BtDevice extends Device { - private static final String kTag = "BtDevice"; - - // TODO: there is no timeout on turn on/off of BtDevice - @Override - protected void turnOnImpl() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter.isEnabled()) { - Logger.DEBUG(kTag, "Bluetooth is already turned on"); - this.doneTurnOn(true); - } else { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mBtDeviceOnEventReceiver, intentFilter); - - // turn on adapter command - adapter.enable(); - } - } - - @Override - protected void turnOffImpl() { - // Register bluetooth device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mBtDeviceOffEventReceiver, intentFilter); - - // turn off adapter command - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if(!adapter.isEnabled()) { - Logger.DEBUG(kTag, "Bluetooth is already turned off"); - this.doneTurnOff(true); - } else { - adapter.disable(); - } - } - - private BroadcastReceiver mBtDeviceOnEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - Logger.DEBUG(kTag, "Bluetooth Adapter state changed: " + state); - if (state == BluetoothAdapter.STATE_ON) { - Logger.DEBUG(kTag, "Bluetooth is turned on successfully"); - doneTurnOn(true); - context.unregisterReceiver(mBtDeviceOnEventReceiver); - } - } - } - }; - - private BroadcastReceiver mBtDeviceOffEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - Logger.DEBUG(kTag, "Bluetooth Adapter state changed: " + state); - if (state == BluetoothAdapter.STATE_OFF) { - Logger.DEBUG(kTag, "Bluetooth is turned off successfully"); - doneTurnOff(true); - context.unregisterReceiver(mBtDeviceOffEventReceiver); - } - } - } - }; - - private Activity mOwnerActivity; - - // Constructor - public BtDevice(Activity ownerActivity) { - super("Bluetooth"); - this.mOwnerActivity = ownerActivity; - } -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java deleted file mode 100644 index 2c6c3795..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/BtP2PClient.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import com.redcarrottt.sc.internal.OnConnectResult; -import com.redcarrottt.sc.internal.OnDisconnectResult; -import com.redcarrottt.sc.internal.OnDiscoverResult; -import com.redcarrottt.sc.internal.P2PClient; - -class BtP2PClient extends P2PClient { - @Override - protected void discoverImpl(OnDiscoverResult onDiscoverResult) { - // Assume that target device has already been bonded. - onDiscoverResult.onDoneDiscover(true); - } - - @Override - protected void connectImpl(OnConnectResult onConnectResult) { - // Assume that target device has already been bonded. - onConnectResult.onDoneConnect(true); - } - - @Override - protected void disconnectImpl(OnDisconnectResult onDisconnectResult) { - // Assume that target device has already been bonded. - onDisconnectResult.onDoneDisconnect(true); - } - - // Constructor - public BtP2PClient() { - } - - // Attributes -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java deleted file mode 100644 index d7d69e8b..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/bt/RfcommClientSocket.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.redcarrottt.sc.internal.bt; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSocket; - -import com.redcarrottt.sc.internal.ClientSocket; -import com.redcarrottt.testapp.Logger; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.util.Set; -import java.util.UUID; - -class RfcommClientSocket extends ClientSocket { - private static String kTag = "RfcommClientSocket"; - - @Override - protected boolean openImpl() { - // Initialize socket - this.mSocket = null; - Set pairedBtDevices = BluetoothAdapter.getDefaultAdapter() - .getBondedDevices(); - for (BluetoothDevice btDevice : pairedBtDevices) { - Logger.DEBUG(kTag, "Found Device: " + btDevice.getAddress() + " / " + btDevice - .getName()); - if (btDevice.getAddress().equals(this.mTargetMacAddr)) { - try { - this.mSocket = btDevice.createRfcommSocketToServiceRecord(this.mServiceUuid); - } catch (IOException e) { - Logger.ERR(kTag, "Socket initialization failed"); - return false; - } - } - } - if (this.mSocket == null) { - Logger.ERR(kTag, "Cannot create bluetooth socket"); - return false; - } - - // Try to open socket - final int kMaxTries = 10; - for (int tries = 0; tries < kMaxTries; tries++) { - try { - this.mSocket.connect(); - this.mInputStream = new BufferedInputStream(this.mSocket.getInputStream()); - this.mOutputStream = new BufferedOutputStream(this.mSocket.getOutputStream()); - break; - } catch (IOException e) { - this.mInputStream = null; - this.mOutputStream = null; - Logger.WARN(kTag, "Try socket open " + tries); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (this.mSocket.isConnected()) { - Logger.VERB(kTag, "Socket open success"); - return true; - } else { - Logger.ERR(kTag, "Socket open failed!"); - this.mSocket = null; - return false; - } - } - - @Override - protected boolean closeImpl() { - if (this.mSocket != null && this.mSocket.isConnected()) { - try { - this.mInputStream.close(); - this.mOutputStream.close(); - this.mSocket.close(); - Logger.VERB(kTag, "Socket closed"); - return true; - } catch (IOException e) { - return false; - } - } - return true; - } - - @Override - protected int sendImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mOutputStream == null) { - Logger.ERR(kTag, "Socket closed! Send failed!"); - return -1; - } - try { - this.mOutputStream.write(dataBuffer, 0, dataLength); - this.mOutputStream.flush(); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Send failed! / " + e.getMessage()); - return -2; - } - } - - @Override - protected int receiveImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mInputStream == null) { - Logger.ERR(kTag, "Socket closed! Receive failed!"); - return -1; - } - try { - int receivedBytes = 0; - while (receivedBytes < dataLength) { - int onceReceivedBytes = this.mInputStream.read(dataBuffer, receivedBytes, - dataLength - receivedBytes); - if (onceReceivedBytes < 0) { - Logger.ERR(kTag, "Receive failed! 1"); - return -2; - } - receivedBytes += onceReceivedBytes; - } - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Receive failed! 2 / " + e.getMessage()); - return -3; - } - } - - // Constructor - RfcommClientSocket(String targetMacAddr, String serviceUuid) { - this.mTargetMacAddr = targetMacAddr; - this.mServiceUuid = UUID.fromString(serviceUuid); - } - - private BluetoothSocket mSocket; - private BufferedInputStream mInputStream; - private BufferedOutputStream mOutputStream; - - // Attributes - private String mTargetMacAddr; - private UUID mServiceUuid; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java deleted file mode 100644 index 5e839c7c..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/TcpClientSocket.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import com.redcarrottt.sc.internal.ClientSocket; -import com.redcarrottt.testapp.Logger; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; - -class TcpClientSocket extends ClientSocket { - private final String kTag = "TcpClientSocket"; - - @Override - protected boolean openImpl() { - Logger.DEBUG(kTag, "Connect to server " + this.getTargetIpAddress() + ":" + this - .mTargetPort); - - // Try to open socket - final int kMaxTries = 10; - for (int tries = 0; tries < kMaxTries; tries++) { - try { - this.mSocket = new Socket(); - this.mSocket.setReuseAddress(true); - this.mSocket.bind(null); - this.mSocket.connect(new InetSocketAddress(this.getTargetIpAddress(), this - .mTargetPort)); - this.mInputStream = new BufferedInputStream(this.mSocket.getInputStream()); - this.mOutputStream = new BufferedOutputStream(this.mSocket.getOutputStream()); - break; - } catch (IOException e) { - this.mSocket = null; - this.mInputStream = null; - this.mOutputStream = null; - Logger.WARN(kTag, "Try socket open " + tries); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - if (this.mSocket != null && this.mSocket.isConnected()) { - Logger.VERB(kTag, "Socket open success"); - return true; - } else { - Logger.ERR(kTag, "Socket open failed!"); - this.mSocket = null; - return false; - } - } - - @Override - protected boolean closeImpl() { - if (this.mSocket != null && this.mSocket.isConnected()) { - try { - this.mInputStream.close(); - this.mOutputStream.close(); - this.mSocket.close(); - Logger.VERB(kTag, "Socket closed"); - return true; - } catch (IOException e) { - return false; - } - } - return true; - } - - @Override - protected int sendImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mOutputStream == null) { - Logger.ERR(kTag, "Socket closed! Send failed!"); - return -1; - } - try { - this.mOutputStream.write(dataBuffer, 0, dataLength); - this.mOutputStream.flush(); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Send failed! / " + e.getMessage()); - return -2; - } - } - - @Override - protected int receiveImpl(byte[] dataBuffer, int dataLength) { - if (this.mSocket == null || !this.mSocket.isConnected() || this.mInputStream == null) { - Logger.ERR(kTag, "Socket closed! Receive failed!"); - return -1; - } - try { - int receivedBytes = 0; - while (receivedBytes < dataLength) { - int onceReceivedBytes = this.mInputStream.read(dataBuffer, receivedBytes, - dataLength - receivedBytes); - if (onceReceivedBytes < 0) { - Logger.ERR(kTag, "Receive failed! 1"); - return -2; - } - receivedBytes += onceReceivedBytes; - } - -// Logger.DEBUG(kTag, "TCP received " + receivedBytes); - return dataLength; - } catch (IOException e) { - Logger.ERR(kTag, "Receive failed! 2 / " + e.getMessage()); - return -3; - } - } - - // Constructor - TcpClientSocket(int targetPort) { - this.mTargetPort = targetPort; - this.mIsInfoSet = false; - this.mInfoSetTrigger = new Object(); - } - - public void setTcpClientInfo(String targetIpAddress) { - this.mTargetIpAddress = targetIpAddress; - - Logger.DEBUG(kTag, "Notify: WfdP2PInfo"); - this.mIsInfoSet = true; - synchronized (this.mInfoSetTrigger) { - this.mInfoSetTrigger.notifyAll(); - } - } - - private String getTargetIpAddress() { - // Wait until wps pin is set, then get the information. - if (this.mIsInfoSet) { - return this.mTargetIpAddress; - } else { - Logger.DEBUG(kTag, "Waiting: mTargetIpAddress"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - return this.mTargetIpAddress; - } - } - - // Components - private Socket mSocket; - private BufferedInputStream mInputStream; - private BufferedOutputStream mOutputStream; - - // TODO: adding port to WFD info would be good. - // Attributes - private int mTargetPort; - - // TCP Socket Info Attributes - private boolean mIsInfoSet; - private final Object mInfoSetTrigger; - private String mTargetIpAddress; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java deleted file mode 100644 index 91eb22a8..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdClientAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; - -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.ControlMessageListener; -import com.redcarrottt.sc.internal.ControlMessageProtocol; -import com.redcarrottt.sc.internal.Core; -import com.redcarrottt.testapp.Logger; - -public class WfdClientAdapter extends ClientAdapter implements ControlMessageListener { - private static final String kTag = "WfdClientAdapter"; - - // Singleton - static public WfdClientAdapter singleton(int id, String name, int targetPort, Activity - ownerActivity) { - if (sSingleton == null) { - sSingleton = new WfdClientAdapter(id, name, targetPort, ownerActivity); - } - return sSingleton; - } - - static private WfdClientAdapter sSingleton; - - // Constructor - private WfdClientAdapter(int id, String name, int targetPort, Activity ownerActivity) { - super(id, name); - - // Components - WfdDevice device = new WfdDevice(ownerActivity); - this.mP2pClient = new WfdP2PClient(ownerActivity); - this.mClientSocket = new TcpClientSocket(targetPort); - - // Initialize - this.initialize(device, this.mP2pClient, this.mClientSocket); - - // Add WfdP2PClient as a control message listener - Core.singleton().getControlMessageReceiver().addControlMessageListener(this); - } - - @Override - public void onReceiveControlMessage(int privateType, String privateMessage) { - if (privateType == ControlMessageProtocol.PrivType.kWFDInfo) { - Logger.DEBUG(kTag, "Received WFD info message: " + privateMessage); - String wfdInfoLines[] = privateMessage.split("\\r?\\n"); - if (wfdInfoLines.length < 3) { - Logger.ERR(kTag, "WFD info is insufficient: " + wfdInfoLines.length + " < 3"); - } - String targetMacAddress = wfdInfoLines[0]; - String wpsPin = wfdInfoLines[1]; - String targetIpAddress = wfdInfoLines[2]; - - mP2pClient.setWfdP2PInfo(targetMacAddress, wpsPin); - mClientSocket.setTcpClientInfo(targetIpAddress); - } - } - - // Components - private WfdP2PClient mP2pClient; - private TcpClientSocket mClientSocket; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java deleted file mode 100644 index dfafe28a..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdDevice.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.WifiManager; - -import com.redcarrottt.sc.internal.Device; -import com.redcarrottt.testapp.Logger; - -class WfdDevice extends Device { - private static final String kTag = "WFdDevice"; - - // TODO: there is no timeout on turn on/off of WfdDevice - @Override - protected void turnOnImpl() { - WifiManager wifiManager = (WifiManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - doneTurnOn(false); - } else if (wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Wi-fi Direct is already turned on"); - doneTurnOn(true); - } else { - // Register wi-fi device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mWfdDeviceOnEventReceiver, intentFilter); - - // turn on wi-fi command - wifiManager.setWifiEnabled(true); - } - } - - @Override - protected void turnOffImpl() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mOwnerActivity.getApplicationContext(); - context.registerReceiver(this.mWfdDeviceOffEventReceiver, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if(wifiManager == null) { - doneTurnOff(true); - } else if(!wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Wi-fi Direct is already turned off"); - doneTurnOff(true); - } else { - wifiManager.setWifiEnabled(false); - } - } - - private BroadcastReceiver mWfdDeviceOnEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - Logger.DEBUG(kTag, "Wi-fi Adapter state changed: " + state); - if (state == WifiManager.WIFI_STATE_ENABLED) { - Logger.DEBUG(kTag, "Wi-fi is turned on successfully"); - doneTurnOn(true); - context.unregisterReceiver(mWfdDeviceOnEventReceiver); - } - } - } - }; - - private BroadcastReceiver mWfdDeviceOffEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, - WifiManager.WIFI_STATE_UNKNOWN); - Logger.DEBUG(kTag, "Wi-fi Adapter state changed: " + state); - if (state == WifiManager.WIFI_STATE_DISABLED) { - Logger.DEBUG(kTag, "Wi-fi is turned off successfully"); - doneTurnOff(true); - context.unregisterReceiver(mWfdDeviceOffEventReceiver); - } - } - } - }; - - // Constructor - public WfdDevice(Activity ownerActivity) { - super("Wi-fi Direct"); - this.mOwnerActivity = ownerActivity; - } - - // Attributes - private Activity mOwnerActivity; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java deleted file mode 100644 index f9b909de..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/sc/internal/wfd/WfdP2PClient.java +++ /dev/null @@ -1,390 +0,0 @@ -package com.redcarrottt.sc.internal.wfd; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.NetworkInfo; -import android.net.wifi.WpsInfo; -import android.net.wifi.p2p.WifiP2pConfig; -import android.net.wifi.p2p.WifiP2pDevice; -import android.net.wifi.p2p.WifiP2pDeviceList; -import android.net.wifi.p2p.WifiP2pGroup; -import android.net.wifi.p2p.WifiP2pManager; -import android.os.Looper; - -import com.redcarrottt.sc.internal.OnConnectResult; -import com.redcarrottt.sc.internal.OnDisconnectResult; -import com.redcarrottt.sc.internal.OnDiscoverResult; -import com.redcarrottt.sc.internal.P2PClient; -import com.redcarrottt.testapp.Logger; - -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -class WfdP2PClient extends P2PClient { - private static final String kTag = "WfdP2PClient"; - - @Override - protected void discoverImpl(OnDiscoverResult onDiscoverResult) { - // Run Discover Transaction - runDiscoverTx(onDiscoverResult); - } - - private void runDiscoverTx(OnDiscoverResult onDiscoverResult) { - if (sOngoingDiscover == null) { - sOngoingDiscover = new DiscoverTransaction(); - sOngoingDiscover.run(onDiscoverResult); - } else { - Logger.WARN(kTag, "Already stopping core"); - onDiscoverResult.onDoneDiscover(false); - } - } - - private static void doneDiscoverTx(OnDiscoverResult onDiscoverResult, boolean isSuccess) { - onDiscoverResult.onDoneDiscover(isSuccess); - sOngoingDiscover = null; - } - - private static DiscoverTransaction sOngoingDiscover = null; - - private class DiscoverTransaction { - // TODO: Adding timeout on this transaction would be good. - private OnDiscoverResult mOnDiscoverResult; - private int mTries = 0; - private final int kMaxTries = 100; - - void run(OnDiscoverResult onDiscoverResult) { - this.mTries = 0; - this.mOnDiscoverResult = onDiscoverResult; - stopP2PDiscovery(); - } - - void retry() { - stopP2PDiscovery(); - } - - // Step 1 - private void stopP2PDiscovery() { - Logger.DEBUG(kTag, "Stop discovery"); - mWFDManager.stopPeerDiscovery(mWFDChannel, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - startP2PDiscovery(); - } - - @Override - public void onFailure(int i) { - Logger.ERR(kTag, "Stopping discovery failed / reason=" + i); - mTries++; - if (mTries < kMaxTries) { - retry(); - } else { - doneDiscoverTx(mOnDiscoverResult, false); - } - } - }); - } - - // Step 2 - private void startP2PDiscovery() { - Logger.DEBUG(kTag, "Start discovery"); - - // Start to listen peer change - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); - Context context = mOwnerActivity.getApplicationContext(); - this.mPeersChangedReceiver = new PeersChangedReceiver(); - context.registerReceiver(mPeersChangedReceiver, intentFilter); - this.mPeerListListener = new PeerListListener(); - - // Discover peers - mWFDManager.discoverPeers(mWFDChannel, null); - } - - // Step 4 - private PeersChangedReceiver mPeersChangedReceiver; - - private class PeersChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert action != null; - if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) { - Logger.DEBUG(kTag, "Peers changed event"); - - // Request peer list - Logger.DEBUG(kTag, "Request WFD peers"); - mWFDManager.requestPeers(mWFDChannel, mPeerListListener); - } - } - } - - ; - - // Step 5 - private PeerListListener mPeerListListener; - - class PeerListListener implements WifiP2pManager.PeerListListener { - private Lock mCallbackLock; - private Boolean mIsPeerFound; - - PeerListListener() { - this.mCallbackLock = new ReentrantLock(); - this.mIsPeerFound = false; - } - - @Override - public void onPeersAvailable(WifiP2pDeviceList peers) { - final WifiP2pDeviceList kPeers = peers; - // Since getting peer device address requires locks, it should run on child thread. - Thread childThread = new Thread() { - @Override - public void run() { - if (mCallbackLock.tryLock()) { - try { - synchronized (mIsPeerFound) { - if (!mIsPeerFound) { - Logger.DEBUG(kTag, "Got peer list (Target=" + - getTargetMacAddress() + ")"); - for (WifiP2pDevice p2pDevice : kPeers.getDeviceList()) { - Logger.DEBUG(kTag, "Peer: " + p2pDevice.deviceAddress - + " / " + p2pDevice.deviceName + " / " + - p2pDevice.status); - - if (p2pDevice.deviceAddress.equals - (getTargetMacAddress()) && p2pDevice.status - == WifiP2pDevice.AVAILABLE) { - mFoundWFDDevice = p2pDevice; - Logger.DEBUG(kTag, "Peer found"); - mIsPeerFound = true; - break; - } - } - } - } - - // Unregister PeersChangedReceiver - if (mPeerListListener != null) { - mOwnerActivity.getApplicationContext().unregisterReceiver - (mPeersChangedReceiver); - mPeerListListener = null; - } - - synchronized (mIsPeerFound) { - if (mIsPeerFound) { - doneDiscoverTx(mOnDiscoverResult, true); - } else { - mTries++; - if (mTries < kMaxTries) { - retry(); - } else { - doneDiscoverTx(mOnDiscoverResult, false); - } - } - } - } finally { - mCallbackLock.unlock(); - } - } - } - }; - childThread.start(); - } - } - } - - private WifiP2pDevice mFoundWFDDevice = null; - - // TODO: Adding timeout on this transaction would be good. - @Override - protected void connectImpl(OnConnectResult onConnectResult) { - if (this.mFoundWFDDevice == null) { - Logger.ERR(kTag, "Not found target WFD device"); - onConnectResult.onDoneConnect(false); - return; - } - - // Start to listen P2P connection event - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); - Context context = mOwnerActivity.getApplicationContext(); - mWFDConnectionReceiver.setOnConnectResult(onConnectResult); - context.registerReceiver(mWFDConnectionReceiver, intentFilter); - - // Setting P2P config - Logger.DEBUG(kTag, "Connect WFD Peer"); - WifiP2pDevice p2pDevice = this.mFoundWFDDevice; - WifiP2pConfig p2pConfig = new WifiP2pConfig(); - p2pConfig.deviceAddress = p2pDevice.deviceAddress; - if (p2pDevice.wpsKeypadSupported()) { - Logger.DEBUG(kTag, "WPS Method: Keypad"); - p2pConfig.wps.setup = WpsInfo.KEYPAD; - p2pConfig.wps.pin = this.getWpsPin(); - } else if (p2pDevice.wpsPbcSupported()) { - Logger.DEBUG(kTag, "WPS Method: PBC - Unsupported"); - p2pConfig.wps.setup = WpsInfo.PBC; - onConnectResult.onDoneConnect(false); - return; - } else if (p2pDevice.wpsDisplaySupported()) { - Logger.DEBUG(kTag, "WPS Method: Display - Unsupported"); - onConnectResult.onDoneConnect(false); - return; - } - p2pConfig.groupOwnerIntent = 0; - - // P2P connection request - final OnConnectResult fOnConnectResult = onConnectResult; - Logger.DEBUG(kTag, "Request to connect: " + p2pDevice.deviceName + " " + p2pDevice - .deviceAddress + " (" + p2pConfig.wps.pin + ")"); - mWFDManager.connect(mWFDChannel, p2pConfig, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - Logger.DEBUG(kTag, "WFD Connection Success"); - } - - @Override - public void onFailure(int i) { - Logger.WARN(kTag, "WFD Connection Failure / reason=" + i + " - retry to connect..."); - connectImpl(fOnConnectResult); - } - }); - } - - private WFDConnectionReceiver mWFDConnectionReceiver = new WFDConnectionReceiver(); - - private class WFDConnectionReceiver extends BroadcastReceiver { - private OnConnectResult mOnConnectResult = null; - - public void setOnConnectResult(OnConnectResult onConnectResult) { - this.mOnConnectResult = onConnectResult; - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert (action != null); - - if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { - NetworkInfo netInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager - .EXTRA_NETWORK_INFO); - Logger.DEBUG(kTag, "Wi-fi direct connection change detected! " + netInfo.toString - ()); - if (netInfo.isConnected()) { - Logger.DEBUG(kTag, "Wi-fi direct Connected!"); - WifiP2pGroup p2pGroup = intent.getParcelableExtra(WifiP2pManager - .EXTRA_WIFI_P2P_GROUP); - String goMacAddress = p2pGroup.getOwner().deviceAddress; - Logger.DEBUG(kTag, "Group owner address: " + goMacAddress); - if (goMacAddress != null && goMacAddress.equals(getTargetMacAddress())) { - context.unregisterReceiver(mWFDConnectionReceiver); - mOnConnectResult.onDoneConnect(true); - } - } - } - } - } - - @Override - protected void disconnectImpl(OnDisconnectResult onDisconnectResult) { - final OnDisconnectResult kOnDisconnectResult = onDisconnectResult; - mWFDManager.removeGroup(mWFDChannel, new WifiP2pManager.ActionListener() { - @Override - public void onSuccess() { - kOnDisconnectResult.onDoneDisconnect(true); - } - - @Override - public void onFailure(int i) { - kOnDisconnectResult.onDoneDisconnect(false); - } - }); - } - - public void setWfdP2PInfo(String targetMacAddress, String wpsPin) { - this.mTargetMacAddress = targetMacAddress; - this.mWpsPin = wpsPin; - - Logger.DEBUG(kTag, "Notify: WfdP2PInfo"); - this.mIsInfoSet = true; - synchronized (this.mInfoSetTrigger) { - this.mInfoSetTrigger.notifyAll(); - } - } - - private String getTargetMacAddress() { - // Wait until target mac address is set, then get the information. - if (this.mIsInfoSet) { - return this.mTargetMacAddress; - } else { - Logger.DEBUG(kTag, "Waiting: mTargetMacAddress"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - Logger.DEBUG(kTag, "Got: mTargetMacAddress"); - return this.mTargetMacAddress; - } - } - - private String getWpsPin() { - // Wait until wps pin is set, then get the information. - if (this.mIsInfoSet) { - return this.mWpsPin; - } else { - Logger.DEBUG(kTag, "Waiting: mWpsPin"); - while (!this.mIsInfoSet) { - synchronized (this.mInfoSetTrigger) { - try { - this.mInfoSetTrigger.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - Logger.DEBUG(kTag, "Got: mWpsPin"); - return this.mWpsPin; - } - } - - // Constructor - public WfdP2PClient(Activity ownerActivity) { - this.mOwnerActivity = ownerActivity; - this.mIsInfoSet = false; - this.mInfoSetTrigger = new Object(); - - // Initialize Android WFD Manager Channel - this.mWFDManager = (WifiP2pManager) this.mOwnerActivity.getApplicationContext() - .getSystemService(Context.WIFI_P2P_SERVICE); - if (this.mWFDManager == null) { - Logger.ERR(kTag, "Failed to initialize Wi-fi Direct Manager"); - return; - } - - - this.mWFDChannel = this.mWFDManager.initialize(this.mOwnerActivity, Looper.getMainLooper - (), null); - if (this.mWFDChannel == null) { - Logger.ERR(kTag, "Failed to initialize Wi-fi Direct Manager"); - } - } - - // Attributes - private Activity mOwnerActivity; - - // P2P Info Attributes - private boolean mIsInfoSet; - private final Object mInfoSetTrigger; - private String mTargetMacAddress; - private String mWpsPin; - - // Components - private WifiP2pManager mWFDManager; - private WifiP2pManager.Channel mWFDChannel; -} diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java deleted file mode 100644 index 87aa7cf1..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/CommInitializer.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.redcarrottt.testapp; - -import android.bluetooth.BluetoothAdapter; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.wifi.WifiManager; - -/* Copyright (c) 2018, contributors. All rights reserved. - * - * Contributor: Gyeonghwan Hong - * - * 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. - */ -public class CommInitializer { - private static final String kTag = "CommInit"; - - public void start() { - new Thread() { - @Override - public void run() { - turnOffBt(); - } - }.start(); - } - - private void turnOffBt() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (adapter.isEnabled()) { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOffBtResult, intentFilter); - - // turn on adapter command - Logger.DEBUG(kTag, "Turn off BT Start"); - adapter.disable(); - } else { - Logger.DEBUG(kTag, "BT already turned off"); - this.turnOnBt(); - } - } - - private BroadcastReceiver TurnOffBtResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - if (state == BluetoothAdapter.STATE_OFF) { - Logger.DEBUG(kTag, "Turn off BT Success"); - context.unregisterReceiver(TurnOffBtResult); - turnOnBt(); - } - } - } - }; - - private void turnOnBt() { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (!adapter.isEnabled()) { - // Register bluetooth device on event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOnBtResult, intentFilter); - - // turn on adapter command - Logger.DEBUG(kTag, "Turn on BT Start"); - adapter.enable(); - } else { - Logger.WARN(kTag, "BT not turned on"); - this.mOnResult.onCommInitializerResult(false); - } - } - - private BroadcastReceiver TurnOnBtResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, - BluetoothAdapter.ERROR); - if (state == BluetoothAdapter.STATE_ON) { - Logger.DEBUG(kTag, "Turn on BT Success"); - context.unregisterReceiver(TurnOnBtResult); - turnOffWifi(); - } - } - } - }; - - private void turnOffWifi() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOffWifiResult, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mMainActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - Logger.ERR(kTag, "Failed to get Wi-fi Manager"); - return; - } - - if (wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Turn off WIFI Start"); - wifiManager.setWifiEnabled(false); - } else { - Logger.DEBUG(kTag, "WIFI already turned off"); - this.turnOnWifi(); - } - } - - private BroadcastReceiver TurnOffWifiResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager - .WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_DISABLED) { - Logger.DEBUG(kTag, "Turn off WFD success"); - context.unregisterReceiver(TurnOffWifiResult); - turnOnWifi(); - } - } - } - }; - - private void turnOnWifi() { - // Register wi-fi device off event receiver - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); - Context context = this.mMainActivity.getApplicationContext(); - context.registerReceiver(this.TurnOnWifiResult, intentFilter); - - // turn off wi-fi command - WifiManager wifiManager = (WifiManager) this.mMainActivity.getApplicationContext() - .getSystemService(Context.WIFI_SERVICE); - if (wifiManager == null) { - Logger.ERR(kTag, "Failed to get Wi-fi Manager"); - return; - } - - if (!wifiManager.isWifiEnabled()) { - Logger.DEBUG(kTag, "Turn on WIFI Start"); - wifiManager.setWifiEnabled(true); - } else { - Logger.DEBUG(kTag, "WIFI already turned on"); - this.mOnResult.onCommInitializerResult(true); - } - } - - private BroadcastReceiver TurnOnWifiResult = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { - final int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager - .WIFI_STATE_UNKNOWN); - if (state == WifiManager.WIFI_STATE_ENABLED) { - Logger.DEBUG(kTag, "Turn on WFD success"); - context.unregisterReceiver(TurnOnWifiResult); - mOnResult.onCommInitializerResult(true); - } - } - } - }; - - public CommInitializer(MainActivity mainActivity, CommInitializerResult onResult) { - this.mMainActivity = mainActivity; - this.mOnResult = onResult; - } - - private MainActivity mMainActivity; - private CommInitializerResult mOnResult; -} - -interface CommInitializerResult { - public void onCommInitializerResult(boolean isSuccess); -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java deleted file mode 100644 index e1e79755..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/Logger.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.redcarrottt.testapp; - -/* Copyright (c) 2018, contributors. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * - * 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. - */ - -import android.annotation.SuppressLint; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -class LogLevel { - public static final int ERR = 1; - public static final int WARN = 2; - public static final int VERB = 3; - public static final int DEBUG = 4; -} - -class LogReceiver extends BroadcastReceiver { - public static final String kAction = "LogBroadcast"; - public static final String kKeyLogLevel = "LogLevel"; - public static final String kKeyLogTag = "LogTag"; - public static final String kKeyLogMessage = "LogMessage"; - - private Callback mCallback; - - public LogReceiver(Callback callback) { - this.mCallback = callback; - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - assert action != null; - if (action.equals(kAction)) { - String logTag = intent.getStringExtra(kKeyLogTag); - String logMessage = intent.getStringExtra(kKeyLogMessage); - int logLevel = intent.getIntExtra(kKeyLogLevel, LogLevel.DEBUG); - this.mCallback.onLogMessage(logLevel, logTag, logMessage); - } - } - - interface Callback { - void onLogMessage(final int logLevel, String logTag, String logMessage); - } -} - -public class Logger { - private static void print(Context context, int logLevel, String logTag, String logMessage) { - Intent broadcastIntent = new Intent(); - broadcastIntent.setAction(LogReceiver.kAction); - broadcastIntent.putExtra(LogReceiver.kKeyLogLevel, logLevel); - broadcastIntent.putExtra(LogReceiver.kKeyLogTag, logTag); - broadcastIntent.putExtra(LogReceiver.kKeyLogMessage, logMessage); - context.sendBroadcast(broadcastIntent); - } - - private static void print(String tag, int logLevel, String logMessage) { - print(defaultContext, logLevel, tag, logMessage); - } - - public static void ERR(String tag, String logMessage) { - print(tag, LogLevel.ERR, logMessage); - } - - public static void WARN(String tag, String logMessage) { - print(tag, LogLevel.WARN, logMessage); - } - - public static void VERB(String tag, String logMessage) { - print(tag, LogLevel.VERB, logMessage); - } - - public static void DEBUG(String tag, String logMessage) { - print(tag, LogLevel.DEBUG, logMessage); - } - - public static void THREAD_LAUNCH(String threadName) { - VERB(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Launch"); - } - - public static void THREAD_ADAPTER_LAUNCH(String adapterName, String threadName) { - VERB(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Launch"); - } - - public static void THREAD_FINISH(String threadName) { - VERB(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Finish"); - } - - public static void THREAD_ADAPTER_FINISH(String adapterName, String threadName) { - VERB(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Finish"); - } - - public static void THREAD_FAIL(String threadName) { - ERR(threadName, "Thread(" + threadName + "/" + Thread.currentThread().getId() + ") " + - "Fail"); - } - - public static void THREAD_ADAPTER_FAIL(String adapterName, String threadName) { - ERR(threadName, "Thread(" + adapterName + "-" + threadName + "/" + Thread.currentThread - ().getId() + ") Fail"); - } - - public static void setDefaultContext(Context context) { - Logger.defaultContext = context; - } - - @SuppressLint("StaticFieldLeak") - private static Context defaultContext; -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java b/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java deleted file mode 100755 index 1814068e..00000000 --- a/subprojects/sc/android/app/src/main/java/com/redcarrottt/testapp/MainActivity.java +++ /dev/null @@ -1,461 +0,0 @@ -package com.redcarrottt.testapp; - -/* Copyright (c) 2017-2018. All rights reserved. - * Gyeonghwan Hong (redcarrottt@gmail.com) - * Eunsoo Park (esevan.park@gmail.com) - * Injung Hwang (sinban04@gmail.com) - * - * 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. - */ - -import android.Manifest; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.graphics.Color; -import android.os.Bundle; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.TextView; - -import com.redcarrottt.sc.api.API; -import com.redcarrottt.sc.api.OnStartSCResult; -import com.redcarrottt.sc.api.OnStopSCResult; -import com.redcarrottt.sc.internal.ClientAdapter; -import com.redcarrottt.sc.internal.ClientAdapterStateListener; -import com.redcarrottt.sc.internal.bt.BtClientAdapter; -import com.redcarrottt.sc.internal.wfd.WfdClientAdapter; - -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Date; - -import static com.redcarrottt.sc.internal.ExpConfig.VERBOSE_BANDWIDTH_UPDATE; - -public class MainActivity extends AppCompatActivity implements LogReceiver.Callback, - CommInitializerResult { - private static final String kTag = "MainActivity"; - - // Components - private ArrayList mLogListViewData = new ArrayList<>(); - private LogListViewAdapter mLogListViewAdapter; - private SpeedWatcherThread mSpeedWatcherThread; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - // Initialize SwitchProfileButton - Button switchProfileButton = (Button) findViewById(R.id.switchProfileButton); - switchProfileButton.setOnClickListener(onClickSwitchProfileButton); - this.updateSwitchProfileButton(); - - // Initialize StartButton - Button startButton = (Button) findViewById(R.id.startButton); - startButton.setOnClickListener(onClickStartButton); - - // Initialize SpeedWatcherThread for BandwidthTextView - this.mSpeedWatcherThread = new SpeedWatcherThread(); - this.mSpeedWatcherThread.start(); - - // Initialize LogListView - this.mLogListViewAdapter = new LogListViewAdapter(this, this.mLogListViewData); - ListView logListView = (ListView) findViewById(R.id.logListView); - logListView.setAdapter(this.mLogListViewAdapter); - - // Initialize Log Receiver - Logger.setDefaultContext(this); - LogReceiver logReceiver = new LogReceiver(this); - IntentFilter broadcastIntentFilter = new IntentFilter(); - broadcastIntentFilter.addAction(LogReceiver.kAction); - this.registerReceiver(logReceiver, broadcastIntentFilter); - - // Require permissions for SC - this.requestPermissions(); - - // Initialize Communication Interfaces - Logger.VERB(kTag, "Initializing network interfaces..."); - mCommInitializer = new CommInitializer(this, this); - mCommInitializer.start(); - } - - - private CommInitializer mCommInitializer; - - @Override - public void onCommInitializerResult(boolean isSuccess) { - if (isSuccess) { - Logger.VERB(kTag, "All network Interfaces ready"); - Button startButton = (Button) findViewById(R.id.startButton); - startButton.setEnabled(true); - } else { - Logger.ERR(kTag, "Initialization failed"); - } - } - - private View.OnClickListener onClickStartButton = new View.OnClickListener() { - @Override - public void onClick(View view) { - // Initialize SC - initializeCommunication(); - } - }; - - private String[] mProfiles = {"Lab", "Home"}; - private int mPresentProfile = 0; - private View.OnClickListener onClickSwitchProfileButton = new View.OnClickListener() { - @Override - public void onClick(View view) { - final int kMaxProfiles = mProfiles.length; - mPresentProfile = (mPresentProfile + 1) % kMaxProfiles; - updateSwitchProfileButton(); - } - }; - - private void updateSwitchProfileButton() { - Button switchProfileButton = (Button) findViewById(R.id.switchProfileButton); - switchProfileButton.setText(this.mProfiles[this.mPresentProfile] + " Profile"); - } - - private void requestPermissions() { - if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET) != - PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission - .INTERNET, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission - .ACCESS_WIFI_STATE, Manifest.permission.CHANGE_WIFI_STATE, Manifest - .permission.CHANGE_NETWORK_STATE, Manifest.permission - .ACCESS_COARSE_LOCATION}, 0); - } - } - - private void initializeCommunication() { - String btAddress = ""; - switch (this.mPresentProfile) { - case 0: - btAddress = "B8:27:EB:D9:FA:85"; - break; - case 1: - btAddress = "B8:27:EB:77:C3:4A"; - break; - } - - if (btAddress == "") { - Logger.ERR(kTag, "No bluetooth address is defined!"); - return; - } else { - Logger.VERB(kTag, "BT Address: " + btAddress); - } - - - // Setting adapters - this.mBtClientAdapter = BtClientAdapter.singleton(1, "BT", btAddress, - "150e8400-1234-41d4-a716-446655440000", this); - this.mBtClientAdapter.listenState(this.mClientAdapterStateListener); - API.registerAdapter(this.mBtClientAdapter); - - this.mWfdClientAdapter = WfdClientAdapter.singleton(2, "WFD", 3455, this); - this.mWfdClientAdapter.listenState(this.mClientAdapterStateListener); - API.registerAdapter(this.mWfdClientAdapter); - - // Start the selective connection - API.startSC(onStartSCResult); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - API.stopSC(onStopSCResult); - } - - // ClientAdapters - private BtClientAdapter mBtClientAdapter; - private WfdClientAdapter mWfdClientAdapter; - - private int mBtClientAdapterState; - private int mWfdClientAdapterState; - - private ClientAdapterStateListener mClientAdapterStateListener = new - ClientAdapterStateListener() { - - @Override - public void onUpdateClientAdapterState(ClientAdapter adapter, int oldState, int newState) { - // Update local state variable - if (adapter == mBtClientAdapter) { - mBtClientAdapterState = newState; - } else if (adapter == mWfdClientAdapter) { - mWfdClientAdapterState = newState; - } - - // Update state text - final String btClientAdapterState = ClientAdapter.stateToString(mBtClientAdapterState); - final String wfdClientAdapterState = ClientAdapter.stateToString - (mWfdClientAdapterState); - final String stateString = "BT: " + btClientAdapterState + " / WFD: " + - wfdClientAdapterState; - - runOnUiThread(new Runnable() { - @Override - public void run() { - // Update UI - TextView adapterStateTextView = (TextView) findViewById(R.id - .adapterStateTextView); - adapterStateTextView.setText(stateString); - - // Add Log - Logger.VERB("Adapters", stateString); - } - }); - } - }; - - private OnStartSCResult onStartSCResult = new OnStartSCResult() { - private int mRetries = 0; - private static final int kMaxRetries = 5; - - @Override - public void onDoneStartSC(boolean isSuccess) { - if (isSuccess) { - // Starting Selective Connection is done - ReceivingThread receivingThread = new ReceivingThread(); - receivingThread.start(); - } else { - // Retry to start SC - if (mRetries++ < kMaxRetries) { - Logger.VERB(kTag, "Failed to start SC... Retry to start."); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - API.startSC(onStartSCResult); - } - } - } - }; - - private OnStopSCResult onStopSCResult = new OnStopSCResult() { - @Override - public void onDoneStopSC(boolean isSuccess) { - if (!isSuccess) { - Log.e(kTag, "Stopping Selective Connection failed"); - } - } - }; - - private class SpeedWatcherThread extends Thread { - private Date mLastAccessedTS; - private int mPrevValue; - private int mTotalDataSize; // Bytes - private final int kSleepMS = 1000; - - public void arrive(int dataSize) { - this.mTotalDataSize += dataSize; - } - - private int getSpeed() { - int speed; - - Date startTS = this.mLastAccessedTS; - Date endTS = new Date(); - int prevValue = this.mPrevValue; - int presentValue = this.mTotalDataSize; - - speed = (int) ((float) (presentValue - prevValue) / ((float) (endTS.getTime() - - startTS.getTime()) / 1000)); - - this.mLastAccessedTS = endTS; - this.mPrevValue = presentValue; - - return speed; - } - - @SuppressLint("SetTextI18n") - @SuppressWarnings("InfiniteLoopStatement") - @Override - public void run() { - this.setName("SpeedWatcher"); - this.mPrevValue = 0; - this.mTotalDataSize = 0; - this.mLastAccessedTS = new Date(); - while (true) { - final int speed = this.getSpeed(); - runOnUiThread(new Runnable() { - @Override - public void run() { - TextView bandwidthTextView = (TextView) findViewById(R.id - .bandwidthTextView); - NumberFormat format = NumberFormat.getNumberInstance(); - if (VERBOSE_BANDWIDTH_UPDATE) { - Log.d(kTag, "Bandwidth update: " + format.format(speed) + "B/s"); - } - bandwidthTextView.setText("Bandwidth: " + format.format(speed) + "B/s"); - } - }); - try { - Thread.sleep(kSleepMS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - private class ReceivingThread extends Thread { - private static final String kTag = "Recv"; - private boolean mIsAlive; - private final boolean kVerboseReceivingThread = false; - - ReceivingThread() { - this.mIsAlive = false; - } - - @Override - public void run() { - this.setName("AppReceiving"); - this.mIsAlive = true; - byte[] buf = new byte[100 * 1024 * 1024]; - String sending_buf = "ACK"; /* Ack Message */ - - while (this.mIsAlive) { - int receivedLength = API.receive(buf); - mSpeedWatcherThread.arrive(receivedLength); - if (kVerboseReceivingThread) { - Logger.DEBUG(kTag, "Received: Size=" + receivedLength); - } - } - } - - public void terminate() { - this.mIsAlive = false; - } - } - - @Override - public void onLogMessage(final int logLevel, final String logTag, final String logMessage) { - final int kPrintThreshold = LogLevel.VERB; - final String kTag = "LOG"; - this.runOnUiThread(new Runnable() { - @SuppressLint("SetTextI18n") - @Override - public void run() { - String printLevel = ""; - int color = Color.BLACK; - switch (logLevel) { - case LogLevel.ERR: - Log.e(logTag, logMessage); - printLevel = "E"; - color = Color.RED; - break; - case LogLevel.WARN: - Log.w(logTag, logMessage); - printLevel = "W"; - color = Color.parseColor("#FF8000"); - break; - case LogLevel.VERB: - Log.i(logTag, logMessage); - printLevel = "V"; - color = Color.parseColor("#0072C1"); - break; - case LogLevel.DEBUG: - Log.d(logTag, logMessage); - printLevel = "D"; - color = Color.parseColor("#5C676F"); - break; - } - String printMessage = "[" + printLevel + "/" + logTag + "] " + logMessage; - - if (logLevel <= kPrintThreshold) { - mLogListViewData.add(0, new LogListViewItem(printMessage, color)); - mLogListViewAdapter.notifyDataSetChanged(); - } - } - }); - } -} - -class LogListViewItem { - private String mText; - private int mColor; - - public String getText() { - return this.mText; - } - - public int getColor() { - return this.mColor; - } - - LogListViewItem(String text, int color) { - this.mText = text; - this.mColor = color; - } -} - -class LogListViewAdapter extends BaseAdapter { - private LayoutInflater mInflater; - private int mLayout; - private ArrayList mData; - - LogListViewAdapter(Context context, ArrayList data) { - this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - this.mLayout = R.layout.item; - this.mData = data; - } - - @Override - public int getCount() { - return this.mData.size(); - } - - @Override - public String getItem(int position) { - return this.mData.get(position).getText(); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(this.mLayout, parent, false); - } - - LogListViewItem item = this.mData.get(position); - TextView contentsTextView = (TextView) convertView.findViewById(R.id.contentsTextView); - contentsTextView.setText(item.getText()); - contentsTextView.setTextColor(item.getColor()); - return contentsTextView; - } -} \ No newline at end of file diff --git a/subprojects/sc/android/app/src/main/res/layout/activity_main.xml b/subprojects/sc/android/app/src/main/res/layout/activity_main.xml deleted file mode 100755 index 5aaada2f..00000000 --- a/subprojects/sc/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - -