Screen overlay warning: remove ability to query and remember allowed apps for API 30+

as we can't query all installed apps anymore when targeting API 30
This commit is contained in:
Torsten Grote
2020-12-14 10:53:12 -03:00
parent 04485e58da
commit e6f66ebc95
6 changed files with 48 additions and 11 deletions

View File

@@ -198,7 +198,10 @@ public class AppModule {
ScreenFilterMonitor provideScreenFilterMonitor( ScreenFilterMonitor provideScreenFilterMonitor(
LifecycleManager lifecycleManager, LifecycleManager lifecycleManager,
ScreenFilterMonitorImpl screenFilterMonitor) { ScreenFilterMonitorImpl screenFilterMonitor) {
lifecycleManager.registerService(screenFilterMonitor); if (SDK_INT <= 29) {
// this keeps track of installed apps and does not work on API 30+
lifecycleManager.registerService(screenFilterMonitor);
}
return screenFilterMonitor; return screenFilterMonitor;
} }

View File

@@ -58,7 +58,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
Logger.getLogger(ScreenFilterMonitorImpl.class.getName()); Logger.getLogger(ScreenFilterMonitorImpl.class.getName());
/* /*
* Ignore Play Services if it uses this package name and public key - it's * Ignore Play Services if it uses this package name and public key - it's
* effectively a system app, but not flagged as such on older systems * effectively a system app, but not flagged as such on older systems
*/ */
private static final String PLAY_SERVICES_PACKAGE = private static final String PLAY_SERVICES_PACKAGE =
@@ -108,7 +108,7 @@ class ScreenFilterMonitorImpl implements ScreenFilterMonitor, Service {
Set<String> allowed = prefs.getStringSet(PREF_KEY_ALLOWED, Set<String> allowed = prefs.getStringSet(PREF_KEY_ALLOWED,
Collections.emptySet()); Collections.emptySet());
List<AppDetails> apps = new ArrayList<>(); List<AppDetails> apps = new ArrayList<>();
List<PackageInfo> packageInfos = @SuppressLint("QueryPermissionsNeeded") List<PackageInfo> packageInfos =
pm.getInstalledPackages(GET_PERMISSIONS); pm.getInstalledPackages(GET_PERMISSIONS);
for (PackageInfo packageInfo : packageInfos) { for (PackageInfo packageInfo : packageInfos) {
if (!allowed.contains(packageInfo.packageName) if (!allowed.contains(packageInfo.packageName)

View File

@@ -39,9 +39,11 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static androidx.lifecycle.Lifecycle.State.STARTED; import static androidx.lifecycle.Lifecycle.State.STARTED;
import static java.util.Collections.emptyList;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS; import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
@@ -201,9 +203,15 @@ public abstract class BaseActivity extends AppCompatActivity
// If the dialog is already visible, filter the tap // If the dialog is already visible, filter the tap
ScreenFilterDialogFragment f = findDialogFragment(); ScreenFilterDialogFragment f = findDialogFragment();
if (f != null && f.isVisible()) return false; if (f != null && f.isVisible()) return false;
Collection<AppDetails> apps = screenFilterMonitor.getApps(); Collection<AppDetails> apps;
// If all overlay apps have been allowed, allow the tap // querying all apps is only possible at API 29 and below
if (apps.isEmpty()) return true; if (SDK_INT <= 29) {
apps = screenFilterMonitor.getApps();
// If all overlay apps have been allowed, allow the tap
if (apps.isEmpty()) return true;
} else {
apps = emptyList();
}
// Show dialog unless onSaveInstanceState() has been called, see #1112 // Show dialog unless onSaveInstanceState() has been called, see #1112
FragmentManager fm = getSupportFragmentManager(); FragmentManager fm = getSupportFragmentManager();
if (!fm.isStateSaved()) { if (!fm.isStateSaved()) {
@@ -265,7 +273,12 @@ public abstract class BaseActivity extends AppCompatActivity
private void protectToolbar() { private void protectToolbar() {
findToolbar(); findToolbar();
if (toolbar != null) { if (toolbar != null) {
boolean filter = !screenFilterMonitor.getApps().isEmpty(); boolean filter;
if (SDK_INT <= 29) {
filter = !screenFilterMonitor.getApps().isEmpty();
} else {
filter = true;
}
UiUtils.setFilterTouchesWhenObscured(toolbar, filter); UiUtils.setFilterTouchesWhenObscured(toolbar, filter);
} }
} }

View File

@@ -5,6 +5,7 @@ import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -28,6 +29,10 @@ import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import static android.os.Build.VERSION.SDK_INT;
import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
import static android.view.View.GONE;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class ScreenFilterDialogFragment extends DialogFragment { public class ScreenFilterDialogFragment extends DialogFragment {
@@ -37,7 +42,7 @@ public class ScreenFilterDialogFragment extends DialogFragment {
@Inject @Inject
ScreenFilterMonitor screenFilterMonitor; ScreenFilterMonitor screenFilterMonitor;
DismissListener dismissListener = null; private DismissListener dismissListener = null;
public static ScreenFilterDialogFragment newInstance( public static ScreenFilterDialogFragment newInstance(
Collection<AppDetails> apps) { Collection<AppDetails> apps) {
@@ -83,10 +88,20 @@ public class ScreenFilterDialogFragment extends DialogFragment {
View dialogView = inflater.inflate(R.layout.dialog_screen_filter, null); View dialogView = inflater.inflate(R.layout.dialog_screen_filter, null);
builder.setView(dialogView); builder.setView(dialogView);
TextView message = dialogView.findViewById(R.id.screen_filter_message); TextView message = dialogView.findViewById(R.id.screen_filter_message);
message.setText(getString(R.string.screen_filter_body,
TextUtils.join("\n", appNames)));
CheckBox allow = dialogView.findViewById(R.id.screen_filter_checkbox); CheckBox allow = dialogView.findViewById(R.id.screen_filter_checkbox);
builder.setNeutralButton(R.string.continue_button, (dialog, which) -> { if (SDK_INT <= 29) {
message.setText(getString(R.string.screen_filter_body,
TextUtils.join("\n", appNames)));
} else {
message.setText(R.string.screen_filter_body_api_30);
allow.setVisibility(GONE);
builder.setNeutralButton(R.string.screen_filter_review_apps,
(dialog, which) -> {
Intent i = new Intent(ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(i);
});
}
builder.setPositiveButton(R.string.continue_button, (dialog, which) -> {
if (allow.isChecked()) screenFilterMonitor.allowApps(packageNames); if (allow.isChecked()) screenFilterMonitor.allowApps(packageNames);
dialog.dismiss(); dialog.dismiss();
}); });

View File

@@ -14,6 +14,8 @@ public interface ScreenFilterMonitor {
* SYSTEM_ALERT_WINDOW permission, excluding system apps, Google Play * SYSTEM_ALERT_WINDOW permission, excluding system apps, Google Play
* Services, and any apps that have been allowed by calling * Services, and any apps that have been allowed by calling
* {@link #allowApps(Collection)}. * {@link #allowApps(Collection)}.
*
* Only works on SDK_INT 29 and below.
*/ */
@UiThread @UiThread
Collection<AppDetails> getApps(); Collection<AppDetails> getApps();
@@ -21,6 +23,8 @@ public interface ScreenFilterMonitor {
/** /**
* Allows the apps with the given package names to use overlay windows. * Allows the apps with the given package names to use overlay windows.
* They will not be returned by future calls to {@link #getApps()}. * They will not be returned by future calls to {@link #getApps()}.
*
* Only works on SDK_INT 29 and below.
*/ */
@UiThread @UiThread
void allowApps(Collection<String> packageNames); void allowApps(Collection<String> packageNames);

View File

@@ -590,7 +590,9 @@
<!-- Screen Filters & Tapjacking --> <!-- Screen Filters & Tapjacking -->
<string name="screen_filter_title">Screen overlay detected</string> <string name="screen_filter_title">Screen overlay detected</string>
<string name="screen_filter_body">Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nThe following apps might be drawing on top:\n\n%1$s</string> <string name="screen_filter_body">Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nThe following apps might be drawing on top:\n\n%1$s</string>
<string name="screen_filter_body_api_30">Another app is drawing on top of Briar. To protect your security, Briar will not respond to touches when another app is drawing on top.\n\nReview apps below to find the responsible app.</string>
<string name="screen_filter_allow">Allow these apps to draw on top</string> <string name="screen_filter_allow">Allow these apps to draw on top</string>
<string name="screen_filter_review_apps">Review apps</string>
<!-- Permission Requests --> <!-- Permission Requests -->
<string name="permission_camera_title">Camera permission</string> <string name="permission_camera_title">Camera permission</string>