/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.tv.feedbackconsent; import static com.android.tv.feedbackconsent.TvFeedbackConstants.BUGREPORT_CONSENT; import static com.android.tv.feedbackconsent.TvFeedbackConstants.BUGREPORT_REQUESTED; import static com.android.tv.feedbackconsent.TvFeedbackConstants.CANCEL_REQUEST; import static com.android.tv.feedbackconsent.TvFeedbackConstants.CONSENT_RECEIVER; import static com.android.tv.feedbackconsent.TvFeedbackConstants.RESULT_CODE_OK; import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_CONSENT; import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_KEY; import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_REQUESTED; import android.os.Bundle; import android.os.ResultReceiver; import android.util.Log; import android.app.Activity; import android.content.Intent; import android.view.View; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; public class TvFeedbackConsentActivity extends Activity implements TvFeedbackConsentDataCollector.TvFeedbackConsentDataCollectorCallback { private static final String TAG = TvFeedbackConsentActivity.class.getSimpleName(); private static final String DATE_PATTERN = "MM/dd/yyyy, hh:mm a"; private static ResultReceiver resultReceiver; private boolean systemLogRequested; private boolean bugreportRequested; private boolean sendLogs; private boolean sendBugreport; private boolean cancelRequest; private static final List systemLogsLoadingText = Collections.singletonList( "Loading, please wait....."); TvFeedbackConsentInformationDialog viewLogsDialog; private TvFeedbackConsentDataCollector tvFeedbackDataCollector; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); systemLogRequested = intent.getBooleanExtra(SYSTEM_LOGS_REQUESTED, false); bugreportRequested = intent.getBooleanExtra(BUGREPORT_REQUESTED, false); if (!systemLogRequested && !bugreportRequested) { Log.e(TAG, "Consent screen requested without requesting any data."); this.onStop(); } setContentView(R.layout.tv_feedback_consent); onViewCreated(); } @Override public void onResume() { super.onResume(); Intent intent = getIntent(); resultReceiver = intent.getParcelableExtra(CONSENT_RECEIVER, ResultReceiver.class); tvFeedbackDataCollector = new TvFeedbackConsentDataCollector(this); tvFeedbackDataCollector.collectSystemLogs(/* numLines= */ 10000); } private void onViewCreated() { View sendFeedbackButton = requireViewById(R.id.send_feedback_button); sendFeedbackButton.setOnClickListener(this::onSendFeedbackButtonClicked); sendFeedbackButton.requestFocus(); View cancelFeedbackButton = requireViewById(R.id.cancel_feedback_button); cancelFeedbackButton.setOnClickListener(this::onCancelFeedbackButtonClicked); if (systemLogRequested) { View systemLogsRow = requireViewById(R.id.system_logs_row); systemLogsRow.setVisibility(View.VISIBLE); View systemLogsSwitch = requireViewById(R.id.system_logs_switch); systemLogsSwitch.setOnFocusChangeListener( (v, focused) -> systemLogsRow.setSelected(focused)); prepareSystemLogsDialog(); } if (bugreportRequested) { View bugreportRow = requireViewById(R.id.bugreport_row); bugreportRow.setVisibility(View.VISIBLE); String dateTime = LocalDateTime.now(ZoneId.systemDefault()).format( DateTimeFormatter.ofPattern(DATE_PATTERN, Locale.US)); String formattedBugreportLegalText = getString( R.string.feedback_bugreport_legal_display_text, dateTime); TextView bugreportLegalTextView = requireViewById(R.id.bugreport_legal_text); bugreportLegalTextView.setText(formattedBugreportLegalText); View bugreportSwitch = requireViewById(R.id.bugreport_switch); bugreportSwitch.setOnFocusChangeListener( (v, focused) -> bugreportRow.setSelected(focused)); } } private void prepareSystemLogsDialog() { viewLogsDialog = new TvFeedbackConsentInformationDialog( TvFeedbackConsentActivity.this, R.style.ViewLogsDialogTheme, R.layout.view_system_logs_dialog, systemLogsLoadingText); viewLogsDialog.create(); View viewLogsButton = requireViewById(R.id.view_logs_button); viewLogsButton.setOnClickListener((v) -> viewLogsDialog.show()); viewLogsButton.setVisibility(View.VISIBLE); } @Override public void onSystemLogsReady() { if (!systemLogRequested || tvFeedbackDataCollector == null || viewLogsDialog == null) { return; } List systemLogs = tvFeedbackDataCollector.getSystemLogs(); viewLogsDialog.updateRecyclerView(systemLogs); } private void onSendFeedbackButtonClicked(View view) { sendLogs = ((Switch) requireViewById(R.id.system_logs_switch)).isChecked(); sendBugreport = ((Switch) requireViewById(R.id.bugreport_switch)).isChecked(); Toast.makeText(view.getContext(), view.getContext().getString(R.string.feedback_submitted_notification), Toast.LENGTH_SHORT) .show(); finish(); } private void onCancelFeedbackButtonClicked(View view) { sendLogs = false; sendBugreport = false; cancelRequest = true; Toast.makeText(view.getContext(), view.getContext().getString(R.string.feedback_cancelled_notification), Toast.LENGTH_SHORT) .show(); finish(); } private void sendResult() { if (resultReceiver == null) { Log.w(TAG, "Activity intent does not contain a result receiver"); return; } Bundle bundle = new Bundle(); bundle.putSerializable(SYSTEM_LOGS_CONSENT, sendLogs); bundle.putSerializable(BUGREPORT_CONSENT, sendBugreport); bundle.putSerializable(CANCEL_REQUEST, cancelRequest); if (systemLogRequested && sendLogs) { bundle.putStringArrayList(SYSTEM_LOGS_KEY, new ArrayList<>(tvFeedbackDataCollector.getSystemLogs())); } try { resultReceiver.send(RESULT_CODE_OK, bundle); } catch (Exception e) { Log.e(TAG, "Exception in sending result: ", e); } } @Override public void onStop() { sendResult(); super.onStop(); } }