diff --git a/android-ngn-stack/src/main/java/org/doubango/ngn/NgnApplication.java b/android-ngn-stack/src/main/java/org/doubango/ngn/NgnApplication.java index 85ce36eaeff12e148055290ef1b1001d94238ddb..32ba0a23446f8ac728ecf256da370cbc512b3d35 100644 --- a/android-ngn-stack/src/main/java/org/doubango/ngn/NgnApplication.java +++ b/android-ngn-stack/src/main/java/org/doubango/ngn/NgnApplication.java @@ -623,8 +623,8 @@ public class NgnApplication extends Application{ // FIXME: one-way audio on Galaxy SII and Nexus //return isSLEs2Supported() && Arrays.asList(sSLEs2FriendlyBuildModels).contains(sBuildModel); // AcceptOnlyIn(Array) //return isSLEs2Supported() && !Arrays.asList(sSLEs2UnFriendlyBuildModels).contains(sBuildModel); // AcceptAllExceptIn(Array) - //return false; - return true; + return false; +// return true; //return isHovis(); //false; } diff --git a/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioConsumer.java b/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioConsumer.java index 49b5f01434555789bd0a8605b167fb4c2a6e7beb..8b84b836e0621e3e39f0fe93151671d7a36908c4 100644 --- a/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioConsumer.java +++ b/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioConsumer.java @@ -1,110 +1,111 @@ /* Copyright (C) 2010-2011, Mamadou Diop. -* Copyright (C) 2011, Doubango Telecom. -* Copyright (C) 2011, Philippe Verney -* -* Contact: Mamadou Diop -* -* This file is part of Open Source Doubango Framework. -* -* This is free software: you can redistribute it and/or modify it under the terms of -* the GNU General Public License as published by the Free Software Foundation, either version 3 -* of the License, or (at your option) any later version. -* -* This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* See the GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ + * Copyright (C) 2011, Doubango Telecom. + * Copyright (C) 2011, Philippe Verney + * + * Contact: Mamadou Diop + * + * This file is part of Open Source Doubango Framework. + * + * This is free software: you can redistribute it and/or modify it under the terms of + * the GNU General Public License as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ package org.doubango.ngn.media; +import android.content.Intent; import android.media.AudioFormat; - import android.media.AudioManager; - import android.media.AudioTrack; - import android.util.Log; +import android.media.AudioManager; +import android.media.AudioTrack; +import android.util.Log; import org.doubango.ngn.BuildConfig; import org.doubango.ngn.NgnApplication; - import org.doubango.ngn.NgnEngine; - import org.doubango.ngn.services.INgnConfigurationService; - import org.doubango.ngn.utils.NgnConfigurationEntry; - import org.doubango.tinyWRAP.ProxyAudioConsumer; - import org.doubango.tinyWRAP.ProxyAudioConsumerCallback; - import org.doubango.utils.Utils; - - import java.math.BigInteger; - import java.nio.ByteBuffer; - import java.util.Arrays; - -public class NgnProxyAudioConsumer extends NgnProxyPlugin{ - private static final String TAG = Utils.getTAG(NgnProxyAudioConsumer.class.getCanonicalName()); - private static final int AUDIO_STREAM_TYPE = AudioManager.STREAM_VOICE_CALL; - - private final INgnConfigurationService mConfigurationService; - private final MyProxyAudioConsumerCallback mCallback; - private final ProxyAudioConsumer mConsumer; - private boolean mRoutingChanged; - private Thread mConsumerThread; - - private int mBufferSize; - private AudioTrack mAudioTrack; - private int mPtime, mInputRate, mChannels; - - private int mOutputRate; - private ByteBuffer mOutputBuffer; - private boolean mAec ; - private boolean mIsInit = false ; - private static final int BUFFER_SIZE_DEFAULT=100; - - - - public NgnProxyAudioConsumer(BigInteger id, ProxyAudioConsumer consumer){ - super(id, consumer); +import org.doubango.ngn.NgnEngine; +import org.doubango.ngn.services.INgnConfigurationService; +import org.doubango.ngn.utils.NgnConfigurationEntry; +import org.doubango.tinyWRAP.ProxyAudioConsumer; +import org.doubango.tinyWRAP.ProxyAudioConsumerCallback; +import org.doubango.utils.Utils; + +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.Arrays; + +public class NgnProxyAudioConsumer extends NgnProxyPlugin { + public static final String ACTION_DATA_RECEIVED = "org.doubango.ngn.mediaNgnProxyAudioConsumer.dataReceived"; + public static final String EXTRA_DATA = "data"; + + private static final String TAG = Utils.getTAG(NgnProxyAudioConsumer.class.getCanonicalName()); + private static final int AUDIO_STREAM_TYPE = AudioManager.STREAM_VOICE_CALL; + + private final INgnConfigurationService mConfigurationService; + private final MyProxyAudioConsumerCallback mCallback; + private final ProxyAudioConsumer mConsumer; + private boolean mRoutingChanged; + private Thread mConsumerThread; + + private int mBufferSize; + private AudioTrack mAudioTrack; + private int mPtime, mInputRate, mChannels; + + private int mOutputRate; + private ByteBuffer mOutputBuffer; + private boolean mAec; + private boolean mIsInit = false; + private static final int BUFFER_SIZE_DEFAULT = 100; + + + public NgnProxyAudioConsumer(BigInteger id, ProxyAudioConsumer consumer) { + super(id, consumer); mCallback = new MyProxyAudioConsumerCallback(this); mConsumer = consumer; mConsumer.setCallback(mCallback); mConfigurationService = NgnEngine.getInstance().getConfigurationService(); - } - - public void setSpeakerphoneOn(boolean speakerOn){ - Log.d(TAG, "setSpeakerphoneOn("+speakerOn+")"); - final AudioManager audiomanager = NgnApplication.getAudioManager(); - if (NgnApplication.getSDKVersion() < 5){ - audiomanager.setRouting(AudioManager.MODE_IN_CALL, - speakerOn ? AudioManager.ROUTE_SPEAKER : AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL); - } - else if(NgnApplication.useSetModeToHackSpeaker()){ - audiomanager.setMode(AudioManager.MODE_IN_CALL); - audiomanager.setSpeakerphoneOn(speakerOn); - audiomanager.setMode(AudioManager.MODE_NORMAL); - } - else{ - audiomanager.setSpeakerphoneOn(speakerOn); - } - - if (super.mPrepared){ - mRoutingChanged = NgnApplication.isAudioRecreateRequired(); - changeVolume(false,false);// disable attenuation - } - } - - public void toggleSpeakerphone(){ - setSpeakerphoneOn(!NgnApplication.getAudioManager().isSpeakerphoneOn()); - } - - public boolean onVolumeChanged(boolean bDown){ - if(!mPrepared || mAudioTrack == null){ - return false; - } - return changeVolume(bDown, true); - } - - private boolean changeVolume(boolean bDown, boolean bVolumeChanged){ - Log.d(TAG,"changeVolume("+bDown+","+bVolumeChanged+ ") aec:"+mAec); - final AudioManager audioManager = NgnApplication.getAudioManager(); - if(audioManager != null){ + } + + public void setSpeakerphoneOn(boolean speakerOn) { + Log.d(TAG, "setSpeakerphoneOn(" + speakerOn + ")"); + final AudioManager audiomanager = NgnApplication.getAudioManager(); + if (NgnApplication.getSDKVersion() < 5) { + audiomanager.setRouting(AudioManager.MODE_IN_CALL, + speakerOn ? AudioManager.ROUTE_SPEAKER : AudioManager.ROUTE_EARPIECE, AudioManager.ROUTE_ALL); + } else if (NgnApplication.useSetModeToHackSpeaker()) { + audiomanager.setMode(AudioManager.MODE_IN_CALL); + audiomanager.setSpeakerphoneOn(speakerOn); + audiomanager.setMode(AudioManager.MODE_NORMAL); + } else { + audiomanager.setSpeakerphoneOn(speakerOn); + } + + if (super.mPrepared) { + mRoutingChanged = NgnApplication.isAudioRecreateRequired(); + changeVolume(false, false);// disable attenuation + } + } + + public void toggleSpeakerphone() { + setSpeakerphoneOn(!NgnApplication.getAudioManager().isSpeakerphoneOn()); + } + + public boolean onVolumeChanged(boolean bDown) { + if (!mPrepared || mAudioTrack == null) { + return false; + } + return changeVolume(bDown, true); + } + + private boolean changeVolume(boolean bDown, boolean bVolumeChanged) { + Log.d(TAG, "changeVolume(" + bDown + "," + bVolumeChanged + ") aec:" + mAec); + final AudioManager audioManager = NgnApplication.getAudioManager(); + if (audioManager != null) { /*if( !mIsInit && mAec && NgnApplication.getAudioManager().isSpeakerphoneOn() ){ mIsInit = true ; Log.d(TAG, "Consumer changeVolume HP on AEC"); @@ -125,219 +126,219 @@ public class NgnProxyAudioConsumer extends NgnProxyPlugin{ Log.d(TAG, "Consumer changeVolume audio attenuation "+attenuation); return true ; //mAudioTrack.setStereoVolume(AudioTrack.getMaxVolume()*attenuation, AudioTrack.getMaxVolume()*attenuation) == AudioTrack.SUCCESS; }*/ - } - return false; - } - - - private int prepareCallback(int ptime, int rate, int channels) { - Log.d(TAG, "prepareCallback("+ptime+","+rate+","+channels+")"); - return prepare(ptime, rate, channels); - } - - private int startCallback() { - Log.d(TAG, "startCallback"); - if(mPrepared && this.mAudioTrack != null){ - super.mStarted = true; - mConsumerThread = new Thread(mRunnablePlayer, "AudioConsumerThread"); - // mConsumerThread.setPriority(Thread.MAX_PRIORITY); - mConsumerThread.start(); - return 0; - } - return -1; - } - - private int pauseCallback() { - Log.d(TAG, "pauseCallback"); - if(mAudioTrack != null){ - synchronized(mAudioTrack){ - mAudioTrack.pause(); - super.mPaused = true; - } - return 0; - } - return -1; - } - - private int stopCallback() { - if(BuildConfig.DEBUG)Log.d(TAG, "stopCallback: " + "NgnProxyAudioConsumer"); - Log.d(TAG, "stopCallback"); - super.mStarted = false; - if(mConsumerThread != null){ - try { - mConsumerThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - mConsumerThread = null; - } - return 0; - } - - public synchronized boolean setGain(long gain){ - return mConsumer.setGain(gain); - } - - private synchronized int prepare(int ptime, int rate, int channels){ - int bytesNseq=0; - if(super.mPrepared){ - Log.e(TAG,"already prepared"); - return -1; - } - - mPtime = ptime; mInputRate = rate; mChannels = channels; - mOutputRate = AudioTrack.getNativeOutputSampleRate(AUDIO_STREAM_TYPE); - if(super.mValid && mConsumer != null && mInputRate != mOutputRate){ - if(mConsumer.queryForResampler(mInputRate, mOutputRate, mPtime, mChannels, - mConfigurationService.getInt(NgnConfigurationEntry.MEDIA_AUDIO_RESAMPLER_QUALITY, NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_RESAMPLER_QUALITY))){ - Log.d(TAG, "queryForResampler("+mOutputRate+") succeed"); - } - else{ - Log.e(TAG, "queryForResampler("+mOutputRate+") failed. Using "+mInputRate); - mOutputRate = mInputRate; - } - } - - final int minBufferSize = AudioTrack.getMinBufferSize(mOutputRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); - final int shortsPerNotif = (mOutputRate * mPtime)/1000; - mBufferSize = Math.max(minBufferSize, shortsPerNotif<<1); - mBufferSize=BUFFER_SIZE_DEFAULT; - mOutputBuffer = ByteBuffer.allocateDirect((shortsPerNotif<<1)+bytesNseq); - mAec = mConfigurationService.getBoolean(NgnConfigurationEntry.GENERAL_AEC, NgnConfigurationEntry.DEFAULT_GENERAL_AEC) ; - - // setSpeakerphoneOn(false); - mAudioTrack = new AudioTrack(AUDIO_STREAM_TYPE, - mOutputRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, - mBufferSize, AudioTrack.MODE_STREAM); - if(mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED){ - Log.d(TAG, "Consumer BufferSize="+mBufferSize+",MinBufferSize="+minBufferSize+",TrueSampleRate="+mAudioTrack.getSampleRate()+" shortsPerNotif<<1:"+(shortsPerNotif<<1)+" mOutputRate:"+mOutputRate+" mPtime:"+mPtime); - changeVolume(false, false); - super.mPrepared = true; - return 0; - } - else{ - Log.e(TAG, "prepare() failed"); - super.mPrepared = false; - return -1; - } - } - - private synchronized void unprepare(){ - if(mAudioTrack != null){ - synchronized(mAudioTrack){ - if(super.mPrepared){ - mAudioTrack.stop(); - } - mAudioTrack.release(); - mAudioTrack = null; - } - } - super.mPrepared = false; - } - - private Runnable mRunnablePlayer = new Runnable(){ - @Override - public void run() { - Log.d(TAG, "===== Audio Player Thread (Start) ====="); - - android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO); - - int nFrameLength = mOutputBuffer.capacity(); - final int nFramesCount = 1; // Number of 20ms' to copy - final byte[] aAudioBytes = new byte[nFrameLength*nFramesCount]; - int i, nGapSize; - long lSizeInBytes = 0 ; - boolean bPlaying = false; - int nWritten = 0; - int bytesNseq=0; - int seq=0; - - - if(NgnProxyAudioConsumer.super.mValid){ - mConsumer.setPullBuffer(mOutputBuffer, mOutputBuffer.capacity()); - mConsumer.setGain(NgnEngine.getInstance().getConfigurationService().getInt(NgnConfigurationEntry.MEDIA_AUDIO_CONSUMER_GAIN, - NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_CONSUMER_GAIN)); - } - - while(NgnProxyAudioConsumer.super.mValid && NgnProxyAudioConsumer.super.mStarted){ - if(mAudioTrack == null){ - break; - } - - if(mRoutingChanged){ - Log.d(TAG, "Routing changed: restart() player"); - mRoutingChanged = false; - unprepare(); - if(prepare(mPtime, mOutputRate, mChannels) != 0){ - break; - } - if(!NgnProxyAudioConsumer.super.mPaused){ - bPlaying = false; - nWritten = 0; - } - } - - for(i=0; i0){ - mOutputBuffer.get(aAudioBytes, i*nFrameLength, (int)lSizeInBytes+bytesNseq); - mOutputBuffer.rewind(); - nGapSize = (nFrameLength - (int)lSizeInBytes)-bytesNseq; - if(nGapSize != 0){ - Arrays.fill(aAudioBytes, i*nFrameLength + (int)lSizeInBytes, (i*nFrameLength + (int)lSizeInBytes) + nGapSize, (byte)0); - } - } - else{ - Arrays.fill(aAudioBytes, i*nFrameLength, (i*nFrameLength)+nFrameLength, (byte)0); - } - nWritten += nFrameLength; - } - - - mAudioTrack.write(aAudioBytes, 0, aAudioBytes.length-bytesNseq); - if( - - !bPlaying && nWritten>mBufferSize){ - mAudioTrack.play(); - bPlaying = true; - } - } + } + return false; + } + + + private int prepareCallback(int ptime, int rate, int channels) { + Log.d(TAG, "prepareCallback(" + ptime + "," + rate + "," + channels + ")"); + return prepare(ptime, rate, channels); + } + + private int startCallback() { + Log.d(TAG, "startCallback"); + if (mPrepared && this.mAudioTrack != null) { + super.mStarted = true; + mConsumerThread = new Thread(mRunnablePlayer, "AudioConsumerThread"); + // mConsumerThread.setPriority(Thread.MAX_PRIORITY); + mConsumerThread.start(); + return 0; + } + return -1; + } + + private int pauseCallback() { + Log.d(TAG, "pauseCallback"); + if (mAudioTrack != null) { + synchronized (mAudioTrack) { + mAudioTrack.pause(); + super.mPaused = true; + } + return 0; + } + return -1; + } + + private int stopCallback() { + if (BuildConfig.DEBUG) Log.d(TAG, "stopCallback: " + "NgnProxyAudioConsumer"); + Log.d(TAG, "stopCallback"); + super.mStarted = false; + if (mConsumerThread != null) { + try { + mConsumerThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mConsumerThread = null; + } + return 0; + } + + public synchronized boolean setGain(long gain) { + return mConsumer.setGain(gain); + } + + private synchronized int prepare(int ptime, int rate, int channels) { + int bytesNseq = 0; + if (super.mPrepared) { + Log.e(TAG, "already prepared"); + return -1; + } + + mPtime = ptime; + mInputRate = rate; + mChannels = channels; + mOutputRate = AudioTrack.getNativeOutputSampleRate(AUDIO_STREAM_TYPE); + if (super.mValid && mConsumer != null && mInputRate != mOutputRate) { +// if (mConsumer.queryForResampler(mInputRate, mOutputRate, mPtime, mChannels, +// mConfigurationService.getInt(NgnConfigurationEntry.MEDIA_AUDIO_RESAMPLER_QUALITY, NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_RESAMPLER_QUALITY))) { +// Log.d(TAG, "queryForResampler(" + mOutputRate + ") succeed"); +// } else { + Log.e(TAG, "queryForResampler(" + mOutputRate + ") failed. Using " + mInputRate); + mOutputRate = mInputRate; +// } + } + + final int minBufferSize = AudioTrack.getMinBufferSize(mOutputRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); + final int shortsPerNotif = (mOutputRate * mPtime) / 1000; + mBufferSize = Math.max(minBufferSize, shortsPerNotif << 1); + mBufferSize = BUFFER_SIZE_DEFAULT; + mOutputBuffer = ByteBuffer.allocateDirect((shortsPerNotif << 1) + bytesNseq); + mAec = mConfigurationService.getBoolean(NgnConfigurationEntry.GENERAL_AEC, NgnConfigurationEntry.DEFAULT_GENERAL_AEC); + + // setSpeakerphoneOn(false); + mAudioTrack = new AudioTrack(AUDIO_STREAM_TYPE, + mOutputRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, + mBufferSize, AudioTrack.MODE_STREAM); + if (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) { + Log.d(TAG, "Consumer BufferSize=" + mBufferSize + ",MinBufferSize=" + minBufferSize + ",TrueSampleRate=" + mAudioTrack.getSampleRate() + " shortsPerNotif<<1:" + (shortsPerNotif << 1) + " mOutputRate:" + mOutputRate + " mPtime:" + mPtime); + mAudioTrack.setStereoVolume(0, 0); + changeVolume(false, false); + super.mPrepared = true; + return 0; + } else { + Log.e(TAG, "prepare() failed"); + super.mPrepared = false; + return -1; + } + } + + private synchronized void unprepare() { + if (mAudioTrack != null) { + synchronized (mAudioTrack) { + if (super.mPrepared) { + mAudioTrack.stop(); + } + mAudioTrack.release(); + mAudioTrack = null; + } + } + super.mPrepared = false; + } + + private Runnable mRunnablePlayer = new Runnable() { + @Override + public void run() { + Log.d(TAG, "===== Audio Player Thread (Start) ====="); + + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO); + + int nFrameLength = mOutputBuffer.capacity(); + final int nFramesCount = 1; // Number of 20ms' to copy + final byte[] aAudioBytes = new byte[nFrameLength * nFramesCount]; + int i, nGapSize; + long lSizeInBytes = 0; + boolean bPlaying = false; + int nWritten = 0; + int bytesNseq = 0; + int seq = 0; + + + if (NgnProxyAudioConsumer.super.mValid) { + mConsumer.setPullBuffer(mOutputBuffer, mOutputBuffer.capacity()); + mConsumer.setGain(NgnEngine.getInstance().getConfigurationService().getInt(NgnConfigurationEntry.MEDIA_AUDIO_CONSUMER_GAIN, + NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_CONSUMER_GAIN)); + } + + while (NgnProxyAudioConsumer.super.mValid && NgnProxyAudioConsumer.super.mStarted) { + if (mAudioTrack == null) { + break; + } + + if (mRoutingChanged) { + Log.d(TAG, "Routing changed: restart() player"); + mRoutingChanged = false; + unprepare(); + if (prepare(mPtime, mOutputRate, mChannels) != 0) { + break; + } + if (!NgnProxyAudioConsumer.super.mPaused) { + bPlaying = false; + nWritten = 0; + } + } + + for (i = 0; i < nFramesCount; i++) { + lSizeInBytes = mConsumer.pull(); + if (lSizeInBytes > 0) { + mOutputBuffer.get(aAudioBytes, i * nFrameLength, (int) lSizeInBytes + bytesNseq); + mOutputBuffer.rewind(); + nGapSize = (nFrameLength - (int) lSizeInBytes) - bytesNseq; + if (nGapSize != 0) { + Arrays.fill(aAudioBytes, i * nFrameLength + (int) lSizeInBytes, (i * nFrameLength + (int) lSizeInBytes) + nGapSize, (byte) 0); + } + } else { + Arrays.fill(aAudioBytes, i * nFrameLength, (i * nFrameLength) + nFrameLength, (byte) 0); + } + nWritten += nFrameLength; + } + + byte[] buf = new byte[aAudioBytes.length - bytesNseq]; + System.arraycopy(aAudioBytes, 0, buf, 0, aAudioBytes.length - bytesNseq); + NgnApplication.getContext().sendBroadcast(new Intent(ACTION_DATA_RECEIVED).putExtra(EXTRA_DATA, buf)); + mAudioTrack.write(aAudioBytes, 0, aAudioBytes.length - bytesNseq); + + if (!bPlaying && nWritten > mBufferSize) { + mAudioTrack.play(); + bPlaying = true; + } + } + + unprepare(); + Log.d(TAG, "===== Audio Player Thread (Stop) ====="); + } + }; + + /** + * MyProxyAudioConsumerCallback + */ + static class MyProxyAudioConsumerCallback extends ProxyAudioConsumerCallback { + final NgnProxyAudioConsumer myConsumer; + + MyProxyAudioConsumerCallback(NgnProxyAudioConsumer consumer) { + super(); + myConsumer = consumer; + } + + @Override + public int prepare(int ptime, int rate, int channels) { + return myConsumer.prepareCallback(ptime, rate, channels); + } + + @Override + public int start() { + return myConsumer.startCallback(); + } + + @Override + public int pause() { + return myConsumer.pauseCallback(); + } - unprepare(); - Log.d(TAG, "===== Audio Player Thread (Stop) ====="); - } - }; - - /** - * MyProxyAudioConsumerCallback - */ - static class MyProxyAudioConsumerCallback extends ProxyAudioConsumerCallback - { - final NgnProxyAudioConsumer myConsumer; - - MyProxyAudioConsumerCallback(NgnProxyAudioConsumer consumer){ - super(); - myConsumer = consumer; - } - - @Override - public int prepare(int ptime, int rate, int channels) { - return myConsumer.prepareCallback(ptime, rate, channels); - } - - @Override - public int start() { - return myConsumer.startCallback(); - } - - @Override - public int pause() { - return myConsumer.pauseCallback(); - } - - @Override - public int stop() { - return myConsumer.stopCallback(); - } - } + @Override + public int stop() { + return myConsumer.stopCallback(); + } + } } diff --git a/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioProducer.java b/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioProducer.java index 14d5f6f820e5b84e446bab2e153eb04f8d6386f4..06604779e52810466456448e58c8043fa32fc731 100644 --- a/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioProducer.java +++ b/android-ngn-stack/src/main/java/org/doubango/ngn/media/NgnProxyAudioProducer.java @@ -3,23 +3,27 @@ * Copyright (C) 2011, Philippe Verney * * Contact: Mamadou Diop - * + * * This file is part of Open Source Doubango Framework. * * This is free software: you can redistribute it and/or modify it under the terms of - * the GNU General Public License as published by the Free Software Foundation, either version 3 + * the GNU General Public License as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. - * + * * This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.doubango.ngn.media; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; @@ -35,333 +39,376 @@ import org.doubango.utils.Utils; import java.math.BigInteger; import java.nio.ByteBuffer; +import java.util.ArrayList; public class NgnProxyAudioProducer extends NgnProxyPlugin { - private static final String TAG = Utils.getTAG(NgnProxyAudioProducer.class - .getCanonicalName()); - private final static float AUDIO_BUFFER_FACTOR = 2.f; - @SuppressWarnings("unused") - private final static int AUDIO_MIN_VALID_BUFFER_SIZE = 4096; - @SuppressWarnings("unused") - private final static int AUDIO_DEFAULT_BUFFER_SIZE = 6200; - - private final MyProxyAudioProducerCallback mCallback; - private final ProxyAudioProducer mProducer; - private boolean mRoutingChanged; - private boolean mOnMute; - private boolean mHasBuiltInAEC; - - private Thread mProducerThread; - private AudioRecord mAudioRecord; - private ByteBuffer mAudioFrame; - private int mPtime, mRate, mChannels; - - public NgnProxyAudioProducer(BigInteger id, ProxyAudioProducer producer) { - super(id, producer); - mProducer = producer; - mCallback = new MyProxyAudioProducerCallback(this); - mProducer.setCallback(mCallback); - mOnMute = false; - mHasBuiltInAEC = false; - } - - public void setOnPause(boolean pause) { - if (super.mPaused == pause) { - return; - } - try { - if (this.mStarted) { - - } - } catch (Exception e) { - Log.e(TAG, e.toString()); - } - - super.mPaused = pause; - } - - public void setOnMute(boolean mute) { - mOnMute = mute; - } - - public boolean isOnMute() { - return mOnMute; - } - - public void setSpeakerphoneOn(boolean speakerOn) { - Log.d(TAG, "setSpeakerphoneOn(" + speakerOn + ")"); - if (NgnApplication.isAudioRecreateRequired()) { - if (super.mPrepared) { - mRoutingChanged = true; - } - } - } - - public void toggleSpeakerphone() { - setSpeakerphoneOn(!NgnApplication.getAudioManager().isSpeakerphoneOn()); - } - - public boolean isSpeakerOn(){ - return NgnApplication.getAudioManager().isSpeakerphoneOn(); - } - - public boolean onVolumeChanged(boolean bDown) { - return true; - } - - private int prepareCallback(int ptime, int rate, int channels) { - Log.d(NgnProxyAudioProducer.TAG, "prepareCallback(" + ptime + "," - + rate + "," + channels + ")"); - return prepare(ptime, rate, channels); - } - - private int startCallback() { - Log.d(NgnProxyAudioProducer.TAG, "startCallback"); - if (mPrepared && mAudioRecord != null) { - super.mStarted = true; - mProducerThread = new Thread(mRunnableRecorder, - "AudioProducerThread"); - //mProducerThread.setPriority(Thread.MAX_PRIORITY); - mProducerThread.start(); - return 0; - } - return -1; - } - - /** - * Function called when the native producer (C++) is ready to send data (every @b ptime milliseconds). It's up to you to fill the data. - * This function is only called if you register a buffer using @ref setPushBuffer(pPushBufferPtr, nPushBufferSize, bUsePushCallback) with @b bUsePushCallback equal to @b true - */ - private int fillPushBuffer(){ - // sample code - // for performance reasons, 'is' and 'buff' must be created once - // up to you to manage the offset index (circle buffer) - // InputStream is = getContext().getAssets().open("audio.wav"); - // byte buff[] = new byte[(int)nPushBufferSize]; // for performance reasons, create once - // is.read(buff, offset, buff.length); - // mAudioFrame.put(buff); - // pmAudioFrame.rewind(); - // is.close(); - Log.d(TAG, "fillPushBuffer"); - return 0; - } - - private int pauseCallback() { - Log.d(NgnProxyAudioProducer.TAG, "pauseCallback"); - setOnPause(true); - return 0; - } - - private int stopCallback() { - Log.d(NgnProxyAudioProducer.TAG, "stopCallback"); - super.mStarted = false; - if (mProducerThread != null) { - try { - mProducerThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - mProducerThread = null; - } - return 0; - } - - private synchronized int prepare(int ptime, int rate, int channels) { - int bytesNseq=0; - if (super.mPrepared) { - Log.e(TAG, "already prepared"); - return -1; - } - Log.d(TAG,"prepare("+ptime+","+rate+","+channels); - - // Use 44100hz for Hovis_Box_V1 - if (NgnApplication.isHovis()) { - rate = 44100; - mProducer.setActualSndCardRecordParams(ptime, rate, channels); - } - - final boolean aecEnabled = NgnEngine.getInstance() - .getConfigurationService().getBoolean( - NgnConfigurationEntry.GENERAL_AEC, - NgnConfigurationEntry.DEFAULT_GENERAL_AEC); - - final int minBufferSize = AudioRecord.getMinBufferSize(rate, - AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); - final int shortsPerNotif = (rate * ptime) / 1000; - // AEC won't work if there is too much delay - // Too short bufferSize will produce BufferOverflow errors but we don't - // have choice if we want AEC - final float bufferFactor = aecEnabled ? NgnProxyAudioProducer.AUDIO_BUFFER_FACTOR - : NgnProxyAudioProducer.AUDIO_BUFFER_FACTOR; - final int bufferSize = Math.max( - (int) ((float) minBufferSize * bufferFactor), - shortsPerNotif << 1); - mAudioFrame = ByteBuffer.allocateDirect((shortsPerNotif << 1)+bytesNseq); - mPtime = ptime; - mRate = rate; - mChannels = channels; - Log.d(TAG, "Configure aecEnabled:" + aecEnabled); - int audioSrc = MediaRecorder.AudioSource.MIC; - - if (aecEnabled) { - //audioSrc = MediaRecorder.AudioSource.VOICE_RECOGNITION; - // Do not use built-in AEC - /* - * if(NgnApplication.getSDKVersion() >= 11){ try { final Field f = - * MediaRecorder - * .AudioSource.class.getDeclaredField("VOICE_COMMUNICATION"); - * audioSrc = f.getInt(null); mHasBuiltInAEC = true; } catch - * (Exception e) { e.printStackTrace(); } } - */ - } - - // Use CAMCORDER audio source for Hovis_Box_V1 - if (NgnApplication.isHovis()) { - audioSrc = MediaRecorder.AudioSource.CAMCORDER; - } - - mAudioRecord = new AudioRecord(audioSrc, rate, - AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, - bufferSize); - - if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) { - super.mPrepared = true; - return 0; - } else { - Log.e(TAG, "prepare(" + mAudioRecord.getState() + ") failed"); - super.mPrepared = false; - return -1; - } - } - - private synchronized void unprepare() { - if (mAudioRecord != null) { - synchronized (mAudioRecord) { - if (super.mPrepared) { // only call stop() is the AudioRecord is - // in initialized state - mAudioRecord.stop(); - } - mAudioRecord.release(); - mAudioRecord = null; - } - } - super.mPrepared = false; - } - - private Runnable mRunnableRecorder = new Runnable() { - @Override - public void run() { - Log.d(TAG, "===== Audio Recorder (Start) ===== "); - android.os.Process - .setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); - - int bytesNseq=0; - long curretTime=0; - - mAudioRecord.startRecording(); - final int nSize = mAudioFrame.capacity()-bytesNseq; - byte silenceBuffer[] = new byte[nSize]; - int nRead; - - if (NgnProxyAudioProducer.super.mValid) { - mProducer.setPushBuffer(mAudioFrame, mAudioFrame.capacity(), false); - mProducer - .setGain(NgnEngine - .getInstance() - .getConfigurationService() - .getInt( - NgnConfigurationEntry.MEDIA_AUDIO_PRODUCER_GAIN, - NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_PRODUCER_GAIN)); - } - // disable Doubango AEC - if (mHasBuiltInAEC) { - final NgnAVSession ngnAVSession = NgnAVSession - .getSession(getSipSessionId()); - if (ngnAVSession != null) { - ngnAVSession.setAECEnabled(false); - } - } - - while (NgnProxyAudioProducer.super.mValid && mStarted) { - if (mAudioRecord == null) { - break; - } - if (mRoutingChanged) { - Log.d(TAG, "Routing changed: restart() recorder"); - mRoutingChanged = false; - unprepare(); - if (prepare(mPtime, mRate, mChannels) != 0) { - break; - } - if (!NgnProxyAudioProducer.super.mPaused) { - mAudioRecord.startRecording(); - } - } - - // To avoid overrun read data even if on pause/mute we have to - // read - if ((nRead = mAudioRecord.read(mAudioFrame, nSize)) > 0) { - if (!NgnProxyAudioProducer.super.mPaused) { - if (mOnMute) { // workaround because Android's - // SetMicrophoneOnMute() is buggy - mAudioFrame.put(silenceBuffer); - mProducer.push(mAudioFrame, silenceBuffer.length); - mAudioFrame.rewind(); - } else { - if (nRead != nSize) { - mProducer.push(mAudioFrame, nRead); - Log.w(TAG, "BufferOverflow?"); - } else { - mProducer.push(); - } - } - } - } - + public static final String ACTION_ADD_SEND = "org.doubango.ngn.media.NgnProxyAudioProducer.addSend"; + public static final String EXTRA_DATA = "data"; + + private static final String TAG = Utils.getTAG(NgnProxyAudioProducer.class + .getCanonicalName()); + private final static float AUDIO_BUFFER_FACTOR = 2.f; + @SuppressWarnings("unused") + private final static int AUDIO_MIN_VALID_BUFFER_SIZE = 4096; + @SuppressWarnings("unused") + private final static int AUDIO_DEFAULT_BUFFER_SIZE = 6200; + + private final MyProxyAudioProducerCallback mCallback; + private final ProxyAudioProducer mProducer; + private boolean mRoutingChanged; + private boolean mOnMute; + private boolean mHasBuiltInAEC; + + private Thread mProducerThread; + // private AudioRecord mAudioRecord; + private ByteBuffer mAudioFrame; + private int mPtime, mRate, mChannels; + + public NgnProxyAudioProducer(BigInteger id, ProxyAudioProducer producer) { + super(id, producer); + mProducer = producer; + mCallback = new MyProxyAudioProducerCallback(this); + mProducer.setCallback(mCallback); + mOnMute = false; + mHasBuiltInAEC = false; + } + + public void setOnPause(boolean pause) { + if (super.mPaused == pause) { + return; + } + try { + if (this.mStarted) { + + } + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + + super.mPaused = pause; + } + + public void setOnMute(boolean mute) { + Log.d(TAG, "===== Audio Recorder " + (mute ? "Mute" : "unMute")); + + mOnMute = mute; + } + + public boolean isOnMute() { + return mOnMute; + } + + public void setSpeakerphoneOn(boolean speakerOn) { + Log.d(TAG, "setSpeakerphoneOn(" + speakerOn + ")"); + if (NgnApplication.isAudioRecreateRequired()) { + if (super.mPrepared) { + mRoutingChanged = true; + } + } + } + + public void toggleSpeakerphone() { + setSpeakerphoneOn(!NgnApplication.getAudioManager().isSpeakerphoneOn()); + } + + public boolean isSpeakerOn() { + return NgnApplication.getAudioManager().isSpeakerphoneOn(); + } + + public boolean onVolumeChanged(boolean bDown) { + return true; + } + + private int prepareCallback(int ptime, int rate, int channels) { + Log.d(NgnProxyAudioProducer.TAG, "prepareCallback(" + ptime + "," + + rate + "," + channels + ")"); + return prepare(ptime, rate, channels); + } + + private int startCallback() { + Log.d(NgnProxyAudioProducer.TAG, "startCallback"); + if (mPrepared) { +// if (mPrepared && mAudioRecord != null) { + super.mStarted = true; + mProducerThread = new Thread(mRunnableRecorder, + "AudioProducerThread"); + //mProducerThread.setPriority(Thread.MAX_PRIORITY); + mProducerThread.start(); + return 0; + } + return -1; + } + + /** + * Function called when the native producer (C++) is ready to send data (every @b ptime milliseconds). It's up to you to fill the data. + * This function is only called if you register a buffer using @ref setPushBuffer(pPushBufferPtr, nPushBufferSize, bUsePushCallback) with @b bUsePushCallback equal to @b true + */ + private int fillPushBuffer() { + // sample code + // for performance reasons, 'is' and 'buff' must be created once + // up to you to manage the offset index (circle buffer) + // InputStream is = getContext().getAssets().open("audio.wav"); + // byte buff[] = new byte[(int)nPushBufferSize]; // for performance reasons, create once + // is.read(buff, offset, buff.length); + // mAudioFrame.put(buff); + // pmAudioFrame.rewind(); + // is.close(); + Log.d(TAG, "fillPushBuffer"); + return 0; + } + + private int pauseCallback() { + Log.d(NgnProxyAudioProducer.TAG, "pauseCallback"); + setOnPause(true); + return 0; + } + + private int stopCallback() { + Log.d(NgnProxyAudioProducer.TAG, "stopCallback"); + super.mStarted = false; + if (mProducerThread != null) { + try { + mProducerThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mProducerThread = null; + } + return 0; + } + + private synchronized int prepare(int ptime, int rate, int channels) { + int bytesNseq = 0; + if (super.mPrepared) { + Log.e(TAG, "already prepared"); + return -1; + } + Log.d(TAG, "prepare(" + ptime + "," + rate + "," + channels); + + // Use 44100hz for Hovis_Box_V1 + if (NgnApplication.isHovis()) { + rate = 44100; + mProducer.setActualSndCardRecordParams(ptime, rate, channels); + } + + final boolean aecEnabled = NgnEngine.getInstance() + .getConfigurationService().getBoolean( + NgnConfigurationEntry.GENERAL_AEC, + NgnConfigurationEntry.DEFAULT_GENERAL_AEC); + + final int minBufferSize = AudioRecord.getMinBufferSize(rate, + AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); + final int shortsPerNotif = (rate * ptime) / 1000; + // AEC won't work if there is too much delay + // Too short bufferSize will produce BufferOverflow errors but we don't + // have choice if we want AEC + final float bufferFactor = aecEnabled ? NgnProxyAudioProducer.AUDIO_BUFFER_FACTOR + : NgnProxyAudioProducer.AUDIO_BUFFER_FACTOR; + final int bufferSize = Math.max( + (int) ((float) minBufferSize * bufferFactor), + shortsPerNotif << 1); + mAudioFrame = ByteBuffer.allocateDirect(((shortsPerNotif << 1) + bytesNseq) * 10); + mPtime = ptime; + mRate = rate; + mChannels = channels; + Log.d(TAG, "Configure aecEnabled:" + aecEnabled); + int audioSrc = MediaRecorder.AudioSource.MIC; + + if (aecEnabled) { + //audioSrc = MediaRecorder.AudioSource.VOICE_RECOGNITION; + // Do not use built-in AEC + /* + * if(NgnApplication.getSDKVersion() >= 11){ try { final Field f = + * MediaRecorder + * .AudioSource.class.getDeclaredField("VOICE_COMMUNICATION"); + * audioSrc = f.getInt(null); mHasBuiltInAEC = true; } catch + * (Exception e) { e.printStackTrace(); } } + */ + } + + // Use CAMCORDER audio source for Hovis_Box_V1 + if (NgnApplication.isHovis()) { + audioSrc = MediaRecorder.AudioSource.CAMCORDER; + } + +// mAudioRecord = new AudioRecord(audioSrc, rate, +// AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, +// bufferSize); + +// if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) { + super.mPrepared = true; + return 0; +// } else { +// Log.e(TAG, "prepare(" + mAudioRecord.getState() + ") failed"); +// super.mPrepared = false; +// return -1; +// } + } + + private synchronized void unprepare() { +// if (mAudioRecord != null) { +// synchronized (mAudioRecord) { +// if (super.mPrepared) { // only call stop() is the AudioRecord is +// // in initialized state +// mAudioRecord.stop(); +// } +// mAudioRecord.release(); +// mAudioRecord = null; +// } +// } + super.mPrepared = false; + } + + private final ArrayList pendingSends = new ArrayList<>(); + + private Runnable mRunnableRecorder = new Runnable() { + @Override + public void run() { + NgnApplication.getContext().registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (ACTION_ADD_SEND.equals(intent.getAction())) { + byte[] buf = intent.getByteArrayExtra(EXTRA_DATA); + if (buf != null) { + synchronized (pendingSends) { + pendingSends.add(buf); + } + } + } + } + }, new IntentFilter(ACTION_ADD_SEND)); + + + Log.d(TAG, "===== Audio Recorder (Start) ===== "); + android.os.Process + .setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); + + int bytesNseq = 0; + long curretTime = 0; + +// mAudioRecord.startRecording(); + final int nSize = mAudioFrame.capacity() - bytesNseq; + byte silenceBuffer[] = new byte[nSize]; + int nRead; + + if (NgnProxyAudioProducer.super.mValid) { + mProducer.setPushBuffer(mAudioFrame, mAudioFrame.capacity(), false); + mProducer + .setGain(NgnEngine + .getInstance() + .getConfigurationService() + .getInt( + NgnConfigurationEntry.MEDIA_AUDIO_PRODUCER_GAIN, + NgnConfigurationEntry.DEFAULT_MEDIA_AUDIO_PRODUCER_GAIN)); + } + // disable Doubango AEC + if (mHasBuiltInAEC) { + final NgnAVSession ngnAVSession = NgnAVSession + .getSession(getSipSessionId()); + if (ngnAVSession != null) { + ngnAVSession.setAECEnabled(false); + } + } + + while (NgnProxyAudioProducer.super.mValid && mStarted) { +// if (mAudioRecord == null) { +// break; +// } + if (mRoutingChanged) { + Log.d(TAG, "Routing changed: restart() recorder"); + mRoutingChanged = false; + unprepare(); + if (prepare(mPtime, mRate, mChannels) != 0) { + break; + } +// if (!NgnProxyAudioProducer.super.mPaused) { +// mAudioRecord.startRecording(); +// } + } + + // To avoid overrun read data even if on pause/mute we have to + // read + // TODO: read from application and push it here. + byte[] toSend = null; + synchronized (pendingSends) { + if (!pendingSends.isEmpty()) { + toSend = pendingSends.remove(0); + } + } + if (toSend == null) { + try { + Thread.sleep(5); + } catch (InterruptedException e) { + e.printStackTrace(); + } + continue; + } + mAudioFrame.put(toSend); + mAudioFrame.rewind(); + mProducer.push(mAudioFrame, toSend.length); +// if ((nRead = mAudioRecord.read(mAudioFrame, nSize)) > 0) { +// if (!NgnProxyAudioProducer.super.mPaused) { +// if (mOnMute) { // workaround because Android's +// // SetMicrophoneOnMute() is buggy +// mAudioFrame.put(silenceBuffer); +// mAudioFrame.rewind(); +// } else { +// if (nRead != nSize) { +// mProducer.push(mAudioFrame, nRead); +// Log.w(TAG, "BufferOverflow?"); +// } else { +//// if (((xxx++) / 20) % 2 == 0) +// mProducer.push(); +// } +// } +// } +// } +// System.out.printf("%d, nRead=%d, mPaused=%b, onMute=%b%n", System.currentTimeMillis(), nRead, NgnProxyAudioProducer.super.mPaused, mOnMute); + /*int state = mAudioRecord.getRecordingState(); if (state == AudioRecord.RECORDSTATE_STOPPED) { Log.d(TAG, "===== RECORDSTATE_STOPPED ===== "); }*/ - } - - unprepare(); - - Log.d(TAG, "===== Audio Recorder (Stop) ===== "); - } - }; - - static class MyProxyAudioProducerCallback extends - ProxyAudioProducerCallback { - final NgnProxyAudioProducer myProducer; - - public MyProxyAudioProducerCallback(NgnProxyAudioProducer producer) { - super(); - myProducer = producer; - } - - @Override - public int prepare(int ptime, int rate, int channels) { - return myProducer.prepareCallback(ptime, rate, channels); - } - - @Override - public int start() { - return myProducer.startCallback(); - } - - @Override - public int fillPushBuffer() { - return myProducer.fillPushBuffer(); - } - - @Override - public int pause() { - return myProducer.pauseCallback(); - } - - @Override - public int stop() { - return myProducer.stopCallback(); - } - } + } + + unprepare(); + + Log.d(TAG, "===== Audio Recorder (Stop) ===== "); + } + }; + + static class MyProxyAudioProducerCallback extends + ProxyAudioProducerCallback { + final NgnProxyAudioProducer myProducer; + + public MyProxyAudioProducerCallback(NgnProxyAudioProducer producer) { + super(); + myProducer = producer; + } + + @Override + public int prepare(int ptime, int rate, int channels) { + return myProducer.prepareCallback(ptime, rate, channels); + } + + @Override + public int start() { + return myProducer.startCallback(); + } + + @Override + public int fillPushBuffer() { + return myProducer.fillPushBuffer(); + } + + @Override + public int pause() { + return myProducer.pauseCallback(); + } + + @Override + public int stop() { + return myProducer.stopCallback(); + } + } } diff --git a/app/build.gradle b/app/build.gradle index 75aef01571291e2666ee48f80193480d3f244d03..9244ba4121f9e0afe468522e3f66e0c7755476f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "org.mcopenplatform.muoapi" - minSdkVersion 17 + minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "0.1" @@ -17,18 +17,18 @@ android { } buildTypes { release { - buildConfigField "boolean", "LOG_SHOW", "false" + buildConfigField "boolean", "LOG_SHOW", "false" minifyEnabled false - minifyEnabled true + minifyEnabled true shrinkResources true zipAlignEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' flavorDimensions "default" } debug { - buildConfigField "boolean", "LOG_SHOW", "true" + buildConfigField "boolean", "LOG_SHOW", "true" + minifyEnabled false minifyEnabled false - minifyEnabled false shrinkResources false zipAlignEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' @@ -70,7 +70,6 @@ android { } - dependencies { implementation project(':android-ngn-stack') api fileTree(include: ['*.jar'], dir: 'libs') @@ -82,6 +81,8 @@ dependencies { api 'com.android.support:support-v4:' + rootProject.supportLibVersion api 'com.android.support:recyclerview-v7:' + rootProject.supportLibVersion // Required -- JUnit 4 framework + implementation 'com.android.support:support-v4:28.0.0' + implementation 'android.arch.lifecycle:extensions:1.1.1' testImplementation 'junit:junit:4.12' // Optional -- Mockito framework testImplementation 'org.mockito:mockito-core:2.7.22' diff --git a/app/src/main/java/org/mcopenplatform/muoapi/mcopsdk/MainActivity.java b/app/src/main/java/org/mcopenplatform/muoapi/mcopsdk/MainActivity.java index df74746e7dbdff42f00af239500debe044f3e8a1..96ca4b51434c3c4aeae8b6aad509f560f006fd43 100644 --- a/app/src/main/java/org/mcopenplatform/muoapi/mcopsdk/MainActivity.java +++ b/app/src/main/java/org/mcopenplatform/muoapi/mcopsdk/MainActivity.java @@ -49,11 +49,9 @@ import org.mcopenplatform.muoapi.ConstantsMCOP; import org.mcopenplatform.muoapi.IMCOPCallback; import org.mcopenplatform.muoapi.IMCOPsdk; import org.mcopenplatform.muoapi.R; -import org.mcopenplatform.muoapi.mcopsdk.datatype.Session; import org.mcopenplatform.muoapi.mcopsdk.datatype.UserData; import org.mcopenplatform.muoapi.mcopsdk.preference.PreferencesManager; import org.mcopenplatform.muoapi.mcopsdk.preference.PreferencesManagerDefault; -import org.mcopenplatform.muoapi.utils.Utils; import java.net.InterfaceAddress; import java.net.URI; @@ -79,7 +77,7 @@ public class MainActivity extends AppCompatActivity { private static final boolean VALUE_BOOLEAN_DEFAULT = false; private static UserData userData; private static final String PARAMETER_PROFILE = "parameters"; - private static final String PARAMETER_SAVE_PROFILE = TAG+".PARAMETER_SAVE_PROFILE"; + private static final String PARAMETER_SAVE_PROFILE = TAG + ".PARAMETER_SAVE_PROFILE"; private String[] currentProfile; private PreferencesManager preferencesManager; @@ -108,195 +106,266 @@ public class MainActivity extends AppCompatActivity { private DialogMenu mDialogShowAdvanceFunction; - private Map getProfilesParameters(List parameters){ - Map parametersMap=new HashMap<>(); - if(parameters!=null && !parameters.isEmpty()){ - Log.i(TAG,"External Parameters"); - }else{ - Log.i(TAG,"No External Parameters"); - parameters=loadParameters(); + private Map getProfilesParameters(List parameters) { + Map parametersMap = new HashMap<>(); + if (parameters != null && !parameters.isEmpty()) { + Log.i(TAG, "External Parameters"); + } else { + Log.i(TAG, "No External Parameters"); + parameters = loadParameters(); } - if(parameters!=null && !parameters.isEmpty()) - for (String parameter:parameters){ - Log.i(TAG,"Parameter: "+parameter); - String[] parametersSplit=parameter.split(":"); - if(parametersSplit!=null) - if(parametersSplit.length==2){ - parametersMap.put(parametersSplit[0],new String[]{parametersSplit[1]}); - }else if(parametersSplit.length==4){ - parametersMap.put(parametersSplit[0],new String[]{parametersSplit[1],parametersSplit[2],parametersSplit[3]}); - }else{ - Log.e(TAG,"Error in parse parameter"); + if (parameters != null && !parameters.isEmpty()) + for (String parameter : parameters) { + Log.i(TAG, "Parameter: " + parameter); + String[] parametersSplit = parameter.split(":"); + if (parametersSplit != null) + if (parametersSplit.length == 2) { + parametersMap.put(parametersSplit[0], new String[]{parametersSplit[1]}); + } else if (parametersSplit.length == 4) { + parametersMap.put(parametersSplit[0], new String[]{parametersSplit[1], parametersSplit[2], parametersSplit[3]}); + } else { + Log.e(TAG, "Error in parse parameter"); + } } - } - if(parametersMap!=null && !parametersMap.isEmpty()){ + if (parametersMap != null && !parametersMap.isEmpty()) { saveParameters(parameters); } return parametersMap; } - private boolean saveParameters(List parameters){ - if(preferencesManager!=null){ - return preferencesManager.putStringSet(this,PARAMETER_SAVE_PROFILE,new HashSet(parameters)); + private boolean saveParameters(List parameters) { + if (preferencesManager != null) { + return preferencesManager.putStringSet(this, PARAMETER_SAVE_PROFILE, new HashSet(parameters)); } return false; } - private ArrayList loadParameters(){ - if(preferencesManager!=null){ - Set stringSet=preferencesManager.getStringSet(this,PARAMETER_SAVE_PROFILE); - if(stringSet!=null){ + private ArrayList loadParameters() { + if (preferencesManager != null) { + Set stringSet = preferencesManager.getStringSet(this, PARAMETER_SAVE_PROFILE); + if (stringSet != null) { return (new ArrayList(stringSet)); } } return null; } + public void closeFragment() { + findViewById(R.id.mainActivity_Container_patch).setVisibility(View.INVISIBLE); + } + + // true: request, false: release + public void requestFloor(boolean request) { + showIdsOperationFloorControl(this, request); + } + + public void makeCall(boolean group, String name) { + try { + int typeCalls = -1; + if (group) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue(); + } else { // private + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue(); + } + if (typeCalls > 0 && mService != null) + mService.makeCall(name, typeCalls); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + + public void hangup(String name) { + if (userData.getSessionIDs() == null) return; + final String[] strings = userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); + + if (strings == null || strings.length == 0) return; + if (strings.length == 1) { + try { + if (mService != null) + mService.hangUpCall(strings[0]); + } catch (RemoteException e) { + e.printStackTrace(); + } + } else { + // hope we are not here. + mDialogIds = DialogMenu.newInstance(strings, null); + mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { + @Override + public void onClickItem(int item) { + if (item >= 0 && strings.length > item) { + try { + if (mService != null) + mService.hangUpCall(strings[item]); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + } + }); + mDialogIds.show(getSupportFragmentManager(), "SimpleDialog"); + } + } + @Override protected void onCreate(Bundle savedInstanceState) { - if(BuildConfig.DEBUG)Log.i(TAG,"onCreate"); + if (BuildConfig.DEBUG) Log.i(TAG, "onCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); setPermissions(); - preferencesManager=new PreferencesManagerDefault(); - isSpeakerphoneOn=false; + preferencesManager = new PreferencesManagerDefault(); + isSpeakerphoneOn = false; clients = new TreeMap<>(); - if(clients==null || clients.isEmpty()){ - clients.put("TESTA", new String[]{"TESTA","TESTA","TESTA"}); - clients.put("TESTB", new String[]{"TESTB","TESTB","TESTB"}); - clients.put("TESTC", new String[]{"TESTC","TESTC","TESTC"}); - clients.put("TESTD", new String[]{"TESTD","TESTD","TESTD"}); - clients.put("TESTE", new String[]{"TESTE","TESTE","TESTE"}); + if (clients == null || clients.isEmpty()) { + clients.put("TESTA", new String[]{"TESTA", "TESTA", "TESTA"}); + clients.put("TESTB", new String[]{"TESTB", "TESTB", "TESTB"}); + clients.put("TESTC", new String[]{"TESTC", "TESTC", "TESTC"}); + clients.put("TESTD", new String[]{"TESTD", "TESTD", "TESTD"}); + clients.put("TESTE", new String[]{"TESTE", "TESTE", "TESTE"}); } - ArrayList strings=getIntent().getStringArrayListExtra(PARAMETER_PROFILE); - Map parameterClients= getProfilesParameters(strings); - if(parameterClients!=null && !parameterClients.isEmpty()) - clients=parameterClients; - - - - mainActivity_Button_Register=(Button)findViewById(R.id.mainActivity_Button_Register); - - mainActivity_Button_deRegister=(Button)findViewById(R.id.mainActivity_Button_deRegister); - mainActivity_TextView_info=(TextView)findViewById(R.id.mainActivity_TextView_info); - mainActivity_TextView_error=(TextView)findViewById(R.id.mainActivity_TextView_error); - mainActivity_TextView_affiliation=(TextView)findViewById(R.id.mainActivity_TextView_affiliation); - mainActivity_Button_affiliation=(Button)findViewById(R.id.mainActivity_Button_affiliation); - mainActivity_Button_unaffiliation=(Button)findViewById(R.id.mainActivity_Button_unaffiliation); - mainActivity_EditText_affiliation=(EditText)findViewById(R.id.mainActivity_EditText_affiliation); - mainActivity_Button_make_call=(Button)findViewById(R.id.mainActivity_Button_make_call); - mainActivity_Button_Hang_up_call=(Button)findViewById(R.id.mainActivity_Button_Hang_up_call); - mainActivity_Button_accept_call=(Button)findViewById(R.id.mainActivity_Button_accept_call); - mainActivity_Button_Release_token=(Button)findViewById(R.id.mainActivity_Button_Release_token); - mainActivity_Button_Request_token=(Button)findViewById(R.id.mainActivity_Button_Request_token); - mainActivity_Button_Speaker=(Button)findViewById(R.id.mainActivity_Button_Speaker); - mainActivity_Button_Advanced_Functions=(Button)findViewById(R.id.mainActivity_Button_Advanced_Functions); - if(userData==null); - userData=new UserData(); - - mMCOPCallback=new IMCOPCallback.Stub() { + ArrayList strings = getIntent().getStringArrayListExtra(PARAMETER_PROFILE); + Map parameterClients = getProfilesParameters(strings); + if (parameterClients != null && !parameterClients.isEmpty()) + clients = parameterClients; + + + Button btn = findViewById(R.id.mainActivity_Button_patch); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + findViewById(R.id.mainActivity_Container_patch).setVisibility(View.VISIBLE); + } + }); + + mainActivity_Button_Register = (Button) findViewById(R.id.mainActivity_Button_Register); + + mainActivity_Button_deRegister = (Button) findViewById(R.id.mainActivity_Button_deRegister); + mainActivity_TextView_info = (TextView) findViewById(R.id.mainActivity_TextView_info); + mainActivity_TextView_error = (TextView) findViewById(R.id.mainActivity_TextView_error); + mainActivity_TextView_affiliation = (TextView) findViewById(R.id.mainActivity_TextView_affiliation); + mainActivity_Button_affiliation = (Button) findViewById(R.id.mainActivity_Button_affiliation); + mainActivity_Button_unaffiliation = (Button) findViewById(R.id.mainActivity_Button_unaffiliation); + mainActivity_EditText_affiliation = (EditText) findViewById(R.id.mainActivity_EditText_affiliation); + mainActivity_Button_make_call = (Button) findViewById(R.id.mainActivity_Button_make_call); + mainActivity_Button_Hang_up_call = (Button) findViewById(R.id.mainActivity_Button_Hang_up_call); + mainActivity_Button_accept_call = (Button) findViewById(R.id.mainActivity_Button_accept_call); + mainActivity_Button_Release_token = (Button) findViewById(R.id.mainActivity_Button_Release_token); + mainActivity_Button_Request_token = (Button) findViewById(R.id.mainActivity_Button_Request_token); + mainActivity_Button_Speaker = (Button) findViewById(R.id.mainActivity_Button_Speaker); + mainActivity_Button_Advanced_Functions = (Button) findViewById(R.id.mainActivity_Button_Advanced_Functions); + if (userData == null) ; + userData = new UserData(); + + mMCOPCallback = new IMCOPCallback.Stub() { @Override public void handleOnEvent(final List actionList) throws RemoteException { runOnUiThread(new Runnable() { @Override public void run() { - if(BuildConfig.DEBUG)Log.i(TAG,"Receive event"); - for(Intent action:actionList){ - int codeError=-1; - int eventTypeInt=-1; - String stringError=null; - String sessionID=null; - if(action!=null && action.getAction()!=null && !action.getAction().trim().isEmpty()) + if (BuildConfig.DEBUG) Log.i(TAG, "Receive event"); + for (Intent action : actionList) { + int codeError = -1; + int eventTypeInt = -1; + String stringError = null; + String sessionID = null; + if (action != null && action.getAction() != null && !action.getAction().trim().isEmpty()) try { - switch (ConstantsMCOP.ActionsCallBack.fromString(action.getAction())){ + switch (ConstantsMCOP.ActionsCallBack.fromString(action.getAction())) { case none: - if(BuildConfig.DEBUG)Log.d(TAG,"none"); + if (BuildConfig.DEBUG) Log.d(TAG, "none"); break; case authorizationRequestEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"authorizationRequestEvent"); - codeError=-1; - if((codeError=action.getIntExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if (BuildConfig.DEBUG) + Log.d(TAG, "authorizationRequestEvent"); + codeError = -1; + if ((codeError = action.getIntExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //Error in authorizationRequestEvent - stringError=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_STRING); - showLastError("authorizationRequestEvent",codeError,stringError); - }else { + stringError = action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.ERROR_STRING); + showLastError("authorizationRequestEvent", codeError, stringError); + } else { //No error - String requestUri=null; - String redirect=null; - if((requestUri=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REQUEST_URI))!=null && - (redirect=action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REDIRECT_URI))!=null - ){ - if(BuildConfig.DEBUG)Log.d(TAG,"onAuthentication URI: "+requestUri+ " redirectionURI: "+redirect); + String requestUri = null; + String redirect = null; + if ((requestUri = action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REQUEST_URI)) != null && + (redirect = action.getStringExtra(ConstantsMCOP.AuthorizationRequestExtras.REDIRECT_URI)) != null + ) { + if (BuildConfig.DEBUG) + Log.d(TAG, "onAuthentication URI: " + requestUri + " redirectionURI: " + redirect); Intent intent2 = new Intent(getApplicationContext(), ScreenAutheticationWebView.class); - intent2.putExtra(ScreenAutheticationWebView.DATA_URI_INTENT,requestUri.trim()); - intent2.putExtra(ScreenAutheticationWebView.DATA_REDIRECTION_URI,redirect.trim()); + intent2.putExtra(ScreenAutheticationWebView.DATA_URI_INTENT, requestUri.trim()); + intent2.putExtra(ScreenAutheticationWebView.DATA_REDIRECTION_URI, redirect.trim()); //Test //For testing purposes only - if(currentProfile!=null && currentProfile.length>=3){ - intent2.putExtra(ScreenAutheticationWebView.DATA_USER,currentProfile[1]); - intent2.putExtra(ScreenAutheticationWebView.DATA_PASS,currentProfile[2]); + if (currentProfile != null && currentProfile.length >= 3) { + intent2.putExtra(ScreenAutheticationWebView.DATA_USER, currentProfile[1]); + intent2.putExtra(ScreenAutheticationWebView.DATA_PASS, currentProfile[2]); } - startActivityForResult(intent2,AUTHETICATION_RESULT); + startActivityForResult(intent2, AUTHETICATION_RESULT); } } break; case loginEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"loginEvent"); - codeError=-1; - if((codeError=action.getIntExtra(ConstantsMCOP.LoginEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if (BuildConfig.DEBUG) Log.d(TAG, "loginEvent"); + codeError = -1; + if ((codeError = action.getIntExtra(ConstantsMCOP.LoginEventExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //LoginEvent Error - stringError=action.getStringExtra(ConstantsMCOP.LoginEventExtras.ERROR_STRING); - showLastError("LoginEvent",codeError,stringError); - }else { + stringError = action.getStringExtra(ConstantsMCOP.LoginEventExtras.ERROR_STRING); + showLastError("LoginEvent", codeError, stringError); + } else { //No Error - boolean success=false; - String mcptt_id=null; - String displayName=null; - if((success=action.getBooleanExtra(ConstantsMCOP.LoginEventExtras.SUCCESS,VALUE_BOOLEAN_DEFAULT))==true && - (mcptt_id=action.getStringExtra(ConstantsMCOP.LoginEventExtras.MCPTT_ID))!=null){ - if(BuildConfig.DEBUG)Log.d(TAG,"Successful Login: "+success+ " mcptt_id: "+mcptt_id); - displayName=action.getStringExtra(ConstantsMCOP.LoginEventExtras.DISPLAY_NAME); - - isRegisted(success,mcptt_id,displayName); - }else{ - Log.e(TAG,"Registration Error"); + boolean success = false; + String mcptt_id = null; + String displayName = null; + if ((success = action.getBooleanExtra(ConstantsMCOP.LoginEventExtras.SUCCESS, VALUE_BOOLEAN_DEFAULT)) == true && + (mcptt_id = action.getStringExtra(ConstantsMCOP.LoginEventExtras.MCPTT_ID)) != null) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Successful Login: " + success + " mcptt_id: " + mcptt_id); + displayName = action.getStringExtra(ConstantsMCOP.LoginEventExtras.DISPLAY_NAME); + + isRegisted(success, mcptt_id, displayName); + } else { + Log.e(TAG, "Registration Error"); } } break; case unLoginEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"unLoginEvent"); - codeError=-1; - if((codeError=action.getIntExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if (BuildConfig.DEBUG) Log.d(TAG, "unLoginEvent"); + codeError = -1; + if ((codeError = action.getIntExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //unLoginEvent Error - stringError=action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); - showLastError("unLoginEvent",codeError,stringError); - }else { + stringError = action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); + showLastError("unLoginEvent", codeError, stringError); + } else { //No Error - boolean success=false; - if((success=action.getBooleanExtra(ConstantsMCOP.UnLoginEventExtras.SUCCESS,VALUE_BOOLEAN_DEFAULT))==true){ + boolean success = false; + if ((success = action.getBooleanExtra(ConstantsMCOP.UnLoginEventExtras.SUCCESS, VALUE_BOOLEAN_DEFAULT)) == true) { unRegisted(success); - }else{ - Log.e(TAG,"Unregistration Error"); + } else { + Log.e(TAG, "Unregistration Error"); } } break; case configurationUpdateEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"configurationUpdateEvent"); + if (BuildConfig.DEBUG) + Log.d(TAG, "configurationUpdateEvent"); break; case callEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"callEvent"); - codeError=-1; - eventTypeInt=action.getIntExtra(ConstantsMCOP.CallEventExtras.EVENT_TYPE,ERROR_CODE_DEFAULT); - ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum eventTypeCall=null; + if (BuildConfig.DEBUG) Log.d(TAG, "callEvent"); + codeError = -1; + eventTypeInt = action.getIntExtra(ConstantsMCOP.CallEventExtras.EVENT_TYPE, ERROR_CODE_DEFAULT); + ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum eventTypeCall = null; - if(eventTypeInt!=ERROR_CODE_DEFAULT && - (eventTypeCall=ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum.fromInt(eventTypeInt))!=null ){ + if (eventTypeInt != ERROR_CODE_DEFAULT && + (eventTypeCall = ConstantsMCOP.CallEventExtras.CallEventEventTypeEnum.fromInt(eventTypeInt)) != null) { String callerID; String groupCallerID; int callType; @@ -304,107 +373,124 @@ public class MainActivity extends AppCompatActivity { case NONE: break; case INCOMING: - stringError=action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - callerID=action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_USERID); - groupCallerID=action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_GROUPID); - callType=action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE,ERROR_CODE_DEFAULT); - if(sessionID!=null)userData.addSessionID(sessionID); - showData("callEvent ("+sessionID+")","INCOMING"+" -> "+callerID+" "+(groupCallerID!=null?groupCallerID:null)+" callType:"+callType); + stringError = action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + callerID = action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_USERID); + groupCallerID = action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_GROUPID); + callType = action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE, ERROR_CODE_DEFAULT); + if (sessionID != null) + userData.addSessionID(sessionID); + showData("callEvent (" + sessionID + ")", "INCOMING" + " -> " + callerID + " " + (groupCallerID != null ? groupCallerID : null) + " callType:" + callType); break; case RINGING: - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - showData("callEvent ("+sessionID+")","RINGING"); - if(sessionID!=null)userData.addSessionID(sessionID); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + showData("callEvent (" + sessionID + ")", "RINGING"); + if (sessionID != null) + userData.addSessionID(sessionID); break; case INPROGRESS: - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - showData("callEvent ("+sessionID+")","INPROGRESS"); - if(sessionID!=null)userData.addSessionID(sessionID); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + showData("callEvent (" + sessionID + ")", "INPROGRESS"); + if (sessionID != null) + userData.addSessionID(sessionID); + sendBroadcast(new Intent("CALL_STATE_CHANGED").putExtra("STATE", "INPROGRESS")); break; case CONNECTED: - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - callerID=action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_USERID); - groupCallerID=action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_GROUPID); - callType=action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE,ERROR_CODE_DEFAULT); - if(sessionID!=null)userData.addSessionID(sessionID); - showData("callEvent ("+sessionID+")","CONNECTED"+" -> "+callerID+" "+(groupCallerID!=null?groupCallerID:null)+" callType:"+callType); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + callerID = action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_USERID); + groupCallerID = action.getStringExtra(ConstantsMCOP.CallEventExtras.CALLER_GROUPID); + callType = action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE, ERROR_CODE_DEFAULT); + if (sessionID != null) + userData.addSessionID(sessionID); + showData("callEvent (" + sessionID + ")", "CONNECTED" + " -> " + callerID + " " + (groupCallerID != null ? groupCallerID : null) + " callType:" + callType); + sendBroadcast(new Intent("CALL_STATE_CHANGED").putExtra("STATE", "CONNECTED") + .putExtra("ID", (groupCallerID == null || "(null)".equals(groupCallerID)) ? callerID : groupCallerID) + .putExtra("SESSION", sessionID)); + break; case TERMINATED: - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - showData("callEvent ("+sessionID+")","TERMINATED"); - if(sessionID!=null)userData.removeSessionID(sessionID); - + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + showData("callEvent (" + sessionID + ")", "TERMINATED"); + if (sessionID != null) + userData.removeSessionID(sessionID); + sendBroadcast(new Intent("CALL_STATE_CHANGED").putExtra("STATE", "TERMINATED")); break; case ERROR: - if((codeError=action.getIntExtra(ConstantsMCOP.CallEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if ((codeError = action.getIntExtra(ConstantsMCOP.CallEventExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //callEvent Error - stringError=action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - showLastError("callEvent ("+sessionID+")",codeError,stringError); + stringError = action.getStringExtra(ConstantsMCOP.CallEventExtras.ERROR_STRING); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + showLastError("callEvent (" + sessionID + ")", codeError, stringError); } - if(sessionID!=null)userData.addSessionID(sessionID); + if (sessionID != null) + userData.addSessionID(sessionID); break; case UPDATE: - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); - int updateCallType=action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE,ERROR_CODE_DEFAULT); - showData("callEvent ("+sessionID+")","UPDATE"+" -> CallType: "+updateCallType); - if(sessionID!=null)userData.addSessionID(sessionID); + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + int updateCallType = action.getIntExtra(ConstantsMCOP.CallEventExtras.CALL_TYPE, ERROR_CODE_DEFAULT); + showData("callEvent (" + sessionID + ")", "UPDATE" + " -> CallType: " + updateCallType); + if (sessionID != null) + userData.addSessionID(sessionID); break; default: - showLastError("callEvent: ",999,"INVALID RECEIVED EVENT"); + showLastError("callEvent: ", 999, "INVALID RECEIVED EVENT"); break; } - }else{ - showLastError("callEvent: ",999,"INVALID RECEIVED EVENT"); + } else { + showLastError("callEvent: ", 999, "INVALID RECEIVED EVENT"); } break; case floorControlEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"floorControlEvent"); - codeError=-1; - if((codeError=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if (BuildConfig.DEBUG) Log.d(TAG, "floorControlEvent"); + codeError = -1; + if ((codeError = action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //Error in unLoginEvent - sessionID=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.SESSION_ID); - stringError=action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); - showLastError("floorControlEvent("+sessionID+")",codeError,stringError); - }else { + sessionID = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.SESSION_ID); + stringError = action.getStringExtra(ConstantsMCOP.UnLoginEventExtras.ERROR_STRING); + showLastError("floorControlEvent(" + sessionID + ")", codeError, stringError); + } else { //No Error - boolean success=false; - String eventFloorControl=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.FLOOR_CONTROL_EVENT); - String causeString=null; - int causeInt=-1; - try{ - sessionID=action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); + boolean success = false; + String eventFloorControl = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.FLOOR_CONTROL_EVENT); + String causeString = null; + int causeInt = -1; + try { + sessionID = action.getStringExtra(ConstantsMCOP.CallEventExtras.SESSION_ID); switch (ConstantsMCOP.FloorControlEventExtras.FloorControlEventTypeEnum.fromString(eventFloorControl)) { case none: break; case granted: - int durationGranted=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.DURATION_TOKEN,ERROR_CODE_DEFAULT); - Log.d(TAG,"floorControl ("+sessionID+") granted"); - showData("floorControl ("+sessionID+")","granted -> Duration: "+durationGranted); + int durationGranted = action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.DURATION_TOKEN, ERROR_CODE_DEFAULT); + Log.d(TAG, "floorControl (" + sessionID + ") granted"); + showData("floorControl (" + sessionID + ")", "granted -> Duration: " + durationGranted); + sendBroadcast(new Intent("FLOOR_STATE_CHANGED").putExtra("STATE", "GRANTED")); break; case idle: - Log.d(TAG,"floorControl ("+sessionID+") idle"); - showData("floorControl ("+sessionID+")","idle"); + Log.d(TAG, "floorControl (" + sessionID + ") idle"); + showData("floorControl (" + sessionID + ")", "idle"); + sendBroadcast(new Intent("FLOOR_STATE_CHANGED").putExtra("STATE", "IDLE")); break; case taken: - String userIDTaken=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.USER_ID); - String displayNameTaken=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.DISPLAY_NAME); - boolean allow_request=action.getBooleanExtra(ConstantsMCOP.FloorControlEventExtras.ALLOW_REQUEST,VALUE_BOOLEAN_DEFAULT); - Log.d(TAG,"floorControl ("+sessionID+") taken"); - showData("floorControl ("+sessionID+")","taken -> userIDTaken(allowRequest="+allow_request+"):("+userIDTaken+":"+displayNameTaken+")"); + String userIDTaken = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.USER_ID); + String displayNameTaken = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.DISPLAY_NAME); + boolean allow_request = action.getBooleanExtra(ConstantsMCOP.FloorControlEventExtras.ALLOW_REQUEST, VALUE_BOOLEAN_DEFAULT); + Log.d(TAG, "floorControl (" + sessionID + ") taken"); + showData("floorControl (" + sessionID + ")", "taken -> userIDTaken(allowRequest=" + allow_request + "):(" + userIDTaken + ":" + displayNameTaken + ")"); + sendBroadcast(new Intent("FLOOR_STATE_CHANGED").putExtra("STATE", "TAKEN").putExtra("ID", userIDTaken)); break; case denied: - causeString=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); - causeInt=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE,ERROR_CODE_DEFAULT); - Log.d(TAG,"floorControl ("+sessionID+") denied"); - showData("floorControl ("+sessionID+")","denied -> cause("+causeInt+":"+causeString+")"); + causeString = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); + causeInt = action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE, ERROR_CODE_DEFAULT); + Log.d(TAG, "floorControl (" + sessionID + ") denied"); + showData("floorControl (" + sessionID + ")", "denied -> cause(" + causeInt + ":" + causeString + ")"); + sendBroadcast(new Intent("FLOOR_STATE_CHANGED").putExtra("STATE", "DENIED")); break; case revoked: - causeString=action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); - causeInt=action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE,ERROR_CODE_DEFAULT); - Log.d(TAG,"floorControl ("+sessionID+") revoked"); - showData("floorControl ("+sessionID+")","revoked ->cause("+causeInt+":"+causeString+")"); + causeString = action.getStringExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_STRING); + causeInt = action.getIntExtra(ConstantsMCOP.FloorControlEventExtras.CAUSE_CODE, ERROR_CODE_DEFAULT); + Log.d(TAG, "floorControl (" + sessionID + ") revoked"); + showData("floorControl (" + sessionID + ")", "revoked ->cause(" + causeInt + ":" + causeString + ")"); + sendBroadcast(new Intent("FLOOR_STATE_CHANGED").putExtra("STATE", "REVOKED")); break; case request_sent: break; @@ -436,139 +522,153 @@ public class MainActivity extends AppCompatActivity { case reception_end_response: break; } - }catch (Exception e){ + } catch (Exception e) { } } break; case groupInfoEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"groupInfoEvent"); - String groupID2=action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.GROUP_ID); - String displayName=action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.DISPLAY_NAME); - int maxDataSizeForSDS=action.getIntExtra(ConstantsMCOP.GroupInfoEventExtras.MAX_DATA_SIZE_FOR_SDS,ERROR_CODE_DEFAULT); - int maxDataSizeAutoRecv=action.getIntExtra(ConstantsMCOP.GroupInfoEventExtras.MAX_DATA_SIZE_AUTO_RECV,ERROR_CODE_DEFAULT); - String activeRealTimeVideoMode=action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.ACTIVE_REAL_TIME_VIDEO_MODE); - ArrayList participantsList=null; - ArrayList participantsListDisplayName=null; - ArrayList participantsListType=null; - try{ - participantsList= action.getStringArrayListExtra(ConstantsMCOP.GroupInfoEventExtras.PARTICIPANTS_LIST); - Log.d(TAG,"ParticipantsList: "+participantsList.size()); - }catch (Exception e){ - Log.e(TAG,"Error in participants info"); + if (BuildConfig.DEBUG) Log.d(TAG, "groupInfoEvent"); + String groupID2 = action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.GROUP_ID); + String displayName = action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.DISPLAY_NAME); + int maxDataSizeForSDS = action.getIntExtra(ConstantsMCOP.GroupInfoEventExtras.MAX_DATA_SIZE_FOR_SDS, ERROR_CODE_DEFAULT); + int maxDataSizeAutoRecv = action.getIntExtra(ConstantsMCOP.GroupInfoEventExtras.MAX_DATA_SIZE_AUTO_RECV, ERROR_CODE_DEFAULT); + String activeRealTimeVideoMode = action.getStringExtra(ConstantsMCOP.GroupInfoEventExtras.ACTIVE_REAL_TIME_VIDEO_MODE); + ArrayList participantsList = null; + ArrayList participantsListDisplayName = null; + ArrayList participantsListType = null; + try { + participantsList = action.getStringArrayListExtra(ConstantsMCOP.GroupInfoEventExtras.PARTICIPANTS_LIST); + Log.d(TAG, "ParticipantsList: " + participantsList.size()); + } catch (Exception e) { + Log.e(TAG, "Error in participants info"); } - try{ - participantsListDisplayName= action.getStringArrayListExtra(ConstantsMCOP.GroupInfoEventExtras.PARTICIPANTS_LIST_DISPLAY_NAME); - Log.d(TAG,"ParticipantsList display name: "+participantsListDisplayName.size()); - }catch (Exception e){ - Log.e(TAG,"Error in participants info"); + try { + participantsListDisplayName = action.getStringArrayListExtra(ConstantsMCOP.GroupInfoEventExtras.PARTICIPANTS_LIST_DISPLAY_NAME); + Log.d(TAG, "ParticipantsList display name: " + participantsListDisplayName.size()); + } catch (Exception e) { + Log.e(TAG, "Error in participants info"); } - try{ - participantsListType= action.getStringArrayListExtra(ConstantsMCOP.GroupInfoEventExtras.PARTICIPANTS_LIST_TYPE); - Log.d(TAG,"ParticipantsList type: "+participantsListType.size()); - }catch (Exception e){ - Log.e(TAG,"Error in participants info"); - } - Log.d(TAG,"INFO Group ("+groupID2+" "+displayName+")"); - Log.d(TAG,"maxDataSizeForSDS:"+maxDataSizeForSDS+""); - Log.d(TAG,"maxDataSizeAutoRecv:"+maxDataSizeAutoRecv+""); - Log.d(TAG,"activeRealTimeVideoMode:"+activeRealTimeVideoMode+""); - Log.d(TAG,"Users:"); - if(participantsList.size()==participantsListDisplayName.size() && participantsList.size()==participantsListType.size()) - for(int con=0;con groups=(HashMap)action.getSerializableExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUPS_LIST); - if(groups!=null) + if (BuildConfig.DEBUG) + Log.d(TAG, "GROUP_AFFILIATION_UPDATE"); + Map groups = (HashMap) action.getSerializableExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUPS_LIST); + if (groups != null) showGroups(groups); break; case GROUP_AFFILIATION_ERROR: - if(BuildConfig.DEBUG)Log.d(TAG,"GROUP_AFFILIATION_ERROR"); - if((codeError=action.getIntExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_CODE,ERROR_CODE_DEFAULT))!=ERROR_CODE_DEFAULT){ + if (BuildConfig.DEBUG) + Log.d(TAG, "GROUP_AFFILIATION_ERROR"); + if ((codeError = action.getIntExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_CODE, ERROR_CODE_DEFAULT)) != ERROR_CODE_DEFAULT) { //Error in unLoginEvent - stringError=action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_STRING); - String groupID=action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUP_ID); - showLastError("groupAffiliationEvent ("+groupID+")",codeError,stringError); + stringError = action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.ERROR_STRING); + String groupID = action.getStringExtra(ConstantsMCOP.GroupAffiliationEventExtras.GROUP_ID); + showLastError("groupAffiliationEvent (" + groupID + ")", codeError, stringError); } break; case REMOTE_AFFILIATION: - if(BuildConfig.DEBUG)Log.d(TAG,"REMOTE_AFFILIATION"); + if (BuildConfig.DEBUG) + Log.d(TAG, "REMOTE_AFFILIATION"); //TODO: Receive Remote Affiliation break; default: - if(BuildConfig.DEBUG)Log.d(TAG,"groupAffiliationEvent type default"); - showLastError("groupAffiliationEvent: ",999,"INVALID RECEIVED EVENT"); + if (BuildConfig.DEBUG) + Log.d(TAG, "groupAffiliationEvent type default"); + showLastError("groupAffiliationEvent: ", 999, "INVALID RECEIVED EVENT"); break; } - }else{ - showLastError("groupAffiliationEvent: ",999,"INVALID RECEIVED EVENT"); + } else { + showLastError("groupAffiliationEvent: ", 999, "INVALID RECEIVED EVENT"); } break; case selectedContactChangeEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"selectedContactChangeEvent"); + if (BuildConfig.DEBUG) + Log.d(TAG, "selectedContactChangeEvent"); break; case eMBMSNotificationEvent: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent"); - codeError=-1; - eventTypeInt=action.getIntExtra(ConstantsMCOP.EMBMSNotificationEventExtras.EVENT_TYPE,ERROR_CODE_DEFAULT); - ConstantsMCOP.EMBMSNotificationEventExtras.EMBMSNotificationEventEventTypeEnum eventType=null; - if(eventTypeInt!=ERROR_CODE_DEFAULT && - (eventType=ConstantsMCOP.EMBMSNotificationEventExtras.EMBMSNotificationEventEventTypeEnum.fromInt(eventTypeInt))!=null ){ - if(BuildConfig.DEBUG)Log.d(TAG,"receive event "); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent"); + codeError = -1; + eventTypeInt = action.getIntExtra(ConstantsMCOP.EMBMSNotificationEventExtras.EVENT_TYPE, ERROR_CODE_DEFAULT); + ConstantsMCOP.EMBMSNotificationEventExtras.EMBMSNotificationEventEventTypeEnum eventType = null; + if (eventTypeInt != ERROR_CODE_DEFAULT && + (eventType = ConstantsMCOP.EMBMSNotificationEventExtras.EMBMSNotificationEventEventTypeEnum.fromInt(eventTypeInt)) != null) { + if (BuildConfig.DEBUG) Log.d(TAG, "receive event "); switch (eventType) { case none: break; case eMBMSAvailable: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent eMBMSAvailable"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent eMBMSAvailable"); mainActivity_TextView_error.setText("eMBMSNotificationEvent eMBMSAvailable"); break; case UndereMBMSCoverage: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent UndereMBMSCoverage"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent UndereMBMSCoverage"); mainActivity_TextView_error.setText("eMBMSNotificationEvent UndereMBMSCoverage"); break; case eMBMSBearerInUse: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent eMBMSBearerInUse"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent eMBMSBearerInUse"); mainActivity_TextView_error.setText("eMBMSNotificationEvent eMBMSBearerInUse"); break; case eMBMSBearerNotInUse: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent eMBMSBearerNotInUse"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent eMBMSBearerNotInUse"); mainActivity_TextView_error.setText("eMBMSNotificationEvent eMBMSBearerNotInUse"); break; case NoeMBMSCoverage: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent NoeMBMSCoverage"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent NoeMBMSCoverage"); mainActivity_TextView_error.setText("eMBMSNotificationEvent NoeMBMSCoverage"); break; case eMBMSNotAvailable: - if(BuildConfig.DEBUG)Log.d(TAG,"eMBMSNotificationEvent eMBMSNotAvailable"); + if (BuildConfig.DEBUG) + Log.d(TAG, "eMBMSNotificationEvent eMBMSNotAvailable"); mainActivity_TextView_error.setText("eMBMSNotificationEvent eMBMSNotAvailable"); break; } - }else{ - showLastError("eMBMSNotificationEvent: ",999,"INVALID RECEIVED EVENT"); + } else { + showLastError("eMBMSNotificationEvent: ", 999, "INVALID RECEIVED EVENT"); } break; default: - if(BuildConfig.DEBUG)Log.d(TAG,"Event type is not valid. "); + if (BuildConfig.DEBUG) + Log.d(TAG, "Event type is not valid. "); break; } - }catch (Exception ex){ - Log.e(TAG,"Event Action Error: "+action.getAction()+" error:"+ex.getMessage()); + } catch (Exception ex) { + Log.e(TAG, "Event Action Error: " + action.getAction() + " error:" + ex.getMessage()); } } } @@ -588,7 +688,7 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { try { - if(mService!=null) + if (mService != null) mService.unLoginMCOP(); } catch (RemoteException e) { e.printStackTrace(); @@ -600,7 +700,7 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { try { - if(mService!=null) + if (mService != null) mService.groupAffiliationOperation( mainActivity_EditText_affiliation.getText().toString().trim(), ConstantsMCOP.GroupAffiliationEventExtras.AffiliationOperationTypeEnum.Affiliate.getValue()); @@ -614,7 +714,7 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { try { - if(mService!=null) + if (mService != null) mService.groupAffiliationOperation( mainActivity_EditText_affiliation.getText().toString().trim(), ConstantsMCOP.GroupAffiliationEventExtras.AffiliationOperationTypeEnum.Deaffiliate.getValue()); @@ -648,14 +748,14 @@ public class MainActivity extends AppCompatActivity { mainActivity_Button_Release_token.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - showIdsOperationFloorControl(getApplicationContext(),false); + showIdsOperationFloorControl(getApplicationContext(), false); } }); mainActivity_Button_Request_token.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - showIdsOperationFloorControl(getApplicationContext(),true); + showIdsOperationFloorControl(getApplicationContext(), true); } }); @@ -663,18 +763,17 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { AudioManager mAudioManager; - mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - if(isSpeakerphoneOn){ - isSpeakerphoneOn=false; + mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + if (isSpeakerphoneOn) { + isSpeakerphoneOn = false; Log.d(TAG, "Speaker false"); mainActivity_Button_Speaker.setText("Speaker false"); - }else{ - isSpeakerphoneOn=true; + } else { + isSpeakerphoneOn = true; Log.d(TAG, "Speaker true"); mainActivity_Button_Speaker.setText("Speaker true"); } mAudioManager.setSpeakerphoneOn(isSpeakerphoneOn); - } }); @@ -682,32 +781,32 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View view) { showAdvanceFeatures(); - } + } }); - if(mConnection==null) - mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, IBinder service) { - Log.e(TAG,"Service Binded!\n"); - mService = IMCOPsdk.Stub.asInterface(service); - try { - mService.registerCallback(mMCOPCallback); - } catch (RemoteException e) { - e.printStackTrace(); + if (mConnection == null) + mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + Log.e(TAG, "Service Binded!\n"); + mService = IMCOPsdk.Stub.asInterface(service); + try { + mService.registerCallback(mMCOPCallback); + } catch (RemoteException e) { + e.printStackTrace(); + } + isConnect = true; } - isConnect=true; - } - @Override - public void onServiceDisconnected(ComponentName className) { - mService = null; - // This method is only invoked when the service quits from the other end or gets killed - // Invoking exit() from the AIDL interface makes the Service kill itself, thus invoking this. - Log.e(TAG,"Service Disconnected.\n"); - isConnect=false; - } - }; + @Override + public void onServiceDisconnected(ComponentName className) { + mService = null; + // This method is only invoked when the service quits from the other end or gets killed + // Invoking exit() from the AIDL interface makes the Service kill itself, thus invoking this. + Log.e(TAG, "Service Disconnected.\n"); + isConnect = false; + } + }; /* if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { // TODO: Consider calling @@ -738,20 +837,20 @@ public class MainActivity extends AppCompatActivity { connectService(null); } - private void showAdvanceFeatures(){ - final String[] strings={ + private void showAdvanceFeatures() { + + final String[] strings = { }; - mDialogShowAdvanceFunction = DialogMenu.newInstance(strings,null); + mDialogShowAdvanceFunction = DialogMenu.newInstance(strings, null); mDialogShowAdvanceFunction.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ + if (item >= 0 && strings.length > item) { - if(false){ + if (false) { - }else - { + } else { } } @@ -761,84 +860,85 @@ public class MainActivity extends AppCompatActivity { } - private void connectService(String client){ - if(!isConnect){ + private void connectService(String client) { + if (!isConnect) { serviceIntent = new Intent() .setComponent(new ComponentName( "org.mcopenplatform.muoapi", "org.mcopenplatform.muoapi.MCOPsdk")); - if(client==null){ - Log.i(TAG,"Current Profile: "+client); - serviceIntent.putExtra("PROFILE_SELECT",currentProfile!=null?currentProfile[0]:client); + if (client == null) { + Log.i(TAG, "Current Profile: " + client); + serviceIntent.putExtra("PROFILE_SELECT", currentProfile != null ? currentProfile[0] : client); } - try{ - ComponentName componentName=this.startService(serviceIntent); - if(componentName==null){ - Log.e(TAG,"Starting Error: "+componentName.getPackageName()); - }else if(serviceIntent==null){ - Log.e(TAG,"serviceIntent Error: "+componentName.getPackageName()); - }else if(mConnection==null){ - Log.e(TAG,"mConnection Error: "+componentName.getPackageName()); - }else{ + try { + ComponentName componentName = this.startService(serviceIntent); + if (componentName == null) { + Log.e(TAG, "Starting Error: " + componentName.getPackageName()); + } else if (serviceIntent == null) { + Log.e(TAG, "serviceIntent Error: " + componentName.getPackageName()); + } else if (mConnection == null) { + Log.e(TAG, "mConnection Error: " + componentName.getPackageName()); + } else { } - }catch (Exception e){ - if(BuildConfig.DEBUG)Log.w(TAG,"Error in start service: "+e.getMessage()); + } catch (Exception e) { + if (BuildConfig.DEBUG) Log.w(TAG, "Error in start service: " + e.getMessage()); } - Log.i(TAG,"Bind Service: "+bindService(serviceIntent, mConnection, BIND_AUTO_CREATE)); + Log.i(TAG, "Bind Service: " + bindService(serviceIntent, mConnection, BIND_AUTO_CREATE)); } } -/* - private void showOptionsProfiles(Map stringsList,final Context context){ - if(stringsList==null)return; - final ArrayList strings=new ArrayList<>(); - for(String[] value:stringsList.values()){ - if(value!=null && value.length>=1 && value[0]!=null){ - strings.add(value[0]); - }else{ - Log.e(TAG,"Error in process value"); - } - } - if(strings==null || strings.isEmpty())return; - mDialogMenu = DialogMenu.newInstance( strings.toArray(new String[strings.size()]),null); - mDialogMenu.setOnClickItemListener(new DialogMenu.OnClickListener() { - @Override - public void onClickItem(int item) { - if(item>=0 && strings.size()>item){ - Log.d(TAG,"Select Profile "+strings.get(item)); - //TODO: - connectService(strings.get(item)); + + /* + private void showOptionsProfiles(Map stringsList,final Context context){ + if(stringsList==null)return; + final ArrayList strings=new ArrayList<>(); + for(String[] value:stringsList.values()){ + if(value!=null && value.length>=1 && value[0]!=null){ + strings.add(value[0]); + }else{ + Log.e(TAG,"Error in process value"); } } - }); - mDialogMenu.show(getSupportFragmentManager(), "SimpleDialog"); - } -*/ - private void showTypeRegister(final Context context){ - final String[] strings={"With External authentication","No authentication"}; - if(strings==null || strings.length==0)return; - mDialogMenu=null; - mDialogMenu = DialogMenu.newInstance(strings,"Registration types"); + if(strings==null || strings.isEmpty())return; + mDialogMenu = DialogMenu.newInstance( strings.toArray(new String[strings.size()]),null); + mDialogMenu.setOnClickItemListener(new DialogMenu.OnClickListener() { + @Override + public void onClickItem(int item) { + if(item>=0 && strings.size()>item){ + Log.d(TAG,"Select Profile "+strings.get(item)); + //TODO: + connectService(strings.get(item)); + } + } + }); + mDialogMenu.show(getSupportFragmentManager(), "SimpleDialog"); + } + */ + private void showTypeRegister(final Context context) { + final String[] strings = {"With External authentication", "No authentication"}; + if (strings == null || strings.length == 0) return; + mDialogMenu = null; + mDialogMenu = DialogMenu.newInstance(strings, "Registration types"); mDialogMenu.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ - Log.d(TAG,"Select type call "+strings[item]); + if (item >= 0 && strings.length > item) { + Log.d(TAG, "Select type call " + strings[item]); try { - int typeCalls=-1; - switch (item){ + int typeCalls = -1; + switch (item) { case 0: - if(mService!=null) - mService.loginMCOP(); + if (mService != null) + mService.loginMCOP(); break; case 1: //Test - if(mService!=null) - mService.authorizeUser(null); + if (mService != null) + mService.authorizeUser(null); break; default: @@ -852,8 +952,8 @@ public class MainActivity extends AppCompatActivity { } }); mDialogMenu.show(getSupportFragmentManager(), "SimpleDialog"); - if(mDialogMenu==null){ - if(mService!=null) { + if (mDialogMenu == null) { + if (mService != null) { try { mService.authorizeUser(null); } catch (RemoteException e) { @@ -863,64 +963,58 @@ public class MainActivity extends AppCompatActivity { } } - private void showMakeCallTypes(final Context context){ - final String[] strings={"Private call" - ,"Private call(whitout floor control)" - ,"Group call" - ,"Emergency Group call" - ,"Emergency Private call" - ,"Chat Group call" + private void showMakeCallTypes(final Context context) { + final String[] strings = {"Private call" + , "Private call(whitout floor control)" + , "Group call" + , "Emergency Group call" + , "Emergency Private call" + , "Chat Group call" }; - if(strings==null || strings.length==0)return; - mDialogMenu = DialogMenu.newInstance(strings,"Call types"); + if (strings == null || strings.length == 0) return; + mDialogMenu = DialogMenu.newInstance(strings, "Call types"); mDialogMenu.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ - Log.d(TAG,"Select type call "+strings[item]); + if (item >= 0 && strings.length > item) { + Log.d(TAG, "Select type call " + strings[item]); try { - int typeCalls=-1; - String typeCall=null; - if((typeCall=strings[item])!=null){ - if(typeCall.compareTo("Private call")==0){ - typeCalls=ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue()| - ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue(); - } - else if(typeCall.compareTo("Private call(whitout floor control)")==0){ - typeCalls=ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithoutFloorCtrl.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue(); - } - else if(typeCall.compareTo("Group call")==0) { - typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue(); - } - else if(typeCall.compareTo("Emergency Group call")==0) { - typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.Emergency.getValue(); - } - else if(typeCall.compareTo("Emergency Private call")==0) { - typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.Emergency.getValue(); - } - else if(typeCall.compareTo("Chat Group call")==0) { - typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | - ConstantsMCOP.CallEventExtras.CallTypeEnum.ChatGroup.getValue(); - } - + int typeCalls = -1; + String typeCall = null; + if ((typeCall = strings[item]) != null) { + if (typeCall.compareTo("Private call") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue(); + } else if (typeCall.compareTo("Private call(whitout floor control)") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithoutFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue(); + } else if (typeCall.compareTo("Group call") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue(); + } else if (typeCall.compareTo("Emergency Group call") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.PrearrangedGroup.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Emergency.getValue(); + } else if (typeCall.compareTo("Emergency Private call") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Private.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.Emergency.getValue(); + } else if (typeCall.compareTo("Chat Group call") == 0) { + typeCalls = ConstantsMCOP.CallEventExtras.CallTypeEnum.Audio.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.WithFloorCtrl.getValue() | + ConstantsMCOP.CallEventExtras.CallTypeEnum.ChatGroup.getValue(); } + } - if(typeCalls>0 && mService!=null) + if (typeCalls > 0 && mService != null) mService.makeCall( mainActivity_EditText_affiliation.getText().toString().trim(), typeCalls @@ -934,26 +1028,26 @@ public class MainActivity extends AppCompatActivity { mDialogMenu.show(getSupportFragmentManager(), "SimpleDialog"); } - private void showIds(final Context context){ - if(userData.getSessionIDs()==null)return; - final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); + private void showIds(final Context context) { + if (userData.getSessionIDs() == null) return; + final String[] strings = userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); - if(strings==null || strings.length==0)return; - if(strings.length==1) { + if (strings == null || strings.length == 0) return; + if (strings.length == 1) { try { - if(mService!=null) - mService.hangUpCall(strings[0]); + if (mService != null) + mService.hangUpCall(strings[0]); } catch (RemoteException e) { e.printStackTrace(); } - }else{ - mDialogIds = DialogMenu.newInstance(strings,null); + } else { + mDialogIds = DialogMenu.newInstance(strings, null); mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ + if (item >= 0 && strings.length > item) { try { - if(mService!=null) + if (mService != null) mService.hangUpCall(strings[item]); } catch (RemoteException e) { e.printStackTrace(); @@ -965,31 +1059,31 @@ public class MainActivity extends AppCompatActivity { } } - private void showIdsOperationFloorControl(final Context context, final boolean request){ - if(userData.getSessionIDs()==null)return; - final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); - if(strings==null || strings.length==0)return; - if(strings.length==1) { + private void showIdsOperationFloorControl(final Context context, final boolean request) { + if (userData.getSessionIDs() == null) return; + final String[] strings = userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); + if (strings == null || strings.length == 0) return; + if (strings.length == 1) { try { - if(mService!=null) + if (mService != null) mService.floorControlOperation( strings[0], - request?ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue():ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), + request ? ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue() : ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), null); } catch (RemoteException e) { e.printStackTrace(); } - }else{ - mDialogIds = DialogMenu.newInstance(strings,null); + } else { + mDialogIds = DialogMenu.newInstance(strings, null); mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ + if (item >= 0 && strings.length > item) { try { - if(mService!=null) + if (mService != null) mService.floorControlOperation( strings[item], - request?ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue():ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), + request ? ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Request.getValue() : ConstantsMCOP.FloorControlEventExtras.FloorControlOperationTypeEnum.MCPTT_Release.getValue(), null); } catch (RemoteException e) { e.printStackTrace(); @@ -1002,25 +1096,25 @@ public class MainActivity extends AppCompatActivity { } } - private void showIdsAcceptCall(final Context context){ - if(userData.getSessionIDs()==null)return; - final String[] strings=userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); - if(strings==null || strings.length==0)return; - if(strings.length==1) { + private void showIdsAcceptCall(final Context context) { + if (userData.getSessionIDs() == null) return; + final String[] strings = userData.getSessionIDs().toArray(new String[userData.getSessionIDs().size()]); + if (strings == null || strings.length == 0) return; + if (strings.length == 1) { try { - if(mService!=null) + if (mService != null) mService.acceptCall(strings[0]); } catch (RemoteException e) { e.printStackTrace(); } - }else{ - mDialogIds = DialogMenu.newInstance(strings,null); + } else { + mDialogIds = DialogMenu.newInstance(strings, null); mDialogIds.setOnClickItemListener(new DialogMenu.OnClickListener() { @Override public void onClickItem(int item) { - if(item>=0 && strings.length>item){ + if (item >= 0 && strings.length > item) { try { - if(mService!=null) + if (mService != null) mService.acceptCall(strings[item]); } catch (RemoteException e) { e.printStackTrace(); @@ -1033,70 +1127,70 @@ public class MainActivity extends AppCompatActivity { } @Override - protected void onDestroy(){ - if(BuildConfig.DEBUG)Log.i(TAG,"onDestroy"); + protected void onDestroy() { + if (BuildConfig.DEBUG) Log.i(TAG, "onDestroy"); super.onDestroy(); - if(mConnection!=null && isConnect){ - try{ - if(BuildConfig.DEBUG)Log.i(TAG,"unbindService"); + if (mConnection != null && isConnect) { + try { + if (BuildConfig.DEBUG) Log.i(TAG, "unbindService"); unbindService(mConnection); - isConnect=false; - }catch (Exception e){ - Log.e(TAG,"Error in unbind Service"); + isConnect = false; + } catch (Exception e) { + Log.e(TAG, "Error in unbind Service"); } - }else{ - Log.e(TAG,"Error 2 in unbind Service"); + } else { + Log.e(TAG, "Error 2 in unbind Service"); } - if(serviceIntent!=null){ - try{ + if (serviceIntent != null) { + try { stopService(serviceIntent); - }catch (Exception e){ - Log.e(TAG,"Error in stop Service"); + } catch (Exception e) { + Log.e(TAG, "Error in stop Service"); } - }else{ - Log.e(TAG,"Error 2 in stop Service"); + } else { + Log.e(TAG, "Error 2 in stop Service"); } - mConnection=null; + mConnection = null; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if(BuildConfig.DEBUG)Log.i(TAG,"onActivityResult"); - switch (requestCode){ + if (BuildConfig.DEBUG) Log.i(TAG, "onActivityResult"); + switch (requestCode) { case AUTHETICATION_RESULT: - if ( resultCode == ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_LISTENER_FAILURE) { + if (resultCode == ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_LISTENER_FAILURE) { String dataError; if (data != null && - (dataError= data.getStringExtra(org.mcopenplatform.muoapi.mcopsdk.ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_ERROR))!=null && + (dataError = data.getStringExtra(org.mcopenplatform.muoapi.mcopsdk.ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_ERROR)) != null && dataError instanceof String) { - Log.e(TAG,"Authentication Error: "+dataError); - }else{ - Log.e(TAG,"Error Processing Authentication."); + Log.e(TAG, "Authentication Error: " + dataError); + } else { + Log.e(TAG, "Error Processing Authentication."); } - }else if ( resultCode == ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_LISTENER_OK) { + } else if (resultCode == ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_LISTENER_OK) { String dataUri; if (data != null && - (dataUri= data.getStringExtra(org.mcopenplatform.muoapi.mcopsdk.ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_RESPONSE))!=null && + (dataUri = data.getStringExtra(org.mcopenplatform.muoapi.mcopsdk.ScreenAutheticationWebView.RETURN_ON_AUTHENTICATION_RESPONSE)) != null && dataUri instanceof String) { URI uri = null; try { uri = new URI(dataUri); Log.i(TAG, "Uri: " + uri.toString()); try { - if(mService!=null) - mService.authorizeUser(dataUri); + if (mService != null) + mService.authorizeUser(dataUri); } catch (RemoteException e) { e.printStackTrace(); } } catch (URISyntaxException e) { - Log.e(TAG,"Authentication Error: "+e.getMessage()); + Log.e(TAG, "Authentication Error: " + e.getMessage()); e.printStackTrace(); } - }else{ - Log.e(TAG,"Error processing file to import Profiles."); + } else { + Log.e(TAG, "Error processing file to import Profiles."); } } break; @@ -1104,68 +1198,66 @@ public class MainActivity extends AppCompatActivity { } //START GUI - private void unRegisted(boolean success){ + private void unRegisted(boolean success) { userData.setRegisted(false); userData.setDisplayName(null); userData.setMcpttID(null); mainActivity_TextView_info.setText("UNREGISTERED"); } - private void isRegisted( boolean success, String mcpttID, String displayName){ + private void isRegisted(boolean success, String mcpttID, String displayName) { userData.setRegisted(success); - if(mcpttID!=null) + if (mcpttID != null) userData.setMcpttID(mcpttID); - if(displayName!=null){ + if (displayName != null) { userData.setDisplayName(displayName); } - Log.d(TAG,"REGISTERED. MCPTT ID: "+mcpttID+" DISPLAY NAME: "+displayName); - mainActivity_TextView_info.setText("REGISTERED. MCPTT ID: "+mcpttID+" DISPLAY NAME: "+displayName); + Log.d(TAG, "REGISTERED. MCPTT ID: " + mcpttID + " DISPLAY NAME: " + displayName); + mainActivity_TextView_info.setText("REGISTERED. MCPTT ID: " + mcpttID + " DISPLAY NAME: " + displayName); } - private void showData(String eventType,String data){ - Log.d(TAG,eventType+": "+data); - mainActivity_TextView_info.setText(eventType+": "+data); + private void showData(String eventType, String data) { + Log.d(TAG, eventType + ": " + data); + mainActivity_TextView_info.setText(eventType + ": " + data); } - private void showLastError(String from,int code,String errorString){ - Log.e(TAG,"ERROR "+from+": "+code+" "+errorString); - mainActivity_TextView_error.setText("ERROR "+from+": "+code+" "+errorString); + private void showLastError(String from, int code, String errorString) { + Log.e(TAG, "ERROR " + from + ": " + code + " " + errorString); + mainActivity_TextView_error.setText("ERROR " + from + ": " + code + " " + errorString); } - private void showGroups(Map groups){ - if(BuildConfig.DEBUG && groups!=null)Log.d(TAG,"showGroups size: "+groups.size()); - String result=""; - if(groups!=null) - for (String groupID:groups.keySet()){ - String type=""; - switch (ConstantsMCOP.GroupAffiliationEventExtras.GroupAffiliationStateEnum.fromInt(groups.get(groupID))){ + private void showGroups(Map groups) { + if (BuildConfig.DEBUG && groups != null) Log.d(TAG, "showGroups size: " + groups.size()); + String result = ""; + if (groups != null) + for (String groupID : groups.keySet()) { + String type = ""; + switch (ConstantsMCOP.GroupAffiliationEventExtras.GroupAffiliationStateEnum.fromInt(groups.get(groupID))) { case notaffiliated: - type="notaffiliated"; + type = "notaffiliated"; break; case affiliating: - type="affiliating"; + type = "affiliating"; break; case affiliated: - type="affiliated"; + type = "affiliated"; break; case deaffiliating: - type="deaffiliating"; + type = "deaffiliating"; break; } - result=result+"groupID:"+groupID+":"+type+"\n"; + result = result + "groupID:" + groupID + ":" + type + "\n"; } Calendar calendar = Calendar.getInstance(); - mainActivity_TextView_affiliation.setText("Lists Group Affiliations:(Time:"+String.format("%1$tA %1$tb %1$td %1$tY at %1$tI:%1$tM %1$Tp", calendar)+")\n"+result); + mainActivity_TextView_affiliation.setText("Lists Group Affiliations:(Time:" + String.format("%1$tA %1$tb %1$td %1$tY at %1$tI:%1$tM %1$Tp", calendar) + ")\n" + result); } - - /** * Set permissions for Android 6.0 or above */ - protected void setPermissions(){ + protected void setPermissions() { //Set Permissions //READ_PHONE_STATE if (ActivityCompat.checkSelfPermission(this, @@ -1177,7 +1269,7 @@ public class MainActivity extends AppCompatActivity { ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.FOREGROUND_SERVICE) != PackageManager.PERMISSION_GRANTED - ) { + ) { //Should we show an explanation? if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { @@ -1193,14 +1285,14 @@ public class MainActivity extends AppCompatActivity { Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE, - // Manifest.permission.FOREGROUND_SERVICE + // Manifest.permission.FOREGROUND_SERVICE }, GET_PERMISSION); } else { //No explanation needed, we can request the permission. ActivityCompat.requestPermissions(this, - new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA,Manifest.permission.READ_PHONE_STATE,Manifest.permission.FOREGROUND_SERVICE}, + new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.CAMERA, Manifest.permission.READ_PHONE_STATE, Manifest.permission.FOREGROUND_SERVICE}, GET_PERMISSION); //MY_PERMISSIONS_REQUEST_READ_CONTACTS is an @@ -1212,8 +1304,8 @@ public class MainActivity extends AppCompatActivity { @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { - if(BuildConfig.DEBUG)Log.i(TAG,"onRequestPermissionsResult"); - super.onRequestPermissionsResult(requestCode, permissions,grantResults); + if (BuildConfig.DEBUG) Log.i(TAG, "onRequestPermissionsResult"); + super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case GET_PERMISSION: { //If request is cancelled, the result arrays are empty. @@ -1242,12 +1334,11 @@ public class MainActivity extends AppCompatActivity { * API>22 */ @TargetApi(Build.VERSION_CODES.M) - protected void setPermissionsWriteSetting(){ + protected void setPermissionsWriteSetting() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - if (Settings.System.canWrite(this) ){ + if (Settings.System.canWrite(this)) { //Do stuff here - } - else { + } else { Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + this.getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); diff --git a/app/src/main/java/patch/Audio.java b/app/src/main/java/patch/Audio.java new file mode 100644 index 0000000000000000000000000000000000000000..87702d6e822eb7312bd7faa9075b39e5ba4a35bc --- /dev/null +++ b/app/src/main/java/patch/Audio.java @@ -0,0 +1,73 @@ +package patch; + +import java.util.ArrayList; + +public class Audio { + private static final long MS_PER_DATA = 20; + + private String sender; + private boolean mine; + private ArrayList data = new ArrayList<>(); + private int curr = 0; + + Audio(String sender, boolean mine) { + String tmp = FragmentPttViewModel.SIDNames.get(sender); + if (tmp == null) tmp = sender; + this.sender = tmp; + this.mine = mine; + } + + String getSender() { + return sender; + } + + boolean isMine() { + return mine; + } + + void addData(byte[] buf) { + synchronized (data) { + data.add(buf); + } + } + + long getLength() { + return data.size(); + } + + long getLengthMS() { + return data.size() * MS_PER_DATA; + } + + long getCurrMS() { + return curr * MS_PER_DATA; + } + + void seek(long pos) { + synchronized (data) { + long dataIdx = pos / MS_PER_DATA; + if (dataIdx >= data.size()) dataIdx = data.size() - 1; + curr = (int) dataIdx; + } + } + + byte[] get(int pos) { + synchronized (data) { + return data.get(pos); + } + } + + byte[] getNext() { + synchronized (data) { + if (curr >= data.size()) { + curr = data.size(); + return null; + } + return data.get(curr++); + } + } + + void resetCurr() { + curr = 0; + } +} diff --git a/app/src/main/java/patch/AudioManager.java b/app/src/main/java/patch/AudioManager.java new file mode 100644 index 0000000000000000000000000000000000000000..c377d9909c6641f33407bf254d5f1b9d8c52572c --- /dev/null +++ b/app/src/main/java/patch/AudioManager.java @@ -0,0 +1,291 @@ +package patch; + +import android.content.Context; +import android.content.Intent; +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.AudioTrack; +import android.media.MediaRecorder; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import org.doubango.ngn.media.NgnProxyAudioProducer; +import org.mcopenplatform.muoapi.mcopsdk.MainActivity; + +import java.util.ArrayList; +import java.util.List; + +public class AudioManager { + + + private AudioTrack mAudioTrack; + private AudioRecord mAudioRecord; + private boolean paused = false; + private boolean recording = false; + private boolean connected = false; + private boolean dirty; + + private final List