content: package io.agora.openlive.activities;
  
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.os.Bundle;
  import android.view.SurfaceView;
  import android.view.View;
  import android.widget.ImageView;
  import android.widget.RelativeLayout;
  import android.widget.TextView;
  
  import androidx.core.graphics.drawable.RoundedBitmapDrawable;
  import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
  
  import io.agora.openlive.R;
  import io.agora.openlive.stats.LocalStatsData;
  import io.agora.openlive.stats.RemoteStatsData;
  import io.agora.openlive.stats.StatsData;
  import io.agora.openlive.ui.VideoGridContainer;
  import io.agora.rtc.Constants;
  import io.agora.rtc.IRtcEngineEventHandler;
  import io.agora.rtc.video.BeautyOptions;
  import io.agora.rtc.video.VideoEncoderConfiguration;
  
  public class LiveActivity extends RtcBaseActivity {
      private static final String TAG = LiveActivity.class.getSimpleName();
  
      private VideoGridContainer mVideoGridContainer;
      private ImageView mMuteAudioBtn;
      private ImageView mMuteVideoBtn;
  
      private VideoEncoderConfiguration.VideoDimensions mVideoDimension;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_live_room);
          initUI();
          initData();
      }
  
      private void initUI() {
          TextView roomName = findViewById(R.id.live_room_name);
          roomName.setText(config().getChannelName());
          roomName.setSelected(true);
          
          initUserIcon();
          int role = getIntent().getIntExtra(
                  io.agora.openlive.Constants.KEY_CLIENT_ROLE,
                  Constants.CLIENT_ROLE_AUDIENCE);
          boolean isBroadcaster =  (role == Constants.CLIENT_ROLE_BROADCASTER);
  
          mMuteVideoBtn = findViewById(R.id.live_btn_mute_video);
          mMuteVideoBtn.setActivated(isBroadcaster);
  
          mMuteAudioBtn = findViewById(R.id.live_btn_mute_audio);
          mMuteAudioBtn.setActivated(isBroadcaster);
  
          ImageView beautyBtn = findViewById(R.id.live_btn_beautification);
          beautyBtn.setActivated(true);
          rtcEngine().setBeautyEffectOptions(beautyBtn.isActivated(),
                  new BeautyOptions());
  
          mVideoGridContainer = findViewById(R.id.live_video_grid_layout);
          mVideoGridContainer.setStatsManager(statsManager());
  
          rtcEngine().setClientRole(role);
          if (isBroadcaster) startBroadcast();
      }
  
      private void initUserIcon() {
          Bitmap origin = BitmapFactory.decodeResource(getResources(), R.drawable.fake_user_icon);
          RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(), origin);
          drawable.setCircular(true);
          ImageView iconView = findViewById(R.id.live_name_board_icon);
          iconView.setImageDrawable(drawable);
      }
  
      private void initData() {
          mVideoDimension = io.agora.openlive.Constants.VIDEO_DIMENSIONS[
                  config().getVideoDimenIndex()];
      }
  
      @Override
      protected void onGlobalLayoutCompleted() {
          RelativeLayout topLayout = findViewById(R.id.live_room_top_layout);
          RelativeLayout.LayoutParams params =
                  (RelativeLayout.LayoutParams) topLayout.getLayoutParams();
          params.height = mStatusBarHeight + topLayout.getMeasuredHeight();
          topLayout.setLayoutParams(params);
          topLayout.setPadding(0, mStatusBarHeight, 0, 0);
      }
  
      private void startBroadcast() {
          rtcEngine().setClientRole(Constants.CLIENT_ROLE_BROADCASTER);
          SurfaceView surface = prepareRtcVideo(0, true);
          mVideoGridContainer.addUserVideoSurface(0, surface, true);
          mMuteAudioBtn.setActivated(true);
      }
  
      private void stopBroadcast() {
          rtcEngine().setClientRole(Constants.CLIENT_ROLE_AUDIENCE);
          removeRtcVideo(0, true);
          mVideoGridContainer.removeUserVideo(0, true);
          mMuteAudioBtn.setActivated(false);
      }
  
      @Override
      public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
          // Do nothing at the moment
      }
  
      @Override
      public void onUserJoined(int uid, int elapsed) {
          // Do nothing at the moment
      }
  
      @Override
      public void onUserOffline(final int uid, int reason) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  removeRemoteUser(uid);
              }
          });
      }
  
      @Override
      public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  renderRemoteUser(uid);
              }
          });
      }
  
      private void renderRemoteUser(int uid) {
          SurfaceView surface = prepareRtcVideo(uid, false);
          mVideoGridContainer.addUserVideoSurface(uid, surface, false);
      }
  
      private void removeRemoteUser(int uid) {
          removeRtcVideo(uid, false);
          mVideoGridContainer.removeUserVideo(uid, false);
      }
  
      @Override
      public void onLocalVideoStats(IRtcEngineEventHandler.LocalVideoStats stats) {
          if (!statsManager().isEnabled()) return;
  
          LocalStatsData data = (LocalStatsData) statsManager().getStatsData(0);
          if (data == null) return;
  
          data.setWidth(mVideoDimension.width);
          data.setHeight(mVideoDimension.height);
          data.setFramerate(stats.sentFrameRate);
      }
  
      @Override
      public void onRtcStats(IRtcEngineEventHandler.RtcStats stats) {
          if (!statsManager().isEnabled()) return;
  
          LocalStatsData data = (LocalStatsData) statsManager().getStatsData(0);
          if (data == null) return;
  
          data.setLastMileDelay(stats.lastmileDelay);
          data.setVideoSendBitrate(stats.txVideoKBitRate);
          data.setVideoRecvBitrate(stats.rxVideoKBitRate);
          data.setAudioSendBitrate(stats.txAudioKBitRate);
          data.setAudioRecvBitrate(stats.rxAudioKBitRate);
          data.setCpuApp(stats.cpuAppUsage);
          data.setCpuTotal(stats.cpuAppUsage);
          data.setSendLoss(stats.txPacketLossRate);
          data.setRecvLoss(stats.rxPacketLossRate);
      }
  
      @Override
      public void onNetworkQuality(int uid, int txQuality, int rxQuality) {
          if (!statsManager().isEnabled()) return;
  
          StatsData data = statsManager().getStatsData(uid);
          if (data == null) return;
  
          data.setSendQuality(statsManager().qualityToString(txQuality));
          data.setRecvQuality(statsManager().qualityToString(rxQuality));
      }
  
      @Override
      public void onRemoteVideoStats(IRtcEngineEventHandler.RemoteVideoStats stats) {
          if (!statsManager().isEnabled()) return;
  
          RemoteStatsData data = (RemoteStatsData) statsManager().getStatsData(stats.uid);
          if (data == null) return;
  
          data.setWidth(stats.width);
          data.setHeight(stats.height);
          data.setFramerate(stats.rendererOutputFrameRate);
          data.setVideoDelay(stats.delay);
      }
  
      @Override
      public void onRemoteAudioStats(IRtcEngineEventHandler.RemoteAudioStats stats) {
          if (!statsManager().isEnabled()) return;
  
          RemoteStatsData data = (RemoteStatsData) statsManager().getStatsData(stats.uid);
          if (data == null) return;
  
          data.setAudioNetDelay(stats.networkTransportDelay);
          data.setAudioNetJitter(stats.jitterBufferDelay);
          data.setAudioLoss(stats.audioLossRate);
          data.setAudioQuality(statsManager().qualityToString(stats.quality));
      }
  
      @Override
      public void finish() {
          super.finish();
          statsManager().clearAllData();
      }
  
      public void onLeaveClicked(View view) {
          finish();
      }
  
      public void onSwitchCameraClicked(View view) {
          rtcEngine().switchCamera();
      }
  
      public void onBeautyClicked(View view) {
          view.setActivated(!view.isActivated());
          rtcEngine().setBeautyEffectOptions(view.isActivated(),
                  new BeautyOptions());
      }
  
      public void onMoreClicked(View view) {
          // Do nothing at the moment
      }
  
      public void onPushStreamClicked(View view) {
          // Do nothing at the moment
      }
  
      public void onMuteAudioClicked(View view) {
          if (!mMuteVideoBtn.isActivated()) return;
  
          rtcEngine().muteLocalAudioStream(view.isActivated());
          view.setActivated(!view.isActivated());
      }
  
      public void onMuteVideoClicked(View view) {
          if (view.isActivated()) {
              stopBroadcast();
          } else {
              startBroadcast();
          }
          view.setActivated(!view.isActivated());
      }
  }
  