management of statistics by calls
This commit is contained in:
parent
0c875fc4e9
commit
f81910644a
9 changed files with 1297 additions and 610 deletions
|
@ -173,3 +173,6 @@ Group changes to describe their impact on the project, as follows:
|
||||||
- Crashes Android 6/7 at starting
|
- Crashes Android 6/7 at starting
|
||||||
- Permissions issues
|
- Permissions issues
|
||||||
- Layout of tablet views
|
- Layout of tablet views
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- management of the view for displaying call statistics
|
||||||
|
|
168
app/src/main/java/org/linphone/call/CallStatsAdapter.java
Normal file
168
app/src/main/java/org/linphone/call/CallStatsAdapter.java
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
package org.linphone.call;
|
||||||
|
|
||||||
|
/*
|
||||||
|
CallStatsAdapter.java
|
||||||
|
Copyright (C) 2019 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
|
This program 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 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseExpandableListAdapter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.linphone.R;
|
||||||
|
import org.linphone.contacts.ContactsManager;
|
||||||
|
import org.linphone.contacts.LinphoneContact;
|
||||||
|
import org.linphone.core.Call;
|
||||||
|
import org.linphone.utils.LinphoneUtils;
|
||||||
|
import org.linphone.views.ContactAvatar;
|
||||||
|
|
||||||
|
public class CallStatsAdapter extends BaseExpandableListAdapter {
|
||||||
|
private final Context mContext;
|
||||||
|
private List<Call> mCalls;
|
||||||
|
|
||||||
|
public CallStatsAdapter(Context mContext) {
|
||||||
|
this.mContext = mContext;
|
||||||
|
mCalls = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateListItems(List<Call> listCall) {
|
||||||
|
if (listCall != null) {
|
||||||
|
mCalls = listCall;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getChildView(
|
||||||
|
int groupPosition,
|
||||||
|
int childPosition,
|
||||||
|
boolean isLastChild,
|
||||||
|
View view,
|
||||||
|
ViewGroup viewGroup) {
|
||||||
|
|
||||||
|
CallStatsChildViewHolder holder;
|
||||||
|
|
||||||
|
if (view != null) {
|
||||||
|
Object possibleHolder = view.getTag();
|
||||||
|
if (possibleHolder instanceof CallStatsChildViewHolder) {
|
||||||
|
holder = (CallStatsChildViewHolder) possibleHolder;
|
||||||
|
view.setTag(holder);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// opening the statistics view
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||||
|
view = inflater.inflate(R.layout.call_stats_child, viewGroup, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// filling the view
|
||||||
|
holder = new CallStatsChildViewHolder(view, mContext);
|
||||||
|
view.setTag(holder);
|
||||||
|
holder.setCall(mCalls.get(groupPosition));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getGroupView(
|
||||||
|
int groupPosition, boolean isExpanded, View view, ViewGroup viewGroup) {
|
||||||
|
|
||||||
|
CallStatsViewHolder holder = null;
|
||||||
|
if (view != null) {
|
||||||
|
Object possibleHolder = view.getTag();
|
||||||
|
if (possibleHolder instanceof CallStatsViewHolder) {
|
||||||
|
holder = (CallStatsViewHolder) possibleHolder;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||||
|
view = inflater.inflate(R.layout.call_stats_group, viewGroup, false);
|
||||||
|
}
|
||||||
|
if (holder == null) {
|
||||||
|
holder = new CallStatsViewHolder(view);
|
||||||
|
view.setTag(holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recovering the current call
|
||||||
|
Call call = (Call) getGroup(groupPosition);
|
||||||
|
// Search for the associated contact
|
||||||
|
LinphoneContact contact =
|
||||||
|
ContactsManager.getInstance().findContactFromAddress(call.getRemoteAddress());
|
||||||
|
if (contact != null) {
|
||||||
|
// Setting up the avatar
|
||||||
|
ContactAvatar.displayAvatar(contact, holder.avatarLayout);
|
||||||
|
// addition of the participant's name
|
||||||
|
holder.participantName.setText(contact.getFullName());
|
||||||
|
} else {
|
||||||
|
String displayName = LinphoneUtils.getAddressDisplayName(call.getRemoteAddress());
|
||||||
|
ContactAvatar.displayAvatar(displayName, holder.avatarLayout);
|
||||||
|
holder.participantName.setText(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add sip address on group view
|
||||||
|
holder.sipUri.setText(call.getRemoteAddress().asString());
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGroupCount() {
|
||||||
|
return mCalls.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildrenCount(int groupPosition) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getGroup(int groupPosition) {
|
||||||
|
if (mCalls.isEmpty() && groupPosition < mCalls.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mCalls.get(groupPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getChild(int groupPosition, int childPosition) {
|
||||||
|
if (mCalls.isEmpty() && groupPosition < mCalls.size()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mCalls.get(groupPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getGroupId(int groupPosition) {
|
||||||
|
return groupPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getChildId(int groupPosition, int childPosition) {
|
||||||
|
return groupPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChildSelectable(int groupPosition, int childPosition) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,396 @@
|
||||||
|
package org.linphone.call;
|
||||||
|
|
||||||
|
/*
|
||||||
|
CallStatsChildViewHolder.java
|
||||||
|
Copyright (C) 2019 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
|
This program 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 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import org.linphone.LinphoneManager;
|
||||||
|
import org.linphone.R;
|
||||||
|
import org.linphone.core.AddressFamily;
|
||||||
|
import org.linphone.core.Call;
|
||||||
|
import org.linphone.core.CallListenerStub;
|
||||||
|
import org.linphone.core.CallParams;
|
||||||
|
import org.linphone.core.CallStats;
|
||||||
|
import org.linphone.core.PayloadType;
|
||||||
|
import org.linphone.core.StreamType;
|
||||||
|
|
||||||
|
public class CallStatsChildViewHolder {
|
||||||
|
private Timer mTimer;
|
||||||
|
private Call mCall;
|
||||||
|
private final Handler mHandler = new Handler();
|
||||||
|
private CallListenerStub mListener;
|
||||||
|
private HashMap<String, String> mEncoderTexts;
|
||||||
|
private HashMap<String, String> mDecoderTexts;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
private TextView mTitleAudio;
|
||||||
|
private TextView mTitleVideo;
|
||||||
|
private TextView mCodecAudio;
|
||||||
|
private TextView mCodecVideo;
|
||||||
|
private TextView mEncoderAudio;
|
||||||
|
private TextView mDecoderAudio;
|
||||||
|
private TextView mEncoderVideo;
|
||||||
|
private TextView mDecoderVideo;
|
||||||
|
private TextView mDisplayFilter;
|
||||||
|
private TextView mDlAudio;
|
||||||
|
private TextView mUlAudio;
|
||||||
|
private TextView mDlVideo;
|
||||||
|
private TextView mUlVideo;
|
||||||
|
private TextView mEdlVideo;
|
||||||
|
private TextView mIceAudio;
|
||||||
|
private TextView mIceVideo;
|
||||||
|
private TextView mVideoResolutionSent;
|
||||||
|
private TextView mVideoResolutionReceived;
|
||||||
|
private TextView mVideoFpsSent;
|
||||||
|
private TextView mVideoFpsReceived;
|
||||||
|
private TextView mSenderLossRateAudio;
|
||||||
|
private TextView mReceiverLossRateAudio;
|
||||||
|
private TextView mSenderLossRateVideo;
|
||||||
|
private TextView mReceiverLossRateVideo;
|
||||||
|
private TextView mIpAudio;
|
||||||
|
private TextView mIpVideo;
|
||||||
|
private TextView mJitterBufferAudio;
|
||||||
|
private View mVideoLayout;
|
||||||
|
private View mAudioLayout;
|
||||||
|
|
||||||
|
public CallStatsChildViewHolder(View view, Context context) {
|
||||||
|
mContext = context;
|
||||||
|
|
||||||
|
mEncoderTexts = new HashMap<>();
|
||||||
|
mDecoderTexts = new HashMap<>();
|
||||||
|
|
||||||
|
mTitleAudio = view.findViewById(R.id.call_stats_audio);
|
||||||
|
mTitleVideo = view.findViewById(R.id.call_stats_video);
|
||||||
|
mCodecAudio = view.findViewById(R.id.codec_audio);
|
||||||
|
mCodecVideo = view.findViewById(R.id.codec_video);
|
||||||
|
mEncoderAudio = view.findViewById(R.id.encoder_audio);
|
||||||
|
mDecoderAudio = view.findViewById(R.id.decoder_audio);
|
||||||
|
mEncoderVideo = view.findViewById(R.id.encoder_video);
|
||||||
|
mDecoderVideo = view.findViewById(R.id.decoder_video);
|
||||||
|
mDisplayFilter = view.findViewById(R.id.display_filter);
|
||||||
|
mDlAudio = view.findViewById(R.id.downloadBandwith_audio);
|
||||||
|
mUlAudio = view.findViewById(R.id.uploadBandwith_audio);
|
||||||
|
mDlVideo = view.findViewById(R.id.downloadBandwith_video);
|
||||||
|
mUlVideo = view.findViewById(R.id.uploadBandwith_video);
|
||||||
|
mEdlVideo = view.findViewById(R.id.estimatedDownloadBandwidth_video);
|
||||||
|
mIceAudio = view.findViewById(R.id.ice_audio);
|
||||||
|
mIceVideo = view.findViewById(R.id.ice_video);
|
||||||
|
mVideoResolutionSent = view.findViewById(R.id.video_resolution_sent);
|
||||||
|
mVideoResolutionReceived = view.findViewById(R.id.video_resolution_received);
|
||||||
|
mVideoFpsSent = view.findViewById(R.id.video_fps_sent);
|
||||||
|
mVideoFpsReceived = view.findViewById(R.id.video_fps_received);
|
||||||
|
mSenderLossRateAudio = view.findViewById(R.id.senderLossRateAudio);
|
||||||
|
mReceiverLossRateAudio = view.findViewById(R.id.receiverLossRateAudio);
|
||||||
|
mSenderLossRateVideo = view.findViewById(R.id.senderLossRateVideo);
|
||||||
|
mReceiverLossRateVideo = view.findViewById(R.id.receiverLossRateVideo);
|
||||||
|
mIpAudio = view.findViewById(R.id.ip_audio);
|
||||||
|
mIpVideo = view.findViewById(R.id.ip_video);
|
||||||
|
mJitterBufferAudio = view.findViewById(R.id.jitterBufferAudio);
|
||||||
|
mVideoLayout = view.findViewById(R.id.callStatsVideo);
|
||||||
|
mAudioLayout = view.findViewById(R.id.callStatsAudio);
|
||||||
|
|
||||||
|
mListener =
|
||||||
|
new CallListenerStub() {
|
||||||
|
public void onStateChanged(Call call, Call.State cstate, String message) {
|
||||||
|
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
||||||
|
if (mTimer != null) {
|
||||||
|
org.linphone.core.tools.Log.i(
|
||||||
|
"[Call Stats] Call is terminated, stopping mCountDownTimer in charge of stats refreshing.");
|
||||||
|
mTimer.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCall(Call call) {
|
||||||
|
if (mCall != null) {
|
||||||
|
mCall.removeListener(mListener);
|
||||||
|
}
|
||||||
|
mCall = call;
|
||||||
|
mCall.addListener(mListener);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
TimerTask mTask;
|
||||||
|
|
||||||
|
mTimer = new Timer();
|
||||||
|
mTask =
|
||||||
|
new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mCall == null) {
|
||||||
|
mTimer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTitleAudio == null
|
||||||
|
|| mCodecAudio == null
|
||||||
|
|| mDlVideo == null
|
||||||
|
|| mEdlVideo == null
|
||||||
|
|| mIceAudio == null
|
||||||
|
|| mVideoResolutionSent == null
|
||||||
|
|| mVideoLayout == null
|
||||||
|
|| mTitleVideo == null
|
||||||
|
|| mIpVideo == null
|
||||||
|
|| mIpAudio == null
|
||||||
|
|| mCodecVideo == null
|
||||||
|
|| mDlAudio == null
|
||||||
|
|| mUlAudio == null
|
||||||
|
|| mUlVideo == null
|
||||||
|
|| mIceVideo == null
|
||||||
|
|| mVideoResolutionReceived == null) {
|
||||||
|
mTimer.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mHandler.post(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mCall == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCall.getState() != Call.State.Released) {
|
||||||
|
CallParams params = mCall.getCurrentParams();
|
||||||
|
if (params != null) {
|
||||||
|
CallStats audioStats =
|
||||||
|
mCall.getStats(StreamType.Audio);
|
||||||
|
CallStats videoStats = null;
|
||||||
|
|
||||||
|
if (params.videoEnabled())
|
||||||
|
videoStats = mCall.getStats(StreamType.Video);
|
||||||
|
|
||||||
|
PayloadType payloadAudio =
|
||||||
|
params.getUsedAudioPayloadType();
|
||||||
|
PayloadType payloadVideo =
|
||||||
|
params.getUsedVideoPayloadType();
|
||||||
|
|
||||||
|
formatText(
|
||||||
|
mDisplayFilter,
|
||||||
|
mContext.getString(
|
||||||
|
R.string.call_stats_display_filter),
|
||||||
|
mCall.getCore().getVideoDisplayFilter());
|
||||||
|
|
||||||
|
displayMediaStats(
|
||||||
|
params,
|
||||||
|
audioStats,
|
||||||
|
payloadAudio,
|
||||||
|
mAudioLayout,
|
||||||
|
mTitleAudio,
|
||||||
|
mCodecAudio,
|
||||||
|
mDlAudio,
|
||||||
|
mUlAudio,
|
||||||
|
null,
|
||||||
|
mIceAudio,
|
||||||
|
mIpAudio,
|
||||||
|
mSenderLossRateAudio,
|
||||||
|
mReceiverLossRateAudio,
|
||||||
|
mEncoderAudio,
|
||||||
|
mDecoderAudio,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
mJitterBufferAudio);
|
||||||
|
|
||||||
|
displayMediaStats(
|
||||||
|
params,
|
||||||
|
videoStats,
|
||||||
|
payloadVideo,
|
||||||
|
mVideoLayout,
|
||||||
|
mTitleVideo,
|
||||||
|
mCodecVideo,
|
||||||
|
mDlVideo,
|
||||||
|
mUlVideo,
|
||||||
|
mEdlVideo,
|
||||||
|
mIceVideo,
|
||||||
|
mIpVideo,
|
||||||
|
mSenderLossRateVideo,
|
||||||
|
mReceiverLossRateVideo,
|
||||||
|
mEncoderVideo,
|
||||||
|
mDecoderVideo,
|
||||||
|
mVideoResolutionSent,
|
||||||
|
mVideoResolutionReceived,
|
||||||
|
mVideoFpsSent,
|
||||||
|
mVideoFpsReceived,
|
||||||
|
true,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mTimer.scheduleAtFixedRate(mTask, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayMediaStats(
|
||||||
|
CallParams params,
|
||||||
|
CallStats stats,
|
||||||
|
PayloadType media,
|
||||||
|
View layout,
|
||||||
|
TextView title,
|
||||||
|
TextView codec,
|
||||||
|
TextView dl,
|
||||||
|
TextView ul,
|
||||||
|
TextView edl,
|
||||||
|
TextView ice,
|
||||||
|
TextView ip,
|
||||||
|
TextView senderLossRate,
|
||||||
|
TextView receiverLossRate,
|
||||||
|
TextView enc,
|
||||||
|
TextView dec,
|
||||||
|
TextView videoResolutionSent,
|
||||||
|
TextView videoResolutionReceived,
|
||||||
|
TextView videoFpsSent,
|
||||||
|
TextView videoFpsReceived,
|
||||||
|
boolean isVideo,
|
||||||
|
TextView jitterBuffer) {
|
||||||
|
|
||||||
|
if (stats != null) {
|
||||||
|
String mime = null;
|
||||||
|
|
||||||
|
layout.setVisibility(View.VISIBLE);
|
||||||
|
title.setVisibility(TextView.VISIBLE);
|
||||||
|
if (media != null) {
|
||||||
|
mime = media.getMimeType();
|
||||||
|
formatText(
|
||||||
|
codec,
|
||||||
|
mContext.getString(R.string.call_stats_codec),
|
||||||
|
mime + " / " + (media.getClockRate() / 1000) + "kHz");
|
||||||
|
}
|
||||||
|
if (mime != null) {
|
||||||
|
|
||||||
|
formatText(
|
||||||
|
enc,
|
||||||
|
mContext.getString(R.string.call_stats_encoder_name),
|
||||||
|
getEncoderText(mime));
|
||||||
|
formatText(
|
||||||
|
dec,
|
||||||
|
mContext.getString(R.string.call_stats_decoder_name),
|
||||||
|
getDecoderText(mime));
|
||||||
|
}
|
||||||
|
formatText(
|
||||||
|
dl,
|
||||||
|
mContext.getString(R.string.call_stats_download),
|
||||||
|
(int) stats.getDownloadBandwidth() + " kbits/s");
|
||||||
|
formatText(
|
||||||
|
ul,
|
||||||
|
mContext.getString(R.string.call_stats_upload),
|
||||||
|
(int) stats.getUploadBandwidth() + " kbits/s");
|
||||||
|
if (isVideo) {
|
||||||
|
formatText(
|
||||||
|
edl,
|
||||||
|
mContext.getString(R.string.call_stats_estimated_download),
|
||||||
|
stats.getEstimatedDownloadBandwidth() + " kbits/s");
|
||||||
|
}
|
||||||
|
formatText(
|
||||||
|
ice,
|
||||||
|
mContext.getString(R.string.call_stats_ice),
|
||||||
|
stats.getIceState().toString());
|
||||||
|
formatText(
|
||||||
|
ip,
|
||||||
|
mContext.getString(R.string.call_stats_ip),
|
||||||
|
(stats.getIpFamilyOfRemote() == AddressFamily.Inet6)
|
||||||
|
? "IpV6"
|
||||||
|
: (stats.getIpFamilyOfRemote() == AddressFamily.Inet)
|
||||||
|
? "IpV4"
|
||||||
|
: "Unknown");
|
||||||
|
|
||||||
|
formatText(
|
||||||
|
senderLossRate,
|
||||||
|
mContext.getString(R.string.call_stats_sender_loss_rate),
|
||||||
|
new DecimalFormat("##.##").format(stats.getSenderLossRate()) + "%");
|
||||||
|
formatText(
|
||||||
|
receiverLossRate,
|
||||||
|
mContext.getString(R.string.call_stats_receiver_loss_rate),
|
||||||
|
new DecimalFormat("##.##").format(stats.getReceiverLossRate()) + "%");
|
||||||
|
|
||||||
|
if (isVideo) {
|
||||||
|
formatText(
|
||||||
|
videoResolutionSent,
|
||||||
|
mContext.getString(R.string.call_stats_video_resolution_sent),
|
||||||
|
"\u2191 " + params.getSentVideoDefinition() != null
|
||||||
|
? params.getSentVideoDefinition().getName()
|
||||||
|
: "");
|
||||||
|
formatText(
|
||||||
|
videoResolutionReceived,
|
||||||
|
mContext.getString(R.string.call_stats_video_resolution_received),
|
||||||
|
"\u2193 " + params.getReceivedVideoDefinition() != null
|
||||||
|
? params.getReceivedVideoDefinition().getName()
|
||||||
|
: "");
|
||||||
|
formatText(
|
||||||
|
videoFpsSent,
|
||||||
|
mContext.getString(R.string.call_stats_video_fps_sent),
|
||||||
|
"\u2191 " + params.getSentFramerate());
|
||||||
|
formatText(
|
||||||
|
videoFpsReceived,
|
||||||
|
mContext.getString(R.string.call_stats_video_fps_received),
|
||||||
|
"\u2193 " + params.getReceivedFramerate());
|
||||||
|
} else {
|
||||||
|
formatText(
|
||||||
|
jitterBuffer,
|
||||||
|
mContext.getString(R.string.call_stats_jitter_buffer),
|
||||||
|
new DecimalFormat("##.##").format(stats.getJitterBufferSizeMs()) + " ms");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
layout.setVisibility(View.GONE);
|
||||||
|
title.setVisibility(TextView.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEncoderText(String mime) {
|
||||||
|
String ret = mEncoderTexts.get(mime);
|
||||||
|
if (ret == null) {
|
||||||
|
org.linphone.mediastream.Factory msfactory =
|
||||||
|
LinphoneManager.getCore().getMediastreamerFactory();
|
||||||
|
ret = msfactory.getEncoderText(mime);
|
||||||
|
mEncoderTexts.put(mime, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDecoderText(String mime) {
|
||||||
|
String ret = mDecoderTexts.get(mime);
|
||||||
|
if (ret == null) {
|
||||||
|
org.linphone.mediastream.Factory msfactory =
|
||||||
|
LinphoneManager.getCore().getMediastreamerFactory();
|
||||||
|
ret = msfactory.getDecoderText(mime);
|
||||||
|
mDecoderTexts.put(mime, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void formatText(TextView tv, String name, String value) {
|
||||||
|
tv.setText(Html.fromHtml("<b>" + name + " </b>" + value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,87 +21,75 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.Html;
|
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ExpandableListView;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import java.text.DecimalFormat;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import org.linphone.LinphoneManager;
|
import org.linphone.LinphoneManager;
|
||||||
import org.linphone.R;
|
import org.linphone.R;
|
||||||
import org.linphone.core.AddressFamily;
|
|
||||||
import org.linphone.core.Call;
|
import org.linphone.core.Call;
|
||||||
import org.linphone.core.CallListenerStub;
|
|
||||||
import org.linphone.core.CallParams;
|
|
||||||
import org.linphone.core.CallStats;
|
|
||||||
import org.linphone.core.Core;
|
import org.linphone.core.Core;
|
||||||
import org.linphone.core.PayloadType;
|
import org.linphone.core.CoreListenerStub;
|
||||||
import org.linphone.core.StreamType;
|
|
||||||
import org.linphone.core.tools.Log;
|
|
||||||
|
|
||||||
public class CallStatsFragment extends Fragment {
|
public class CallStatsFragment extends Fragment {
|
||||||
private final Handler mHandler = new Handler();
|
|
||||||
private Timer mTimer;
|
|
||||||
private TimerTask mTask;
|
|
||||||
|
|
||||||
private View mView;
|
|
||||||
private DrawerLayout mSideMenu;
|
private DrawerLayout mSideMenu;
|
||||||
private RelativeLayout mSideMenuContent;
|
private RelativeLayout mSideMenuContent;;
|
||||||
|
private ExpandableListView mExpandableList;
|
||||||
private HashMap<String, String> mEncoderTexts;
|
private CallStatsAdapter mAdapter;
|
||||||
private HashMap<String, String> mDecoderTexts;
|
private CoreListenerStub mListener;
|
||||||
|
|
||||||
private Call mCall;
|
|
||||||
private CallListenerStub mListener;
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(
|
public View onCreateView(
|
||||||
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
|
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.call_stats, container, false);
|
View view = inflater.inflate(R.layout.call_stats, container, false);
|
||||||
mView = view;
|
|
||||||
|
|
||||||
mEncoderTexts = new HashMap<>();
|
mExpandableList = view.findViewById(R.id.devices_list);
|
||||||
mDecoderTexts = new HashMap<>();
|
|
||||||
|
|
||||||
mListener =
|
mListener =
|
||||||
new CallListenerStub() {
|
new CoreListenerStub() {
|
||||||
public void onStateChanged(Call call, Call.State cstate, String message) {
|
@Override
|
||||||
|
public void onCallStateChanged(
|
||||||
|
Core lc, Call call, Call.State cstate, String message) {
|
||||||
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
||||||
if (mTimer != null) {
|
mAdapter.updateListItems(
|
||||||
Log.i(
|
Arrays.asList(LinphoneManager.getCore().getCalls()));
|
||||||
"[Call Stats] Call is terminated, stopping mCountDownTimer in charge of stats refreshing.");
|
|
||||||
mTimer.cancel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
Core core = LinphoneManager.getCore();
|
Core core = LinphoneManager.getCore();
|
||||||
if (core != null) {
|
|
||||||
setCall(core.getCurrentCall());
|
if (mAdapter == null) {
|
||||||
|
mAdapter = new CallStatsAdapter(getActivity());
|
||||||
|
|
||||||
|
mExpandableList.setAdapter(mAdapter);
|
||||||
|
// allows you to open the first child in the list
|
||||||
|
mExpandableList.expandGroup(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sends calls from the list to the adapter
|
||||||
|
if (core != null && core.getCallsNb() >= 1) {
|
||||||
|
mAdapter.updateListItems(Arrays.asList(core.getCalls()));
|
||||||
|
}
|
||||||
|
|
||||||
|
core.addListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
setCall(null);
|
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
LinphoneManager.getCore().removeListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDrawer(DrawerLayout drawer, RelativeLayout content) {
|
public void setDrawer(DrawerLayout drawer, RelativeLayout content) {
|
||||||
|
@ -131,294 +119,4 @@ public class CallStatsFragment extends Fragment {
|
||||||
mSideMenu.closeDrawer(mSideMenuContent, animate);
|
mSideMenu.closeDrawer(mSideMenuContent, animate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCall(Call call) {
|
|
||||||
if (mCall != null) {
|
|
||||||
mCall.removeListener(mListener);
|
|
||||||
}
|
|
||||||
mCall = call;
|
|
||||||
init(mView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(View view) {
|
|
||||||
if (getResources().getBoolean(R.bool.hide_in_call_stats)) return;
|
|
||||||
|
|
||||||
if (mTimer != null && mTask != null) {
|
|
||||||
mTimer.cancel();
|
|
||||||
mTimer = null;
|
|
||||||
mTask = null;
|
|
||||||
}
|
|
||||||
if (mCall == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final TextView titleAudio = view.findViewById(R.id.call_stats_audio);
|
|
||||||
final TextView titleVideo = view.findViewById(R.id.call_stats_video);
|
|
||||||
final TextView codecAudio = view.findViewById(R.id.codec_audio);
|
|
||||||
final TextView codecVideo = view.findViewById(R.id.codec_video);
|
|
||||||
final TextView encoderAudio = view.findViewById(R.id.encoder_audio);
|
|
||||||
final TextView decoderAudio = view.findViewById(R.id.decoder_audio);
|
|
||||||
final TextView encoderVideo = view.findViewById(R.id.encoder_video);
|
|
||||||
final TextView decoderVideo = view.findViewById(R.id.decoder_video);
|
|
||||||
final TextView displayFilter = view.findViewById(R.id.display_filter);
|
|
||||||
final TextView dlAudio = view.findViewById(R.id.downloadBandwith_audio);
|
|
||||||
final TextView ulAudio = view.findViewById(R.id.uploadBandwith_audio);
|
|
||||||
final TextView dlVideo = view.findViewById(R.id.downloadBandwith_video);
|
|
||||||
final TextView ulVideo = view.findViewById(R.id.uploadBandwith_video);
|
|
||||||
final TextView edlVideo = view.findViewById(R.id.estimatedDownloadBandwidth_video);
|
|
||||||
final TextView iceAudio = view.findViewById(R.id.ice_audio);
|
|
||||||
final TextView iceVideo = view.findViewById(R.id.ice_video);
|
|
||||||
final TextView videoResolutionSent = view.findViewById(R.id.video_resolution_sent);
|
|
||||||
final TextView videoResolutionReceived = view.findViewById(R.id.video_resolution_received);
|
|
||||||
final TextView videoFpsSent = view.findViewById(R.id.video_fps_sent);
|
|
||||||
final TextView videoFpsReceived = view.findViewById(R.id.video_fps_received);
|
|
||||||
final TextView senderLossRateAudio = view.findViewById(R.id.senderLossRateAudio);
|
|
||||||
final TextView receiverLossRateAudio = view.findViewById(R.id.receiverLossRateAudio);
|
|
||||||
final TextView senderLossRateVideo = view.findViewById(R.id.senderLossRateVideo);
|
|
||||||
final TextView receiverLossRateVideo = view.findViewById(R.id.receiverLossRateVideo);
|
|
||||||
final TextView ipAudio = view.findViewById(R.id.ip_audio);
|
|
||||||
final TextView ipVideo = view.findViewById(R.id.ip_video);
|
|
||||||
final TextView jitterBufferAudio = view.findViewById(R.id.jitterBufferAudio);
|
|
||||||
final View videoLayout = view.findViewById(R.id.callStatsVideo);
|
|
||||||
final View audioLayout = view.findViewById(R.id.callStatsAudio);
|
|
||||||
|
|
||||||
mTimer = new Timer();
|
|
||||||
mTask =
|
|
||||||
new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mCall == null) {
|
|
||||||
mTimer.cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (titleAudio == null
|
|
||||||
|| codecAudio == null
|
|
||||||
|| dlVideo == null
|
|
||||||
|| edlVideo == null
|
|
||||||
|| iceAudio == null
|
|
||||||
|| videoResolutionSent == null
|
|
||||||
|| videoLayout == null
|
|
||||||
|| titleVideo == null
|
|
||||||
|| ipVideo == null
|
|
||||||
|| ipAudio == null
|
|
||||||
|| codecVideo == null
|
|
||||||
|| dlAudio == null
|
|
||||||
|| ulAudio == null
|
|
||||||
|| ulVideo == null
|
|
||||||
|| iceVideo == null
|
|
||||||
|| videoResolutionReceived == null) {
|
|
||||||
mTimer.cancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mHandler.post(
|
|
||||||
new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mCall == null) return;
|
|
||||||
|
|
||||||
if (mCall.getState() != Call.State.Released) {
|
|
||||||
CallParams params = mCall.getCurrentParams();
|
|
||||||
if (params != null) {
|
|
||||||
CallStats audioStats =
|
|
||||||
mCall.getStats(StreamType.Audio);
|
|
||||||
CallStats videoStats = null;
|
|
||||||
|
|
||||||
if (params.videoEnabled())
|
|
||||||
videoStats = mCall.getStats(StreamType.Video);
|
|
||||||
|
|
||||||
PayloadType payloadAudio =
|
|
||||||
params.getUsedAudioPayloadType();
|
|
||||||
PayloadType payloadVideo =
|
|
||||||
params.getUsedVideoPayloadType();
|
|
||||||
|
|
||||||
formatText(
|
|
||||||
displayFilter,
|
|
||||||
getString(
|
|
||||||
R.string.call_stats_display_filter),
|
|
||||||
mCall.getCore().getVideoDisplayFilter());
|
|
||||||
|
|
||||||
displayMediaStats(
|
|
||||||
params,
|
|
||||||
audioStats,
|
|
||||||
payloadAudio,
|
|
||||||
audioLayout,
|
|
||||||
titleAudio,
|
|
||||||
codecAudio,
|
|
||||||
dlAudio,
|
|
||||||
ulAudio,
|
|
||||||
null,
|
|
||||||
iceAudio,
|
|
||||||
ipAudio,
|
|
||||||
senderLossRateAudio,
|
|
||||||
receiverLossRateAudio,
|
|
||||||
encoderAudio,
|
|
||||||
decoderAudio,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
jitterBufferAudio);
|
|
||||||
|
|
||||||
displayMediaStats(
|
|
||||||
params,
|
|
||||||
videoStats,
|
|
||||||
payloadVideo,
|
|
||||||
videoLayout,
|
|
||||||
titleVideo,
|
|
||||||
codecVideo,
|
|
||||||
dlVideo,
|
|
||||||
ulVideo,
|
|
||||||
edlVideo,
|
|
||||||
iceVideo,
|
|
||||||
ipVideo,
|
|
||||||
senderLossRateVideo,
|
|
||||||
receiverLossRateVideo,
|
|
||||||
encoderVideo,
|
|
||||||
decoderVideo,
|
|
||||||
videoResolutionSent,
|
|
||||||
videoResolutionReceived,
|
|
||||||
videoFpsSent,
|
|
||||||
videoFpsReceived,
|
|
||||||
true,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mCall.addListener(mListener);
|
|
||||||
mTimer.scheduleAtFixedRate(mTask, 0, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void formatText(TextView tv, String name, String value) {
|
|
||||||
tv.setText(Html.fromHtml("<b>" + name + " </b>" + value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getEncoderText(String mime) {
|
|
||||||
String ret = mEncoderTexts.get(mime);
|
|
||||||
if (ret == null) {
|
|
||||||
org.linphone.mediastream.Factory msfactory =
|
|
||||||
LinphoneManager.getCore().getMediastreamerFactory();
|
|
||||||
ret = msfactory.getEncoderText(mime);
|
|
||||||
mEncoderTexts.put(mime, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getDecoderText(String mime) {
|
|
||||||
String ret = mDecoderTexts.get(mime);
|
|
||||||
if (ret == null) {
|
|
||||||
org.linphone.mediastream.Factory msfactory =
|
|
||||||
LinphoneManager.getCore().getMediastreamerFactory();
|
|
||||||
ret = msfactory.getDecoderText(mime);
|
|
||||||
mDecoderTexts.put(mime, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayMediaStats(
|
|
||||||
CallParams params,
|
|
||||||
CallStats stats,
|
|
||||||
PayloadType media,
|
|
||||||
View layout,
|
|
||||||
TextView title,
|
|
||||||
TextView codec,
|
|
||||||
TextView dl,
|
|
||||||
TextView ul,
|
|
||||||
TextView edl,
|
|
||||||
TextView ice,
|
|
||||||
TextView ip,
|
|
||||||
TextView senderLossRate,
|
|
||||||
TextView receiverLossRate,
|
|
||||||
TextView enc,
|
|
||||||
TextView dec,
|
|
||||||
TextView videoResolutionSent,
|
|
||||||
TextView videoResolutionReceived,
|
|
||||||
TextView videoFpsSent,
|
|
||||||
TextView videoFpsReceived,
|
|
||||||
boolean isVideo,
|
|
||||||
TextView jitterBuffer) {
|
|
||||||
if (stats != null) {
|
|
||||||
String mime = null;
|
|
||||||
|
|
||||||
layout.setVisibility(View.VISIBLE);
|
|
||||||
title.setVisibility(TextView.VISIBLE);
|
|
||||||
if (media != null) {
|
|
||||||
mime = media.getMimeType();
|
|
||||||
formatText(
|
|
||||||
codec,
|
|
||||||
getString(R.string.call_stats_codec),
|
|
||||||
mime + " / " + (media.getClockRate() / 1000) + "kHz");
|
|
||||||
}
|
|
||||||
if (mime != null) {
|
|
||||||
formatText(enc, getString(R.string.call_stats_encoder_name), getEncoderText(mime));
|
|
||||||
formatText(dec, getString(R.string.call_stats_decoder_name), getDecoderText(mime));
|
|
||||||
}
|
|
||||||
formatText(
|
|
||||||
dl,
|
|
||||||
getString(R.string.call_stats_download),
|
|
||||||
(int) stats.getDownloadBandwidth() + " kbits/s");
|
|
||||||
formatText(
|
|
||||||
ul,
|
|
||||||
getString(R.string.call_stats_upload),
|
|
||||||
(int) stats.getUploadBandwidth() + " kbits/s");
|
|
||||||
if (isVideo) {
|
|
||||||
formatText(
|
|
||||||
edl,
|
|
||||||
getString(R.string.call_stats_estimated_download),
|
|
||||||
stats.getEstimatedDownloadBandwidth() + " kbits/s");
|
|
||||||
}
|
|
||||||
formatText(ice, getString(R.string.call_stats_ice), stats.getIceState().toString());
|
|
||||||
formatText(
|
|
||||||
ip,
|
|
||||||
getString(R.string.call_stats_ip),
|
|
||||||
(stats.getIpFamilyOfRemote() == AddressFamily.Inet6)
|
|
||||||
? "IpV6"
|
|
||||||
: (stats.getIpFamilyOfRemote() == AddressFamily.Inet)
|
|
||||||
? "IpV4"
|
|
||||||
: "Unknown");
|
|
||||||
formatText(
|
|
||||||
senderLossRate,
|
|
||||||
getString(R.string.call_stats_sender_loss_rate),
|
|
||||||
new DecimalFormat("##.##").format(stats.getSenderLossRate()) + "%");
|
|
||||||
formatText(
|
|
||||||
receiverLossRate,
|
|
||||||
getString(R.string.call_stats_receiver_loss_rate),
|
|
||||||
new DecimalFormat("##.##").format(stats.getReceiverLossRate()) + "%");
|
|
||||||
if (isVideo) {
|
|
||||||
formatText(
|
|
||||||
videoResolutionSent,
|
|
||||||
getString(R.string.call_stats_video_resolution_sent),
|
|
||||||
"\u2191 " + params.getSentVideoDefinition() != null
|
|
||||||
? params.getSentVideoDefinition().getName()
|
|
||||||
: "");
|
|
||||||
formatText(
|
|
||||||
videoResolutionReceived,
|
|
||||||
getString(R.string.call_stats_video_resolution_received),
|
|
||||||
"\u2193 " + params.getReceivedVideoDefinition() != null
|
|
||||||
? params.getReceivedVideoDefinition().getName()
|
|
||||||
: "");
|
|
||||||
formatText(
|
|
||||||
videoFpsSent,
|
|
||||||
getString(R.string.call_stats_video_fps_sent),
|
|
||||||
"\u2191 " + params.getSentFramerate());
|
|
||||||
formatText(
|
|
||||||
videoFpsReceived,
|
|
||||||
getString(R.string.call_stats_video_fps_received),
|
|
||||||
"\u2193 " + params.getReceivedFramerate());
|
|
||||||
} else {
|
|
||||||
formatText(
|
|
||||||
jitterBuffer,
|
|
||||||
getString(R.string.call_stats_jitter_buffer),
|
|
||||||
new DecimalFormat("##.##").format(stats.getJitterBufferSizeMs()) + " ms");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
layout.setVisibility(View.GONE);
|
|
||||||
title.setVisibility(TextView.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
37
app/src/main/java/org/linphone/call/CallStatsViewHolder.java
Normal file
37
app/src/main/java/org/linphone/call/CallStatsViewHolder.java
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package org.linphone.call;
|
||||||
|
|
||||||
|
/*
|
||||||
|
CallStatsViewHolder.java
|
||||||
|
Copyright (C) 2019 Belledonne Communications, Grenoble, France
|
||||||
|
|
||||||
|
This program 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 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.linphone.R;
|
||||||
|
|
||||||
|
public class CallStatsViewHolder {
|
||||||
|
|
||||||
|
public final RelativeLayout avatarLayout;
|
||||||
|
public final TextView participantName, sipUri;
|
||||||
|
|
||||||
|
public CallStatsViewHolder(View v) {
|
||||||
|
avatarLayout = v.findViewById(R.id.avatar_layout);
|
||||||
|
participantName = v.findViewById(R.id.name);
|
||||||
|
sipUri = v.findViewById(R.id.sipUri);
|
||||||
|
}
|
||||||
|
}
|
306
app/src/main/res/layout-land/call_stats_child.xml
Normal file
306
app/src/main/res/layout-land/call_stats_child.xml
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_audio"
|
||||||
|
style="@style/call_stats_title_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical|center"
|
||||||
|
android:text="@string/call_stats_audio"
|
||||||
|
tools:gravity="center" />
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:id="@+id/callStatsAudio"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_sip_adress"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/codec_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_codec" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/encoder_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_encoder_name" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/decoder_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uploadBandwith_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_upload" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/downloadBandwith_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_download" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ice_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ice" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ip_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/senderLossRateAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_sender_loss_rate" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/receiverLossRateAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_receiver_loss_rate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/jitterBufferAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_jitter_buffer" />
|
||||||
|
|
||||||
|
</TableLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_video"
|
||||||
|
style="@style/call_stats_title_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical|center"
|
||||||
|
android:text="@string/call_stats_video"
|
||||||
|
tools:gravity="center" />
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:id="@+id/callStatsVideo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left|center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/codec_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_codec" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/encoder_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_encoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/decoder_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/display_filter"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uploadBandwith_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_upload" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/downloadBandwith_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_download" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/estimatedDownloadBandwidth_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_estimated_download" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ice_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ice" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ip_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/senderLossRateVideo"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_sender_loss_rate" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/receiverLossRateVideo"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_receiver_loss_rate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_resolution_sent"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_resolution_sent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_resolution_received"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_resolution_received" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_fps_sent"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_fps_sent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_fps_received"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_fps_received" />
|
||||||
|
|
||||||
|
</TableLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
|
@ -1,285 +1,15 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<LinearLayout
|
<ExpandableListView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/devices_list"
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/call_stats_audio"
|
|
||||||
style="@style/call_stats_title_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical|center"
|
|
||||||
android:text="@string/call_stats_audio"
|
|
||||||
tools:gravity="center" />
|
|
||||||
|
|
||||||
<TableLayout
|
|
||||||
android:id="@+id/callStatsAudio"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="start|center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:paddingRight="5dp"
|
|
||||||
android:paddingBottom="10dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/codec_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:divider="?attr/dividerColor"
|
||||||
android:paddingLeft="5dp"
|
android:childDivider="?attr/dividerColor"
|
||||||
android:text="@string/call_stats_codec" />
|
android:dividerHeight="1dp"
|
||||||
|
android:groupIndicator="@null" />
|
||||||
|
|
||||||
<TextView
|
</RelativeLayout>
|
||||||
android:id="@+id/encoder_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_encoder_name" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/decoder_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_decoder_name" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/uploadBandwith_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_upload" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/downloadBandwith_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_download" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/ice_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_ice" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/ip_audio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_ip" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/senderLossRateAudio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_sender_loss_rate" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/receiverLossRateAudio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_receiver_loss_rate" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/jitterBufferAudio"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_jitter_buffer" />
|
|
||||||
|
|
||||||
</TableLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/call_stats_video"
|
|
||||||
style="@style/call_stats_title_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical|center"
|
|
||||||
android:text="@string/call_stats_video"
|
|
||||||
tools:gravity="center" />
|
|
||||||
|
|
||||||
<TableLayout
|
|
||||||
android:id="@+id/callStatsVideo"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="left|center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:paddingRight="5dp"
|
|
||||||
android:paddingBottom="10dp">
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/codec_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_codec" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/encoder_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_encoder_name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/decoder_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_decoder_name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/display_filter"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_decoder_name" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/uploadBandwith_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_upload" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/downloadBandwith_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_download" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/estimatedDownloadBandwidth_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_estimated_download" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/ice_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_ice" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/ip_video"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_ip" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/senderLossRateVideo"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_sender_loss_rate" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/receiverLossRateVideo"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_receiver_loss_rate" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_resolution_sent"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_video_resolution_sent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_resolution_received"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_video_resolution_received" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_fps_sent"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_video_fps_sent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/video_fps_received"
|
|
||||||
style="@style/call_stats_font"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingLeft="5dp"
|
|
||||||
android:text="@string/call_stats_video_fps_received" />
|
|
||||||
|
|
||||||
</TableLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
294
app/src/main/res/layout/call_stats_child.xml
Normal file
294
app/src/main/res/layout/call_stats_child.xml
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_audio"
|
||||||
|
style="@style/call_stats_title_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical|center"
|
||||||
|
android:text="@string/call_stats_audio"
|
||||||
|
tools:gravity="center" />
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:id="@+id/callStatsAudio"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_sip_adress"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/codec_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_codec" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/encoder_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_encoder_name" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/decoder_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uploadBandwith_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_upload" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/downloadBandwith_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_download" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ice_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ice" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ip_audio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/senderLossRateAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_sender_loss_rate" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/receiverLossRateAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_receiver_loss_rate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/jitterBufferAudio"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_jitter_buffer" />
|
||||||
|
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/call_stats_video"
|
||||||
|
style="@style/call_stats_title_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical|center"
|
||||||
|
android:text="@string/call_stats_video"
|
||||||
|
tools:gravity="center" />
|
||||||
|
|
||||||
|
<TableLayout
|
||||||
|
android:id="@+id/callStatsVideo"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left|center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/codec_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_codec" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/encoder_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_encoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/decoder_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/display_filter"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_decoder_name" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/uploadBandwith_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_upload" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/downloadBandwith_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_download" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/estimatedDownloadBandwidth_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_estimated_download" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ice_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ice" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/ip_video"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_ip" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/senderLossRateVideo"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_sender_loss_rate" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/receiverLossRateVideo"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_receiver_loss_rate" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_resolution_sent"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_resolution_sent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_resolution_received"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_resolution_received" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_fps_sent"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_fps_sent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/video_fps_received"
|
||||||
|
style="@style/call_stats_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:text="@string/call_stats_video_fps_received" />
|
||||||
|
|
||||||
|
</TableLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
55
app/src/main/res/layout/call_stats_group.xml
Normal file
55
app/src/main/res/layout/call_stats_group.xml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<include layout="@layout/contact_avatar" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="5dp"
|
||||||
|
android:layout_toLeftOf="@+id/dropdown"
|
||||||
|
android:layout_toRightOf="@id/avatar"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<org.linphone.views.MarqueeTextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
style="@style/contact_name_list_cell_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true" />
|
||||||
|
|
||||||
|
<org.linphone.views.MarqueeTextView
|
||||||
|
android:id="@+id/sipUri"
|
||||||
|
style="@style/sip_uri_small_font"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@id/dropdown"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:src="@drawable/chevron_list_close"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
Loading…
Reference in a new issue