• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 package com.android.settings.accessibility;
17 
18 import android.app.Activity;
19 import android.content.Intent;
20 import android.text.TextUtils;
21 
22 import androidx.annotation.Nullable;
23 import androidx.annotation.VisibleForTesting;
24 
25 import com.android.server.accessibility.Flags;
26 import com.android.settings.overlay.FeatureFactory;
27 import com.android.settingslib.DeviceInfoUtils;
28 
29 import java.lang.ref.WeakReference;
30 
31 /**
32  * Manages the feedback flow. This class is responsible for checking feedback availability and
33  * sending feedback. Uses a WeakReference to the Activity to prevent memory leaks.
34  */
35 public class FeedbackManager {
36 
37     static final String CATEGORY_TAG = "category_tag";
38     private static final int FEEDBACK_INTENT_RESULT_CODE = 0;
39 
40     private final WeakReference<Activity> mActivityWeakReference;
41     @Nullable private final String mReporterPackage;
42     @Nullable private final String mCategoryTag;
43 
44     /**
45      * Constructs a new FeedbackManager.
46      *
47      * @param activity The activity context. A WeakReference is used to prevent memory leaks.
48      * @param pageId The unique identifier of the page associated with the feedback.
49      */
FeedbackManager(@ullable Activity activity, int pageId)50     public FeedbackManager(@Nullable Activity activity, int pageId) {
51         this(activity,
52                 DeviceInfoUtils.getFeedbackReporterPackage(activity),
53                 FeatureFactory.getFeatureFactory()
54                         .getAccessibilityFeedbackFeatureProvider()
55                         .getCategory(pageId));
56     }
57 
58     /**
59      * Constructs a new FeedbackManager. This constructor is visible for testing.
60      *
61      * @param activity The activity context. A WeakReference is used to prevent memory leaks.
62      * @param reporterPackage The package name of the feedback reporter.
63      * @param category The feedback bucket ID.
64      */
65     @VisibleForTesting
FeedbackManager(@ullable Activity activity, @Nullable String reporterPackage, @Nullable String category)66     public FeedbackManager(@Nullable Activity activity, @Nullable String reporterPackage,
67             @Nullable String category) {
68         this.mActivityWeakReference = new WeakReference<>(activity);
69         this.mReporterPackage = reporterPackage;
70         this.mCategoryTag = category;
71     }
72 
73     /**
74      * Checks if feedback is available on the device.
75      *
76      * @return {@code true} if feedback is available, {@code false} otherwise.
77      */
isAvailable()78     public boolean isAvailable() {
79         if (!Flags.enableLowVisionGenericFeedback()) {
80             return false;
81         }
82 
83         return !TextUtils.isEmpty(mReporterPackage)
84                 && !TextUtils.isEmpty(mCategoryTag)
85                 && mActivityWeakReference.get() != null;
86     }
87 
88     /**
89      * Sends feedback using the available feedback reporter. This will start the feedback
90      * activity. It is the responsibility of the calling activity to handle the result
91      * code {@link #FEEDBACK_INTENT_RESULT_CODE} if necessary.
92      *
93      * @return {@code true} if the feedback intent was successfully started, {@code false}
94      * otherwise.
95      */
sendFeedback()96     public boolean sendFeedback() {
97         Activity activity = mActivityWeakReference.get();
98         if (!isAvailable() || activity == null) {
99             return false;
100         }
101 
102         final Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
103         intent.setPackage(mReporterPackage);
104         intent.putExtra(CATEGORY_TAG, mCategoryTag);
105         activity.startActivityForResult(intent, FEEDBACK_INTENT_RESULT_CODE);
106         return true;
107     }
108 }
109