Allow side-by-side installation of staging build.

master
Alan Evans 2020-09-18 16:52:11 -03:00 committed by Greyson Parrelli
parent a8415a3484
commit c61d731358
20 changed files with 130 additions and 53 deletions

1
.gitignore vendored
View File

@ -25,3 +25,4 @@ obj/
jni/libspeex/.deps/
*.sh
pkcs11.password
dev.keystore

View File

@ -100,6 +100,15 @@ android {
javaMaxHeapSize "4g"
}
signingConfigs {
staging {
storeFile file("${project.rootDir}/dev.keystore")
storePassword 'android'
keyAlias 'staging'
keyPassword 'android'
}
}
defaultConfig {
versionCode canonicalVersionCode * postFixSize
versionName canonicalVersionName
@ -195,6 +204,8 @@ android {
}
staging {
initWith debug
applicationIdSuffix ".staging"
signingConfig signingConfigs.staging
buildConfigField "String", "SIGNAL_URL", "\"https://textsecure-service-staging.whispersystems.org\""
buildConfigField "String", "STORAGE_URL", "\"https://storage-staging.signal.org\""

View File

@ -5,5 +5,12 @@
<application
android:name=".FlipperApplicationContext"
tools:replace="android:name"/>
tools:replace="android:name">
<activity
android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
android:exported="true" />
</application>
</manifest>

View File

@ -5,7 +5,7 @@
<uses-sdk tools:overrideLibrary="androidx.camera.core,androidx.camera.camera2,androidx.camera.lifecycle" />
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
<permission android:name="${applicationId}.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"
android:protectionLevel="signature" />
@ -113,7 +113,7 @@
<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" />
<activity android:name="org.thoughtcrime.securesms.WebRtcCallActivity"
<activity android:name=".WebRtcCallActivity"
android:theme="@style/TextSecure.LightTheme.WebRTCCall"
android:excludeFromRecents="true"
android:screenOrientation="portrait"
@ -136,7 +136,7 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.thoughtcrime.securesms.MainActivity" />
android:value=".MainActivity" />
</activity>
<activity android:name=".PromptMmsActivity"
@ -528,7 +528,7 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode"
android:launchMode="singleTask" />
<service android:enabled="true" android:name="org.thoughtcrime.securesms.service.WebRtcCallService"/>
<service android:enabled="true" android:name=".service.WebRtcCallService"/>
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:exported="false" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".messages.IncomingMessageObserver$ForegroundService"/>
@ -650,15 +650,15 @@
<provider android:name=".providers.PartProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="org.thoughtcrime.provider.securesms" />
android:authorities="${applicationId}.part" />
<provider android:name=".providers.MmsBodyProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="org.thoughtcrime.provider.securesms.mms" />
android:authorities="${applicationId}.mms" />
<provider android:name="androidx.core.content.FileProvider"
android:authorities="org.thoughtcrime.securesms.fileprovider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
@ -667,23 +667,23 @@
</provider>
<provider android:name=".database.DatabaseContentProviders$Conversation"
android:authorities="org.thoughtcrime.securesms.database.conversation"
android:authorities="${applicationId}.database.conversation"
android:exported="false" />
<provider android:name=".database.DatabaseContentProviders$ConversationList"
android:authorities="org.thoughtcrime.securesms.database.conversationlist"
android:authorities="${applicationId}.database.conversationlist"
android:exported="false" />
<provider android:name=".database.DatabaseContentProviders$Attachment"
android:authorities="org.thoughtcrime.securesms.database.attachment"
android:authorities="${applicationId}.database.attachment"
android:exported="false" />
<provider android:name=".database.DatabaseContentProviders$Sticker"
android:authorities="org.thoughtcrime.securesms.database.sticker"
android:authorities="${applicationId}.database.sticker"
android:exported="false" />
<provider android:name=".database.DatabaseContentProviders$StickerPack"
android:authorities="org.thoughtcrime.securesms.database.stickerpack"
android:authorities="${applicationId}.database.stickerpack"
android:exported="false" />
<receiver android:name=".service.BootReceiver">

View File

@ -4,9 +4,12 @@ import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
/**
* Starting in API 26, a {@link ContentProvider} needs to be defined for each authority you wish to
* observe changes on. These classes essentially do nothing except exist so Android doesn't complain.
@ -14,11 +17,15 @@ import androidx.annotation.Nullable;
public class DatabaseContentProviders {
public static class ConversationList extends NoopContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://org.thoughtcrime.securesms.database.conversationlist");
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".database.conversationlist";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
}
public static class Conversation extends NoopContentProvider {
private static final String CONTENT_URI_STRING = "content://org.thoughtcrime.securesms.database.conversation/";
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".database.conversation";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY + "/";
public static Uri getUriForThread(long threadId) {
return Uri.parse(CONTENT_URI_STRING + threadId);
@ -34,15 +41,24 @@ public class DatabaseContentProviders {
}
public static class Attachment extends NoopContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://org.thoughtcrime.securesms.database.attachment");
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".database.attachment";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
}
public static class Sticker extends NoopContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://org.thoughtcrime.securesms.database.sticker");
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".database.sticker";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
}
public static class StickerPack extends NoopContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://org.thoughtcrime.securesms.database.stickerpack");
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".database.stickerpack";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY;
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
}
private static abstract class NoopContentProvider extends ContentProvider {

View File

@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.BuildConfig;
import org.whispersystems.libsignal.util.Pair;
import java.util.ArrayList;
@ -24,7 +25,7 @@ public class LogSectionPermissions implements LogSection {
List<Pair<String, Boolean>> status = new ArrayList<>();
try {
PackageInfo info = context.getPackageManager().getPackageInfo("org.thoughtcrime.securesms", PackageManager.GET_PERMISSIONS);
PackageInfo info = context.getPackageManager().getPackageInfo(BuildConfig.APPLICATION_ID, PackageManager.GET_PERMISSIONS);
for (int i = 0; i < info.requestedPermissions.length; i++) {
status.add(new Pair<>(info.requestedPermissions[i],

View File

@ -4,25 +4,26 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.blurhash.BlurHash;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.providers.DeprecatedPersistentBlobProvider;
import org.thoughtcrime.securesms.providers.PartProvider;
import org.thoughtcrime.securesms.util.MediaUtil;
import java.io.IOException;
import java.io.InputStream;
public class PartAuthority {
private static final String PART_URI_STRING = "content://org.thoughtcrime.securesms/part";
private static final String STICKER_URI_STRING = "content://org.thoughtcrime.securesms/sticker";
private static final String AUTHORITY = BuildConfig.APPLICATION_ID;
private static final String PART_URI_STRING = "content://" + AUTHORITY + "/part";
private static final String STICKER_URI_STRING = "content://" + AUTHORITY + "/sticker";
private static final Uri PART_CONTENT_URI = Uri.parse(PART_URI_STRING);
private static final Uri STICKER_CONTENT_URI = Uri.parse(STICKER_URI_STRING);
@ -35,8 +36,8 @@ public class PartAuthority {
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("org.thoughtcrime.securesms", "part/*/#", PART_ROW);
uriMatcher.addURI("org.thoughtcrime.securesms", "sticker/#", STICKER_ROW);
uriMatcher.addURI(AUTHORITY, "part/*/#", PART_ROW);
uriMatcher.addURI(AUTHORITY, "sticker/#", STICKER_ROW);
uriMatcher.addURI(DeprecatedPersistentBlobProvider.AUTHORITY, DeprecatedPersistentBlobProvider.EXPECTED_PATH_OLD, PERSISTENT_ROW);
uriMatcher.addURI(DeprecatedPersistentBlobProvider.AUTHORITY, DeprecatedPersistentBlobProvider.EXPECTED_PATH_NEW, PERSISTENT_ROW);
uriMatcher.addURI(BlobProvider.AUTHORITY, BlobProvider.PATH, BLOB_ROW);

View File

@ -5,12 +5,14 @@ import android.content.Context;
import android.content.UriMatcher;
import android.media.MediaDataSource;
import android.net.Uri;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.WorkerThread;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
@ -43,9 +45,9 @@ public class BlobProvider {
private static final String MULTI_SESSION_DIRECTORY = "multi_session_blobs";
private static final String SINGLE_SESSION_DIRECTORY = "single_session_blobs";
public static final Uri CONTENT_URI = Uri.parse("content://org.thoughtcrime.securesms/blob");
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String PATH = "blob/*/*/*/*/*";
public static final String AUTHORITY = BuildConfig.APPLICATION_ID;
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/blob");
public static final String PATH = "blob/*/*/*/*/*";
private static final int STORAGE_TYPE_PATH_SEGMENT = 1;
private static final int MIMETYPE_PATH_SEGMENT = 2;

View File

@ -4,16 +4,17 @@ import android.content.ContentUris;
import android.content.Context;
import android.content.UriMatcher;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.logging.Log;
import android.webkit.MimeTypeMap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.FileProviderUtil;
import java.io.File;
@ -29,11 +30,11 @@ import java.io.InputStream;
@Deprecated
public class DeprecatedPersistentBlobProvider {
private static final String TAG = DeprecatedPersistentBlobProvider.class.getSimpleName();
private static final String TAG = Log.tag(DeprecatedPersistentBlobProvider.class);
private static final String URI_STRING = "content://org.thoughtcrime.securesms/capture-new";
public static final String AUTHORITY = BuildConfig.APPLICATION_ID;
private static final String URI_STRING = "content://" + AUTHORITY + "/capture-new";
public static final Uri CONTENT_URI = Uri.parse(URI_STRING);
public static final String AUTHORITY = "org.thoughtcrime.securesms";
public static final String EXPECTED_PATH_OLD = "capture/*/*/#";
public static final String EXPECTED_PATH_NEW = "capture-new/*/*/*/*/#";

View File

@ -24,8 +24,10 @@ import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.logging.Log;
import java.io.File;
@ -35,7 +37,8 @@ import java.io.OutputStream;
public class MmsBodyProvider extends ContentProvider {
private static final String TAG = MmsBodyProvider.class.getSimpleName();
private static final String CONTENT_URI_STRING = "content://org.thoughtcrime.provider.securesms.mms/mms";
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".mms";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY + "/mms";
public static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
private static final int SINGLE_ROW = 1;
@ -43,7 +46,7 @@ public class MmsBodyProvider extends ContentProvider {
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("org.thoughtcrime.provider.securesms.mms", "mms/#", SINGLE_ROW);
uriMatcher.addURI(CONTENT_AUTHORITY, "mms/#", SINGLE_ROW);
}
@Override

View File

@ -26,12 +26,14 @@ import android.net.Uri;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.logging.Log;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.PartUriParser;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.MemoryFileUtil;
@ -46,7 +48,8 @@ public class PartProvider extends ContentProvider {
private static final String TAG = PartProvider.class.getSimpleName();
private static final String CONTENT_URI_STRING = "content://org.thoughtcrime.provider.securesms/part";
private static final String CONTENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".part";
private static final String CONTENT_URI_STRING = "content://" + CONTENT_AUTHORITY + "/part";
private static final Uri CONTENT_URI = Uri.parse(CONTENT_URI_STRING);
private static final int SINGLE_ROW = 1;
@ -54,7 +57,7 @@ public class PartProvider extends ContentProvider {
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("org.thoughtcrime.provider.securesms", "part/*/#", SINGLE_ROW);
uriMatcher.addURI(CONTENT_AUTHORITY, "part/*/#", SINGLE_ROW);
}
@Override

View File

@ -32,6 +32,7 @@ import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.logging.Log;
@ -61,14 +62,14 @@ public class KeyCachingService extends Service {
public static final int SERVICE_RUNNING_ID = 4141;
public static final String KEY_PERMISSION = "org.thoughtcrime.securesms.ACCESS_SECRETS";
public static final String NEW_KEY_EVENT = "org.thoughtcrime.securesms.service.action.NEW_KEY_EVENT";
public static final String CLEAR_KEY_EVENT = "org.thoughtcrime.securesms.service.action.CLEAR_KEY_EVENT";
public static final String LOCK_TOGGLED_EVENT = "org.thoughtcrime.securesms.service.action.LOCK_ENABLED_EVENT";
private static final String PASSPHRASE_EXPIRED_EVENT = "org.thoughtcrime.securesms.service.action.PASSPHRASE_EXPIRED_EVENT";
public static final String CLEAR_KEY_ACTION = "org.thoughtcrime.securesms.service.action.CLEAR_KEY";
public static final String DISABLE_ACTION = "org.thoughtcrime.securesms.service.action.DISABLE";
public static final String LOCALE_CHANGE_EVENT = "org.thoughtcrime.securesms.service.action.LOCALE_CHANGE_EVENT";
public static final String KEY_PERMISSION = BuildConfig.APPLICATION_ID + ".ACCESS_SECRETS";
public static final String NEW_KEY_EVENT = BuildConfig.APPLICATION_ID + ".service.action.NEW_KEY_EVENT";
public static final String CLEAR_KEY_EVENT = BuildConfig.APPLICATION_ID + ".service.action.CLEAR_KEY_EVENT";
public static final String LOCK_TOGGLED_EVENT = BuildConfig.APPLICATION_ID + ".service.action.LOCK_ENABLED_EVENT";
private static final String PASSPHRASE_EXPIRED_EVENT = BuildConfig.APPLICATION_ID + ".service.action.PASSPHRASE_EXPIRED_EVENT";
public static final String CLEAR_KEY_ACTION = BuildConfig.APPLICATION_ID + ".service.action.CLEAR_KEY";
public static final String DISABLE_ACTION = BuildConfig.APPLICATION_ID + ".service.action.DISABLE";
public static final String LOCALE_CHANGE_EVENT = BuildConfig.APPLICATION_ID + ".service.action.LOCALE_CHANGE_EVENT";
private DynamicLanguage dynamicLanguage = new DynamicLanguage();

View File

@ -7,11 +7,13 @@ import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;
import org.thoughtcrime.securesms.BuildConfig;
import java.io.File;
public class FileProviderUtil {
private static final String AUTHORITY = "org.thoughtcrime.securesms.fileprovider";
private static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".fileprovider";
public static Uri getUriFor(@NonNull Context context, @NonNull File file) {
if (Build.VERSION.SDK_INT >= 24) return FileProvider.getUriForFile(context, AUTHORITY, file);

View File

@ -2,14 +2,18 @@ package org.thoughtcrime.securesms.util;
import android.content.Context;
import android.os.Environment;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.database.NoExternalStorageException;
import java.io.File;
public class StorageUtil {
private static final String PRODUCTION_PACKAGE_ID = "org.thoughtcrime.securesms";
public static File getBackupDirectory() throws NoExternalStorageException {
File storage = Environment.getExternalStorageDirectory();
@ -20,6 +24,11 @@ public class StorageUtil {
File signal = new File(storage, "Signal");
File backups = new File(signal, "Backups");
//noinspection ConstantConditions
if (BuildConfig.APPLICATION_ID.startsWith(PRODUCTION_PACKAGE_ID + ".")) {
backups = new File(backups, BuildConfig.APPLICATION_ID.substring(PRODUCTION_PACKAGE_ID.length() + 1));
}
if (!backups.exists()) {
if (!backups.mkdirs()) {
throw new NoExternalStorageException("Unable to create backup directory...");

View File

@ -183,7 +183,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior=".util.views.SlideUpWithSnackbarBehavior">
app:layout_behavior="org.thoughtcrime.securesms.util.views.SlideUpWithSnackbarBehavior">
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
android:id="@+id/camera_fab"

View File

@ -113,7 +113,7 @@
android:layout_marginTop="16dp"
android:elevation="8dp"
android:transitionName="avatar"
app:layout_behavior=".recipients.ui.RecipientSettingsCoordinatorLayoutBehavior" />
app:layout_behavior="org.thoughtcrime.securesms.recipients.ui.RecipientSettingsCoordinatorLayoutBehavior" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/name"

View File

@ -154,7 +154,7 @@
android:layout_marginTop="16dp"
android:elevation="8dp"
android:transitionName="avatar"
app:layout_behavior=".recipients.ui.RecipientSettingsCoordinatorLayoutBehavior" />
app:layout_behavior="org.thoughtcrime.securesms.recipients.ui.RecipientSettingsCoordinatorLayoutBehavior" />
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/name"

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/core_black"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="org.thoughtcrime.securesms.staging"
android:icon="@mipmap/ic_launcher"
android:smallIcon="@mipmap/ic_launcher"
android:label="@string/app_name"/>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="org.thoughtcrime.securesms.staging"
android:userVisible="true"
android:supportsUploading="true"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>