mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Factor out power management UI code into library
This commit is contained in:
@@ -99,13 +99,14 @@ dependencies {
|
||||
implementation project(path: ':briar-core', configuration: 'default')
|
||||
implementation project(path: ':bramble-core', configuration: 'default')
|
||||
implementation project(':bramble-android')
|
||||
implementation project(':dont-kill-me-lib')
|
||||
|
||||
implementation 'androidx.fragment:fragment:1.3.4'
|
||||
implementation "androidx.fragment:fragment:$androidx_fragment_version"
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'androidx.exifinterface:exifinterface:1.3.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'com.google.android.material:material:1.3.0'
|
||||
implementation "androidx.constraintlayout:constraintlayout:$androidx_constraintlayout_version"
|
||||
implementation "com.google.android.material:material:$google_material_version"
|
||||
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
|
||||
|
||||
implementation 'info.guardianproject.panic:panic:1.0'
|
||||
|
||||
@@ -39,11 +39,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static java.lang.Thread.sleep;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.briar.android.OverlayTapViewAction.visualClick;
|
||||
import static org.briarproject.briar.android.ViewActions.waitFor;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
tools:ignore="ScopedStorage" />
|
||||
|
||||
<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
@@ -477,9 +476,6 @@
|
||||
|
||||
<queries>
|
||||
<package android:name="info.guardianproject.ripple" />
|
||||
<package android:name="com.huawei.systemmanager" />
|
||||
<package android:name="com.huawei.powergenie" />
|
||||
<package android:name="com.evenwell.PowerMonitor" />
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.system.ClockModule;
|
||||
import org.briarproject.briar.BriarCoreEagerSingletons;
|
||||
import org.briarproject.briar.BriarCoreModule;
|
||||
import org.briarproject.briar.android.account.DoNotKillMeFragment;
|
||||
import org.briarproject.briar.android.attachment.AttachmentModule;
|
||||
import org.briarproject.briar.android.attachment.media.MediaModule;
|
||||
import org.briarproject.briar.android.contact.connect.BluetoothIntroFragment;
|
||||
@@ -239,4 +240,6 @@ public interface AndroidComponent
|
||||
void inject(ReceiveFragment receiveFragment);
|
||||
|
||||
void inject(BluetoothIntroFragment bluetoothIntroFragment);
|
||||
|
||||
void inject(DoNotKillMeFragment dozeFragment);
|
||||
}
|
||||
|
||||
@@ -1,57 +1,16 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.AbstractDozeWatchdogImpl;
|
||||
import org.briarproject.bramble.api.lifecycle.Service;
|
||||
import org.briarproject.bramble.api.lifecycle.ServiceException;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
|
||||
|
||||
class DozeWatchdogImpl implements DozeWatchdog, Service {
|
||||
|
||||
private final Context appContext;
|
||||
private final AtomicBoolean dozed = new AtomicBoolean(false);
|
||||
private final BroadcastReceiver receiver = new DozeBroadcastReceiver();
|
||||
class DozeWatchdogImpl extends AbstractDozeWatchdogImpl
|
||||
implements DozeWatchdog, Service {
|
||||
|
||||
DozeWatchdogImpl(Context appContext) {
|
||||
this.appContext = appContext;
|
||||
super(appContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAndResetDozeFlag() {
|
||||
return dozed.getAndSet(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startService() throws ServiceException {
|
||||
if (SDK_INT < 23) return;
|
||||
IntentFilter filter = new IntentFilter(ACTION_DEVICE_IDLE_MODE_CHANGED);
|
||||
appContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopService() throws ServiceException {
|
||||
if (SDK_INT < 23) return;
|
||||
appContext.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
private class DozeBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (SDK_INT < 23) return;
|
||||
PowerManager pm =
|
||||
(PowerManager) appContext.getSystemService(POWER_SERVICE);
|
||||
if (pm.isDeviceIdleMode()) dozed.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.AbstractDoNotKillMeFragment;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class DoNotKillMeFragment extends AbstractDoNotKillMeFragment {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
SetupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
FragmentActivity activity = requireActivity();
|
||||
getAndroidComponent(activity).inject(this);
|
||||
viewModel = new ViewModelProvider(activity, viewModelFactory)
|
||||
.get(SetupViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClicked() {
|
||||
viewModel.dozeExceptionConfirmed();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.account.PowerView.OnCheckedChangedListener;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class DozeFragment extends SetupFragment
|
||||
implements OnCheckedChangedListener {
|
||||
|
||||
private final static String TAG = DozeFragment.class.getName();
|
||||
|
||||
private DozeView dozeView;
|
||||
private HuaweiProtectedAppsView huaweiProtectedAppsView;
|
||||
private HuaweiAppLaunchView huaweiAppLaunchView;
|
||||
private XiaomiView xiaomiView;
|
||||
private Button next;
|
||||
private boolean secondAttempt = false;
|
||||
|
||||
public static DozeFragment newInstance() {
|
||||
return new DozeFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
requireActivity().setTitle(getString(R.string.setup_doze_title));
|
||||
setHasOptionsMenu(false);
|
||||
View v = inflater.inflate(R.layout.fragment_setup_doze, container,
|
||||
false);
|
||||
dozeView = v.findViewById(R.id.dozeView);
|
||||
dozeView.setOnCheckedChangedListener(this);
|
||||
huaweiProtectedAppsView = v.findViewById(R.id.huaweiProtectedAppsView);
|
||||
huaweiProtectedAppsView.setOnCheckedChangedListener(this);
|
||||
huaweiAppLaunchView = v.findViewById(R.id.huaweiAppLaunchView);
|
||||
huaweiAppLaunchView.setOnCheckedChangedListener(this);
|
||||
xiaomiView = v.findViewById(R.id.xiaomiView);
|
||||
xiaomiView.setOnCheckedChangedListener(this);
|
||||
next = v.findViewById(R.id.next);
|
||||
ProgressBar progressBar = v.findViewById(R.id.progress);
|
||||
|
||||
dozeView.setOnButtonClickListener(this::askForDozeWhitelisting);
|
||||
next.setOnClickListener(this);
|
||||
|
||||
viewModel.getIsCreatingAccount()
|
||||
.observe(getViewLifecycleOwner(), isCreatingAccount -> {
|
||||
if (isCreatingAccount) {
|
||||
next.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_doze_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int request, int result,
|
||||
@Nullable Intent data) {
|
||||
super.onActivityResult(request, result, data);
|
||||
if (request == REQUEST_DOZE_WHITELISTING) {
|
||||
if (!dozeView.needsToBeShown() || secondAttempt) {
|
||||
dozeView.setChecked(true);
|
||||
} else if (getContext() != null) {
|
||||
secondAttempt = true;
|
||||
showOnboardingDialog(getContext(), getHelpText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckedChanged() {
|
||||
next.setEnabled(dozeView.isChecked() &&
|
||||
huaweiProtectedAppsView.isChecked() &&
|
||||
huaweiAppLaunchView.isChecked() &&
|
||||
xiaomiView.isChecked());
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
private void askForDozeWhitelisting() {
|
||||
if (getContext() == null) return;
|
||||
Intent i = UiUtils.getDozeWhitelistingIntent(getContext());
|
||||
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
viewModel.dozeExceptionConfirmed();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
interface DozeHelper {
|
||||
|
||||
boolean needToShowDozeFragment(Context context);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
class DozeHelperImpl implements DozeHelper {
|
||||
@Override
|
||||
public boolean needToShowDozeFragment(Context context) {
|
||||
Context appContext = context.getApplicationContext();
|
||||
return needsDozeWhitelisting(appContext) ||
|
||||
HuaweiProtectedAppsView.needsToBeShown(appContext) ||
|
||||
HuaweiAppLaunchView.needsToBeShown(appContext) ||
|
||||
XiaomiView.isXiaomiOrRedmiDevice();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.android.dontkillmelib.DozeHelperImpl;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class DozeView extends PowerView {
|
||||
|
||||
@Nullable
|
||||
private Runnable onButtonClickListener;
|
||||
|
||||
public DozeView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DozeView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public DozeView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setText(R.string.setup_doze_intro);
|
||||
setButtonText(R.string.setup_doze_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsToBeShown() {
|
||||
return needsToBeShown(getContext());
|
||||
}
|
||||
|
||||
public static boolean needsToBeShown(Context context) {
|
||||
return needsDozeWhitelisting(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getHelpText() {
|
||||
return R.string.setup_doze_explanation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClick() {
|
||||
if (onButtonClickListener == null) throw new IllegalStateException();
|
||||
onButtonClickListener.run();
|
||||
}
|
||||
|
||||
public void setOnButtonClickListener(Runnable runnable) {
|
||||
onButtonClickListener = runnable;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class HuaweiAppLaunchView extends PowerView {
|
||||
|
||||
private final static String PACKAGE_NAME = "com.huawei.systemmanager";
|
||||
private final static String CLASS_NAME =
|
||||
PACKAGE_NAME + ".power.ui.HwPowerManagerActivity";
|
||||
|
||||
public HuaweiAppLaunchView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HuaweiAppLaunchView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public HuaweiAppLaunchView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setText(R.string.setup_huawei_app_launch_text);
|
||||
setButtonText(R.string.setup_huawei_app_launch_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsToBeShown() {
|
||||
return needsToBeShown(getContext());
|
||||
}
|
||||
|
||||
public static boolean needsToBeShown(Context context) {
|
||||
// "App launch" was introduced in EMUI 8 (Android 8.0)
|
||||
if (SDK_INT < 26) return false;
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(),
|
||||
MATCH_DEFAULT_ONLY);
|
||||
return !resolveInfos.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@StringRes
|
||||
protected int getHelpText() {
|
||||
return R.string.setup_huawei_app_launch_help;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClick() {
|
||||
getContext().startActivity(getIntent());
|
||||
setChecked(true);
|
||||
}
|
||||
|
||||
private static Intent getIntent() {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(PACKAGE_NAME, CLASS_NAME);
|
||||
return intent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class HuaweiProtectedAppsView extends PowerView {
|
||||
|
||||
private final static String PACKAGE_NAME = "com.huawei.systemmanager";
|
||||
private final static String CLASS_NAME =
|
||||
PACKAGE_NAME + ".optimize.process.ProtectActivity";
|
||||
|
||||
public HuaweiProtectedAppsView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HuaweiProtectedAppsView(Context context,
|
||||
@Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public HuaweiProtectedAppsView(Context context,
|
||||
@Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setText(R.string.setup_huawei_text);
|
||||
setButtonText(R.string.setup_huawei_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsToBeShown() {
|
||||
return needsToBeShown(getContext());
|
||||
}
|
||||
|
||||
public static boolean needsToBeShown(Context context) {
|
||||
// "Protected apps" no longer exists on Huawei EMUI 5.0 (Android 7.0)
|
||||
if (SDK_INT >= 24) return false;
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<ResolveInfo> resolveInfos = pm.queryIntentActivities(getIntent(),
|
||||
MATCH_DEFAULT_ONLY);
|
||||
return !resolveInfos.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@StringRes
|
||||
protected int getHelpText() {
|
||||
return R.string.setup_huawei_help;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClick() {
|
||||
getContext().startActivity(getIntent());
|
||||
setChecked(true);
|
||||
}
|
||||
|
||||
private static Intent getIntent() {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(PACKAGE_NAME, CLASS_NAME);
|
||||
return intent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
abstract class PowerView extends ConstraintLayout {
|
||||
|
||||
private final TextView textView;
|
||||
private final ImageView checkImage;
|
||||
private final Button button;
|
||||
|
||||
private boolean checked = false;
|
||||
|
||||
@Nullable
|
||||
private OnCheckedChangedListener onCheckedChangedListener;
|
||||
|
||||
public PowerView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public PowerView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public PowerView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
LayoutInflater inflater = (LayoutInflater) context
|
||||
.getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||
View v = inflater.inflate(R.layout.power_view, this, true);
|
||||
|
||||
textView = v.findViewById(R.id.textView);
|
||||
checkImage = v.findViewById(R.id.checkImage);
|
||||
button = v.findViewById(R.id.button);
|
||||
button.setOnClickListener(view -> onButtonClick());
|
||||
ImageButton helpButton = v.findViewById(R.id.helpButton);
|
||||
helpButton.setOnClickListener(view -> onHelpButtonClick());
|
||||
|
||||
// we need to manage the checkImage state ourselves, because automatic
|
||||
// state saving is done based on the view's ID and there can be
|
||||
// multiple ImageViews with the same ID in the view hierarchy
|
||||
setSaveFromParentEnabled(true);
|
||||
|
||||
if (!isInEditMode() && !needsToBeShown()) {
|
||||
setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState ss = new SavedState(superState);
|
||||
ss.value = new boolean[] {checked};
|
||||
return ss;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState ss = (SavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
setChecked(ss.value[0]); // also calls listener
|
||||
}
|
||||
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public abstract boolean needsToBeShown();
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
if (checked) {
|
||||
checkImage.setVisibility(VISIBLE);
|
||||
} else {
|
||||
checkImage.setVisibility(INVISIBLE);
|
||||
}
|
||||
if (onCheckedChangedListener != null) {
|
||||
onCheckedChangedListener.onCheckedChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return getVisibility() == GONE || checked;
|
||||
}
|
||||
|
||||
public void setOnCheckedChangedListener(
|
||||
OnCheckedChangedListener onCheckedChangedListener) {
|
||||
this.onCheckedChangedListener = onCheckedChangedListener;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
protected abstract int getHelpText();
|
||||
|
||||
protected void setText(@StringRes int res) {
|
||||
textView.setText(res);
|
||||
}
|
||||
|
||||
protected void setButtonText(@StringRes int res) {
|
||||
button.setText(res);
|
||||
}
|
||||
|
||||
protected abstract void onButtonClick();
|
||||
|
||||
private void onHelpButtonClick() {
|
||||
showOnboardingDialog(getContext(),
|
||||
getContext().getString(getHelpText()));
|
||||
}
|
||||
|
||||
private static class SavedState extends BaseSavedState {
|
||||
private boolean[] value = {false};
|
||||
|
||||
private SavedState(@Nullable Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
private SavedState(Parcel in) {
|
||||
super(in);
|
||||
in.readBooleanArray(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeBooleanArray(value);
|
||||
}
|
||||
|
||||
static final Parcelable.Creator<SavedState> CREATOR
|
||||
= new Parcelable.Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
interface OnCheckedChangedListener {
|
||||
void onCheckedChanged();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,12 +14,14 @@ import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||
import static androidx.lifecycle.Lifecycle.State.STARTED;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.AUTHOR_NAME;
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.CREATED;
|
||||
@@ -28,6 +30,7 @@ import static org.briarproject.briar.android.account.SetupViewModel.State.FAILED
|
||||
import static org.briarproject.briar.android.account.SetupViewModel.State.SET_PASSWORD;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setInputStateAlwaysVisible;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setInputStateHidden;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -77,7 +80,10 @@ public class SetupActivity extends BaseActivity
|
||||
|
||||
@TargetApi(23)
|
||||
void showDozeFragment() {
|
||||
showNextFragment(DozeFragment.newInstance());
|
||||
Fragment f = new DoNotKillMeFragment();
|
||||
String tag = DoNotKillMeFragment.TAG;
|
||||
if (!getLifecycle().getCurrentState().isAtLeast(STARTED)) return;
|
||||
showFragment(getSupportFragmentManager(), f, tag);
|
||||
}
|
||||
|
||||
void showApp() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.briarproject.briar.android.account;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
@@ -95,7 +96,7 @@ class SetupViewModel extends AndroidViewModel {
|
||||
}
|
||||
|
||||
boolean needToShowDozeFragment() {
|
||||
return dozeHelper.needToShowDozeFragment(getApplication());
|
||||
return dozeHelper.needToShowDoNotKillMeFragment(getApplication());
|
||||
}
|
||||
|
||||
void dozeExceptionConfirmed() {
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import static android.os.Build.BRAND;
|
||||
import static org.briarproject.bramble.util.AndroidUtils.getSystemProperty;
|
||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class XiaomiView extends PowerView {
|
||||
|
||||
public XiaomiView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public XiaomiView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public XiaomiView(Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setText(R.string.setup_xiaomi_text);
|
||||
setButtonText(R.string.setup_xiaomi_button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsToBeShown() {
|
||||
return isXiaomiOrRedmiDevice();
|
||||
}
|
||||
|
||||
public static boolean isXiaomiOrRedmiDevice() {
|
||||
return "Xiaomi".equalsIgnoreCase(BRAND) ||
|
||||
"Redmi".equalsIgnoreCase(BRAND);
|
||||
}
|
||||
|
||||
@Override
|
||||
@StringRes
|
||||
protected int getHelpText() {
|
||||
return R.string.setup_xiaomi_help;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onButtonClick() {
|
||||
int bodyRes = isMiuiTenOrLater()
|
||||
? R.string.setup_xiaomi_dialog_body_new
|
||||
: R.string.setup_xiaomi_dialog_body_old;
|
||||
showOnboardingDialog(getContext(), getContext().getString(bodyRes));
|
||||
setChecked(true);
|
||||
}
|
||||
|
||||
private boolean isMiuiTenOrLater() {
|
||||
String version = getSystemProperty("ro.miui.ui.version.name");
|
||||
if (isNullOrEmpty(version)) return false;
|
||||
version = version.replaceAll("[^\\d]", "");
|
||||
try {
|
||||
return Integer.parseInt(version) >= 10;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,11 +36,11 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_PASSWORD;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_UNLOCK;
|
||||
import static org.briarproject.briar.android.util.UiUtils.excludeSystemUi;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.briar.android.util.UiUtils.isSamsung7;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
|
||||
@@ -27,10 +27,10 @@ import androidx.annotation.CallSuper;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
@NotNullByDefault
|
||||
public class BriarControllerImpl implements BriarController {
|
||||
|
||||
@@ -25,11 +25,11 @@ import androidx.lifecycle.MutableLiveData;
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.android.dontkillmelib.PowerUtils.needsDozeWhitelisting;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||
import static org.briarproject.briar.android.controller.BriarControllerImpl.DOZE_ASK_AGAIN;
|
||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
@NotNullByDefault
|
||||
public class NavDrawerViewModel extends DbViewModel {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
@@ -12,7 +10,6 @@ import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.os.PowerManager;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
@@ -68,13 +65,11 @@ import androidx.lifecycle.Observer;
|
||||
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
|
||||
|
||||
import static android.content.Context.KEYGUARD_SERVICE;
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.content.Intent.CATEGORY_DEFAULT;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.os.Build.MANUFACTURER;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;
|
||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||
import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_ALL;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||
@@ -323,23 +318,6 @@ public class UiUtils {
|
||||
.show();
|
||||
}
|
||||
|
||||
public static boolean needsDozeWhitelisting(Context ctx) {
|
||||
if (SDK_INT < 23) return false;
|
||||
PowerManager pm = (PowerManager) ctx.getSystemService(POWER_SERVICE);
|
||||
String packageName = ctx.getPackageName();
|
||||
if (pm == null) throw new AssertionError();
|
||||
return !pm.isIgnoringBatteryOptimizations(packageName);
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
@SuppressLint("BatteryLife")
|
||||
public static Intent getDozeWhitelistingIntent(Context ctx) {
|
||||
Intent i = new Intent();
|
||||
i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
i.setData(Uri.parse("package:" + ctx.getPackageName()));
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if location is enabled,
|
||||
* or it isn't required due to this being a SDK < 28 device.
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.briarproject.briar.android.view.BriarRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/feedList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:emptyText="@string/blogs_rss_feeds_manage_empty_state"
|
||||
app:scrollToEnd="false"
|
||||
tools:listitem="@layout/list_item_rss_feed" />
|
||||
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_activity_vertical">
|
||||
|
||||
<org.briarproject.briar.android.account.DozeView
|
||||
android:id="@+id/dozeView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<org.briarproject.briar.android.account.HuaweiProtectedAppsView
|
||||
android:id="@+id/huaweiProtectedAppsView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dozeView" />
|
||||
|
||||
<org.briarproject.briar.android.account.HuaweiAppLaunchView
|
||||
android:id="@+id/huaweiAppLaunchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/huaweiProtectedAppsView" />
|
||||
|
||||
<org.briarproject.briar.android.account.XiaomiView
|
||||
android:id="@+id/xiaomiView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_large"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/huaweiAppLaunchView" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/next"
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
android:text="@string/create_account_button"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/xiaomiView"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:enabled="true" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/next"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/next" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/margin_large"
|
||||
android:layout_marginLeft="@dimen/margin_large"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:layout_marginEnd="@dimen/margin_large"
|
||||
android:layout_marginRight="@dimen/margin_large"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/setup_huawei_text" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/checkImage"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/button"
|
||||
app:srcCompat="@drawable/ic_check_white"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
style="@style/BriarButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
app:layout_constraintEnd_toStartOf="@+id/helpButton"
|
||||
app:layout_constraintStart_toEndOf="@+id/checkImage"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView"
|
||||
tools:text="@string/setup_huawei_button" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/helpButton"
|
||||
style="@style/BriarButtonFlat.Positive"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:contentDescription="@string/help"
|
||||
android:tint="@color/briar_button_text_positive"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/button"
|
||||
app:srcCompat="@drawable/ic_help_outline_white" />
|
||||
|
||||
</merge>
|
||||
@@ -65,6 +65,12 @@
|
||||
<item name="android:minWidth">@dimen/button_size</item>
|
||||
</style>
|
||||
|
||||
<style name="HelpButton" parent="BriarButtonFlat.Positive">
|
||||
<item name="android:tint">@color/briar_button_text_positive</item>
|
||||
</style>
|
||||
|
||||
<style name="DoNotKillMeButton" parent="BriarButton" />
|
||||
|
||||
<style name="Divider">
|
||||
<item name="android:background">@color/divider</item>
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.account;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.android.dontkillmelib.DozeHelper;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
@@ -48,7 +49,7 @@ public class SetupViewModelTest extends BrambleMockTestCase {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(accountManager).accountExists();
|
||||
will(returnValue(false));
|
||||
allowing(dozeHelper).needToShowDozeFragment(app);
|
||||
allowing(dozeHelper).needToShowDoNotKillMeFragment(app);
|
||||
allowing(app).getApplicationContext();
|
||||
will(returnValue(appContext));
|
||||
allowing(appContext).getPackageManager();
|
||||
|
||||
Reference in New Issue
Block a user