• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.feedbackconsent;
18 
19 import static com.android.tv.feedbackconsent.TvFeedbackConstants.BUGREPORT_CONSENT;
20 import static com.android.tv.feedbackconsent.TvFeedbackConstants.BUGREPORT_REQUESTED;
21 import static com.android.tv.feedbackconsent.TvFeedbackConstants.BUGREPORT_TOGGLE_ON_BY_DEFAULT;
22 import static com.android.tv.feedbackconsent.TvFeedbackConstants.CANCEL_REQUEST;
23 import static com.android.tv.feedbackconsent.TvFeedbackConstants.CONSENT_RECEIVER;
24 import static com.android.tv.feedbackconsent.TvFeedbackConstants.RESULT_CODE_OK;
25 import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_CONSENT;
26 import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_KEY;
27 import static com.android.tv.feedbackconsent.TvFeedbackConstants.SYSTEM_LOGS_REQUESTED;
28 
29 import android.os.Bundle;
30 import android.os.ResultReceiver;
31 import android.util.Log;
32 import android.app.Activity;
33 import android.content.Intent;
34 import android.view.View;
35 import android.widget.Switch;
36 import android.widget.TextView;
37 import android.widget.Toast;
38 
39 import java.time.LocalDateTime;
40 import java.time.ZoneId;
41 import java.time.format.DateTimeFormatter;
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.List;
45 import java.util.Locale;
46 
47 public class TvFeedbackConsentActivity extends Activity implements
48         TvFeedbackConsentDataCollector.TvFeedbackConsentDataCollectorCallback {
49 
50     private static final String TAG = TvFeedbackConsentActivity.class.getSimpleName();
51 
52     private static final String DATE_PATTERN = "MM/dd/yyyy, hh:mm a";
53     private static ResultReceiver resultReceiver;
54     private boolean systemLogRequested;
55     private boolean bugreportRequested;
56     private boolean setBugreportSwitchOnByDefault;
57     private boolean sendLogs;
58     private boolean sendBugreport;
59     private boolean cancelRequest;
60 
61     private static final List<String> systemLogsLoadingText = Collections.singletonList(
62             "Loading, please wait.....");
63     TvFeedbackConsentInformationDialog viewLogsDialog;
64     private TvFeedbackConsentDataCollector tvFeedbackDataCollector;
65 
66     @Override
onCreate(Bundle savedInstanceState)67     public void onCreate(Bundle savedInstanceState) {
68         super.onCreate(savedInstanceState);
69         Intent intent = getIntent();
70         systemLogRequested = intent.getBooleanExtra(SYSTEM_LOGS_REQUESTED, false);
71         bugreportRequested = intent.getBooleanExtra(BUGREPORT_REQUESTED, false);
72         setBugreportSwitchOnByDefault =
73             intent.getBooleanExtra(BUGREPORT_TOGGLE_ON_BY_DEFAULT, false);
74 
75         if (!systemLogRequested && !bugreportRequested) {
76             Log.e(TAG, "Consent screen requested without requesting any data.");
77             this.onStop();
78         }
79         setContentView(R.layout.tv_feedback_consent);
80         onViewCreated();
81     }
82 
83     @Override
onResume()84     public void onResume() {
85         super.onResume();
86         Intent intent = getIntent();
87         resultReceiver = intent.getParcelableExtra(CONSENT_RECEIVER, ResultReceiver.class);
88         tvFeedbackDataCollector = new TvFeedbackConsentDataCollector(this);
89         tvFeedbackDataCollector.collectSystemLogs(/* numLines= */ 10000);
90     }
91 
onViewCreated()92     private void onViewCreated() {
93         View sendFeedbackButton = requireViewById(R.id.send_feedback_button);
94         sendFeedbackButton.setOnClickListener(this::onSendFeedbackButtonClicked);
95         sendFeedbackButton.requestFocus();
96 
97         View cancelFeedbackButton = requireViewById(R.id.cancel_feedback_button);
98         cancelFeedbackButton.setOnClickListener(this::onCancelFeedbackButtonClicked);
99 
100 
101         if (systemLogRequested) {
102             View systemLogsRow = requireViewById(R.id.system_logs_row);
103             systemLogsRow.setVisibility(View.VISIBLE);
104             View systemLogsSwitch = requireViewById(R.id.system_logs_switch);
105             systemLogsSwitch.setOnFocusChangeListener(
106                     (v, focused) -> systemLogsRow.setSelected(focused));
107             prepareSystemLogsDialog();
108         }
109 
110         if (bugreportRequested) {
111             View bugreportRow = requireViewById(R.id.bugreport_row);
112             bugreportRow.setVisibility(View.VISIBLE);
113 
114             String dateTime = LocalDateTime.now(ZoneId.systemDefault()).format(
115                 DateTimeFormatter.ofPattern(DATE_PATTERN, Locale.US));
116             String formattedBugreportLegalText = getString(
117                 R.string.feedback_bugreport_legal_display_text, dateTime);
118             TextView bugreportLegalTextView = requireViewById(R.id.bugreport_legal_text);
119             bugreportLegalTextView.setText(formattedBugreportLegalText);
120 
121             Switch bugreportSwitch = requireViewById(R.id.bugreport_switch);
122             bugreportSwitch = requireViewById(R.id.bugreport_switch);
123             if (setBugreportSwitchOnByDefault) {
124                 bugreportSwitch.setChecked(true);
125             }
126             bugreportSwitch.setOnFocusChangeListener(
127                 (v, focused) -> bugreportRow.setSelected(focused));
128         }
129     }
130 
prepareSystemLogsDialog()131     private void prepareSystemLogsDialog() {
132         viewLogsDialog = new TvFeedbackConsentInformationDialog(
133                 TvFeedbackConsentActivity.this,
134                 R.style.ViewLogsDialogTheme,
135                 R.layout.view_system_logs_dialog,
136                 systemLogsLoadingText);
137         viewLogsDialog.create();
138 
139         View viewLogsButton = requireViewById(R.id.view_logs_button);
140         viewLogsButton.setOnClickListener((v) -> viewLogsDialog.show());
141         viewLogsButton.setVisibility(View.VISIBLE);
142 
143     }
144 
145     @Override
onSystemLogsReady()146     public void onSystemLogsReady() {
147         if (!systemLogRequested || tvFeedbackDataCollector == null || viewLogsDialog == null) {
148             return;
149         }
150         List<String> systemLogs = tvFeedbackDataCollector.getSystemLogs();
151         viewLogsDialog.updateRecyclerView(systemLogs);
152     }
153 
onSendFeedbackButtonClicked(View view)154     private void onSendFeedbackButtonClicked(View view) {
155         sendLogs = ((Switch) requireViewById(R.id.system_logs_switch)).isChecked();
156         sendBugreport = ((Switch) requireViewById(R.id.bugreport_switch)).isChecked();
157 
158         Toast.makeText(view.getContext(),
159                 view.getContext().getString(R.string.feedback_submitted_notification),
160                 Toast.LENGTH_SHORT)
161             .show();
162         finish();
163     }
164 
onCancelFeedbackButtonClicked(View view)165     private void onCancelFeedbackButtonClicked(View view) {
166         sendLogs = false;
167         sendBugreport = false;
168         cancelRequest = true;
169 
170         Toast.makeText(view.getContext(),
171                 view.getContext().getString(R.string.feedback_cancelled_notification),
172                 Toast.LENGTH_SHORT)
173             .show();
174         finish();
175     }
176 
sendResult()177     private void sendResult() {
178         if (resultReceiver == null) {
179             Log.w(TAG, "Activity intent does not contain a result receiver");
180             return;
181         }
182         Bundle bundle = new Bundle();
183         bundle.putSerializable(SYSTEM_LOGS_CONSENT, sendLogs);
184         bundle.putSerializable(BUGREPORT_CONSENT, sendBugreport);
185         bundle.putSerializable(CANCEL_REQUEST, cancelRequest);
186         if (systemLogRequested && sendLogs) {
187             bundle.putStringArrayList(SYSTEM_LOGS_KEY,
188                     new ArrayList<>(tvFeedbackDataCollector.getSystemLogs()));
189         }
190 
191         try {
192             resultReceiver.send(RESULT_CODE_OK, bundle);
193         } catch (Exception e) {
194             Log.e(TAG, "Exception in sending result: ", e);
195         }
196     }
197 
198     @Override
onStop()199     public void onStop() {
200         sendResult();
201         super.onStop();
202     }
203 }