Add shake-to-report for internal users.

This commit is contained in:
Greyson Parrelli
2021-01-04 18:39:48 -05:00
committed by Alan Evans
parent 7ef77bf16c
commit 61c5fc1057
8 changed files with 414 additions and 2 deletions

View File

@@ -17,6 +17,7 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Build;
import androidx.annotation.NonNull;
@@ -32,6 +33,7 @@ import com.google.android.gms.security.ProviderInstaller;
import org.conscrypt.Conscrypt;
import org.signal.aesgcmprovider.AesGcmProvider;
import org.signal.core.util.ShakeDetector;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.AndroidLogger;
import org.signal.core.util.logging.Log;
@@ -69,6 +71,7 @@ import org.thoughtcrime.securesms.service.LocalBackupListener;
import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
import org.thoughtcrime.securesms.shakereport.ShakeToReport;
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
import org.thoughtcrime.securesms.util.AppStartup;
import org.thoughtcrime.securesms.util.DynamicTheme;
@@ -177,6 +180,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
executePendingContactSync();
KeyCachingService.onAppForegrounded(this);
ApplicationDependencies.getMegaphoneRepository().onAppForegrounded();
ApplicationDependencies.getShakeToReport().enable();
checkBuildExpiration();
});
@@ -190,6 +194,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
KeyCachingService.onAppBackgrounded(this);
ApplicationDependencies.getMessageNotifier().clearVisibleThread();
ApplicationDependencies.getFrameRateTracker().end();
ApplicationDependencies.getShakeToReport().disable();
}
public ExpiringMessageManager getExpiringMessageManager() {

View File

@@ -15,6 +15,7 @@ import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.util.ConfigurationUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.dynamiclanguage.DynamicLanguageContextWrapper;
@@ -44,6 +45,7 @@ public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onStart() {
logEvent("onStart()");
ApplicationDependencies.getShakeToReport().registerActivity(this);
super.onStart();
}

View File

@@ -22,6 +22,7 @@ import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
import org.thoughtcrime.securesms.service.TrimThreadsByDateManager;
import org.thoughtcrime.securesms.shakereport.ShakeToReport;
import org.thoughtcrime.securesms.util.EarlyMessageCache;
import org.thoughtcrime.securesms.util.FrameRateTracker;
import org.thoughtcrime.securesms.util.Hex;
@@ -69,6 +70,7 @@ public class ApplicationDependencies {
private static volatile TypingStatusSender typingStatusSender;
private static volatile DatabaseObserver databaseObserver;
private static volatile TrimThreadsByDateManager trimThreadsByDateManager;
private static volatile ShakeToReport shakeToReport;
@MainThread
public static void init(@NonNull Application application, @NonNull Provider provider) {
@@ -321,6 +323,18 @@ public class ApplicationDependencies {
return databaseObserver;
}
public static @NonNull ShakeToReport getShakeToReport() {
if (shakeToReport == null) {
synchronized (LOCK) {
if (shakeToReport == null) {
shakeToReport = provider.provideShakeToReport();
}
}
}
return shakeToReport;
}
public interface Provider {
@NonNull GroupsV2Operations provideGroupsV2Operations();
@NonNull SignalServiceAccountManager provideSignalServiceAccountManager();
@@ -340,5 +354,6 @@ public class ApplicationDependencies {
@NonNull TypingStatusRepository provideTypingStatusRepository();
@NonNull TypingStatusSender provideTypingStatusSender();
@NonNull DatabaseObserver provideDatabaseObserver();
@NonNull ShakeToReport provideShakeToReport();
}
}

View File

@@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.push.SecurityEventListener;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
import org.thoughtcrime.securesms.service.TrimThreadsByDateManager;
import org.thoughtcrime.securesms.shakereport.ShakeToReport;
import org.thoughtcrime.securesms.util.AlarmSleepTimer;
import org.thoughtcrime.securesms.util.ByteUnit;
import org.thoughtcrime.securesms.util.EarlyMessageCache;
@@ -201,6 +202,11 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
return new DatabaseObserver(context);
}
@Override
public @NonNull ShakeToReport provideShakeToReport() {
return new ShakeToReport(context);
}
private static class DynamicCredentialsProvider implements CredentialsProvider {
private final Context context;

View File

@@ -0,0 +1,138 @@
package org.thoughtcrime.securesms.shakereport;
import android.app.Activity;
import android.app.Application;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import org.signal.core.util.ShakeDetector;
import org.signal.core.util.logging.Log;
import org.signal.core.util.tracing.Tracer;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogRepository;
import org.thoughtcrime.securesms.sharing.ShareIntents;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.lang.ref.WeakReference;
/**
* A class that will detect a shake and then prompts the user to submit a debuglog. Basically a
* shortcut to submit a debuglog from anywhere.
*/
public final class ShakeToReport implements ShakeDetector.Listener {
private static final String TAG = Log.tag(ShakeToReport.class);
private final Application application;
private final ShakeDetector detector;
private WeakReference<Activity> weakActivity;
public ShakeToReport(@NonNull Application application) {
this.application = application;
this.detector = new ShakeDetector(this);
this.weakActivity = new WeakReference<>(null);
}
public void enable() {
if (!FeatureFlags.internalUser()) return;
detector.start(ServiceUtil.getSensorManager(application));
}
public void disable() {
if (!FeatureFlags.internalUser()) return;
detector.stop();
}
public void registerActivity(@NonNull Activity activity) {
if (!FeatureFlags.internalUser()) return;
this.weakActivity = new WeakReference<>(activity);
}
@Override
public void onShakeDetected() {
Activity activity = weakActivity.get();
if (activity == null) {
Log.w(TAG, "No registered activity!");
return;
}
disable();
new AlertDialog.Builder(activity)
.setTitle(R.string.ShakeToReport_shake_detected)
.setMessage(R.string.ShakeToReport_submit_debug_log)
.setNegativeButton(android.R.string.cancel, (d, i) -> {
d.dismiss();
enableIfVisible();
})
.setPositiveButton(R.string.ShakeToReport_submit, (d, i) -> {
d.dismiss();
submitLog(activity);
})
.show();
}
private void submitLog(@NonNull Activity activity) {
AlertDialog spinner = SimpleProgressDialog.show(activity);
SubmitDebugLogRepository repo = new SubmitDebugLogRepository();
Log.i(TAG, "Submitting log...");
repo.getLogLines(lines -> {
Log.i(TAG, "Retrieved log lines...");
repo.submitLog(lines, Tracer.getInstance().serialize(), url -> {
Log.i(TAG, "Logs uploaded!");
Util.runOnMain(() -> {
spinner.dismiss();
if (url.isPresent()) {
showPostSubmitDialog(activity, url.get());
} else {
Toast.makeText(activity, R.string.ShakeToReport_failed_to_submit, Toast.LENGTH_SHORT).show();
enableIfVisible();
}
});
});
});
}
private void showPostSubmitDialog(@NonNull Activity activity, @NonNull String url) {
AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle(R.string.ShakeToReport_success)
.setMessage(url)
.setNegativeButton(android.R.string.cancel, (d, i) -> {
d.dismiss();
enableIfVisible();
})
.setPositiveButton(R.string.ShakeToReport_share, (d, i) -> {
d.dismiss();
enableIfVisible();
activity.startActivity(new ShareIntents.Builder(activity)
.setText(url)
.build());
})
.show();
((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
}
private void enableIfVisible() {
if (ApplicationContext.getInstance(application).isAppVisible()) {
enable();
}
}
}

View File

@@ -41,8 +41,8 @@ public final class ShareIntents {
@Nullable StickerLocator extraSticker,
boolean isBorderless)
{
this.extraText = extraText;
this.extraMedia = extraMedia;
this.extraText = extraText;
this.extraMedia = extraMedia;
this.extraSticker = extraSticker;
this.isBorderless = isBorderless;
}

View File

@@ -1518,6 +1518,14 @@
<string name="SearchFragment_header_contacts">Contacts</string>
<string name="SearchFragment_header_messages">Messages</string>
<!-- ShakeToReport -->
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
<string name="ShakeToReport_submit" translatable="false">Submit</string>
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
<string name="ShakeToReport_success" translatable="false">Success!</string>
<string name="ShakeToReport_share" translatable="false">Share</string>
<!-- SharedContactDetailsActivity -->
<string name="SharedContactDetailsActivity_add_to_contacts">Add to Contacts</string>
<string name="SharedContactDetailsActivity_invite_to_signal">Invite to Signal</string>