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
|
||||
- Permissions issues
|
||||
- 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.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.Arrays;
|
||||
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.Core;
|
||||
import org.linphone.core.PayloadType;
|
||||
import org.linphone.core.StreamType;
|
||||
import org.linphone.core.tools.Log;
|
||||
import org.linphone.core.CoreListenerStub;
|
||||
|
||||
public class CallStatsFragment extends Fragment {
|
||||
private final Handler mHandler = new Handler();
|
||||
private Timer mTimer;
|
||||
private TimerTask mTask;
|
||||
|
||||
private View mView;
|
||||
private DrawerLayout mSideMenu;
|
||||
private RelativeLayout mSideMenuContent;
|
||||
|
||||
private HashMap<String, String> mEncoderTexts;
|
||||
private HashMap<String, String> mDecoderTexts;
|
||||
|
||||
private Call mCall;
|
||||
private CallListenerStub mListener;
|
||||
private RelativeLayout mSideMenuContent;;
|
||||
private ExpandableListView mExpandableList;
|
||||
private CallStatsAdapter mAdapter;
|
||||
private CoreListenerStub mListener;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(
|
||||
LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.call_stats, container, false);
|
||||
mView = view;
|
||||
|
||||
mEncoderTexts = new HashMap<>();
|
||||
mDecoderTexts = new HashMap<>();
|
||||
mExpandableList = view.findViewById(R.id.devices_list);
|
||||
|
||||
mListener =
|
||||
new CallListenerStub() {
|
||||
public void onStateChanged(Call call, Call.State cstate, String message) {
|
||||
new CoreListenerStub() {
|
||||
@Override
|
||||
public void onCallStateChanged(
|
||||
Core lc, Call call, Call.State cstate, String message) {
|
||||
if (cstate == Call.State.End || cstate == Call.State.Error) {
|
||||
if (mTimer != null) {
|
||||
Log.i(
|
||||
"[Call Stats] Call is terminated, stopping mCountDownTimer in charge of stats refreshing.");
|
||||
mTimer.cancel();
|
||||
}
|
||||
mAdapter.updateListItems(
|
||||
Arrays.asList(LinphoneManager.getCore().getCalls()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
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
|
||||
public void onPause() {
|
||||
setCall(null);
|
||||
super.onPause();
|
||||
LinphoneManager.getCore().removeListener(mListener);
|
||||
}
|
||||
|
||||
public void setDrawer(DrawerLayout drawer, RelativeLayout content) {
|
||||
|
@ -131,294 +119,4 @@ public class CallStatsFragment extends Fragment {
|
|||
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"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<ExpandableListView
|
||||
android:id="@+id/devices_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent"
|
||||
android:divider="?attr/dividerColor"
|
||||
android:childDivider="?attr/dividerColor"
|
||||
android:dividerHeight="1dp"
|
||||
android:groupIndicator="@null" />
|
||||
|
||||
<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_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>
|
||||
</RelativeLayout>
|
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