results = new LinkedList<>();
- SQLiteDatabase database = databaseHelper.getReadableDatabase();
- Cursor cursor = null;
-
- try {
- cursor = database.query(TABLE_NAME, null, where, null, null, null, ID + " ASC", null);
-
- while (cursor.moveToNext()) {
- long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
- String item = cursor.getString(cursor.getColumnIndexOrThrow(ITEM));
- boolean encrypted = cursor.getInt(cursor.getColumnIndexOrThrow(ENCRYPTED)) == 1;
-
- try{
- Job job = jobSerializer.deserialize(keys, encrypted, item);
- results.add(job);
- } catch (IOException e) {
- Log.w("PersistentStore", e);
- remove(id);
- }
- }
- } finally {
- if (cursor != null)
- cursor.close();
- }
-
- return results;
- }
-
- public void remove(long id) {
- databaseHelper.getWritableDatabase()
- .delete(TABLE_NAME, ID + " = ?", new String[] {String.valueOf(id)});
- }
-
- private static class DatabaseHelper extends SQLiteOpenHelper {
-
- public DatabaseHelper(Context context, String name) {
- super(context, name, null, DATABASE_VERSION);
- }
-
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL(DATABASE_CREATE);
- }
-
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
-
- }
- }
-
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkBackoffRequirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkBackoffRequirement.java
deleted file mode 100644
index 147f4342b7..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkBackoffRequirement.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-import org.thoughtcrime.securesms.logging.Log;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Uses exponential backoff to re-schedule network jobs to be retried in the future.
- */
-public class NetworkBackoffRequirement implements Requirement, ContextDependent {
-
- private static final String TAG = NetworkBackoffRequirement.class.getSimpleName();
-
- private static final long MAX_WAIT = TimeUnit.SECONDS.toMillis(30);
-
- private transient Context context;
-
- public NetworkBackoffRequirement(@NonNull Context context) {
- this.context = context.getApplicationContext();
- }
-
- @Override
- public boolean isPresent(@NonNull Job job) {
- return new NetworkRequirement(context).isPresent() && System.currentTimeMillis() >= calculateNextRunTime(job);
- }
-
- @Override
- public void onRetry(@NonNull Job job) {
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context.getApplicationContext();
- }
-
- private static long calculateNextRunTime(@NonNull Job job) {
- return 0;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java
deleted file mode 100644
index 050fac6a27..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirement.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-
-/**
- * A requirement that is satisfied when a network connection is present.
- */
-public class NetworkRequirement extends SimpleRequirement implements ContextDependent {
-
- private transient Context context;
-
- public NetworkRequirement(Context context) {
- this.context = context;
- }
-
- public NetworkRequirement() {}
-
- @Override
- public boolean isPresent() {
- ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo netInfo = cm.getActiveNetworkInfo();
-
- return netInfo != null && netInfo.isConnected();
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java
deleted file mode 100644
index 788c09eeef..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/NetworkRequirementProvider.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-
-public class NetworkRequirementProvider implements RequirementProvider {
-
- private RequirementListener listener;
-
- private final NetworkRequirement requirement;
-
- public NetworkRequirementProvider(Context context) {
- this.requirement = new NetworkRequirement(context);
-
- context.getApplicationContext().registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (listener == null) {
- return;
- }
-
- if (requirement.isPresent()) {
- listener.onRequirementStatusChanged();
- }
- }
- }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
- }
-
- @Override
- public void setListener(RequirementListener listener) {
- this.listener = listener;
- }
-
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java
deleted file mode 100644
index 3631efb36c..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/Requirement.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Job;
-
-import java.io.Serializable;
-
-/**
- * A Requirement that must be satisfied before a Job can run.
- */
-public interface Requirement extends Serializable {
- /**
- * @return true if the requirement is satisfied, false otherwise.
- */
- boolean isPresent(@NonNull Job job);
-
- void onRetry(@NonNull Job job);
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java
deleted file mode 100644
index a548adfb98..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementListener.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-public interface RequirementListener {
- public void onRequirementStatusChanged();
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java
deleted file mode 100644
index 95e1c19af1..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/RequirementProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright (C) 2014 Open Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-/**
- * Notifies listeners when a {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement}'s
- * state is likely to have changed.
- */
-public interface RequirementProvider {
-
- /**
- * The {@link org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener} to call when
- * a {@link org.thoughtcrime.securesms.jobmanager.requirements.Requirement}'s status is likely to
- * have changed.
- *
- * @param listener The listener to call.
- */
- public void setListener(RequirementListener listener);
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/requirements/SimpleRequirement.java b/src/org/thoughtcrime/securesms/jobmanager/requirements/SimpleRequirement.java
deleted file mode 100644
index e6e852b00d..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/requirements/SimpleRequirement.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.requirements;
-
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Job;
-
-public abstract class SimpleRequirement implements Requirement {
-
- @Override
- public boolean isPresent(@NonNull Job job) {
- return isPresent();
- }
-
- @Override
- public void onRetry(@NonNull Job job) {
- }
-
- public abstract boolean isPresent();
-}
diff --git a/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java b/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java
deleted file mode 100644
index f44b21deba..0000000000
--- a/src/org/thoughtcrime/securesms/jobmanager/util/Base64.java
+++ /dev/null
@@ -1,741 +0,0 @@
-package org.thoughtcrime.securesms.jobmanager.util;
-
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.UnsupportedEncodingException;
-
-/**
- * Utilities for encoding and decoding the Base64 representation of
- * binary data. See RFCs 2045 and 3548.
- */
-public class Base64 {
- /**
- * Default values for encoder/decoder flags.
- */
- public static final int DEFAULT = 0;
-
- /**
- * Encoder flag bit to omit the padding '=' characters at the end
- * of the output (if any).
- */
- public static final int NO_PADDING = 1;
-
- /**
- * Encoder flag bit to omit all line terminators (i.e., the output
- * will be on one long line).
- */
- public static final int NO_WRAP = 2;
-
- /**
- * Encoder flag bit to indicate lines should be terminated with a
- * CRLF pair instead of just an LF. Has no effect if {@code
- * NO_WRAP} is specified as well.
- */
- public static final int CRLF = 4;
-
- /**
- * Encoder/decoder flag bit to indicate using the "URL and
- * filename safe" variant of Base64 (see RFC 3548 section 4) where
- * {@code -} and {@code _} are used in place of {@code +} and
- * {@code /}.
- */
- public static final int URL_SAFE = 8;
-
- /**
- * Flag to pass to {@link android.util.Base64OutputStream} to indicate that it
- * should not close the output stream it is wrapping when it
- * itself is closed.
- */
- public static final int NO_CLOSE = 16;
-
- // --------------------------------------------------------
- // shared code
- // --------------------------------------------------------
-
- /* package */ static abstract class Coder {
- public byte[] output;
- public int op;
-
- /**
- * Encode/decode another block of input data. this.output is
- * provided by the caller, and must be big enough to hold all
- * the coded data. On exit, this.opwill be set to the length
- * of the coded data.
- *
- * @param finish true if this is the final call to process for
- * this object. Will finalize the coder state and
- * include any final bytes in the output.
- *
- * @return true if the input so far is good; false if some
- * error has been detected in the input stream..
- */
- public abstract boolean process(byte[] input, int offset, int len, boolean finish);
-
- /**
- * @return the maximum number of bytes a call to process()
- * could produce for the given number of input bytes. This may
- * be an overestimate.
- */
- public abstract int maxOutputSize(int len);
- }
-
- // --------------------------------------------------------
- // decoding
- // --------------------------------------------------------
-
- /**
- * Decode the Base64-encoded data in input and return the data in
- * a new byte array.
- *
- * The padding '=' characters at the end are considered optional, but
- * if any are present, there must be the correct number of them.
- *
- * @param str the input String to decode, which is converted to
- * bytes using the default charset
- * @param flags controls certain features of the decoded output.
- * Pass {@code DEFAULT} to decode standard Base64.
- *
- * @throws IllegalArgumentException if the input contains
- * incorrect padding
- */
- public static byte[] decode(String str, int flags) {
- return decode(str.getBytes(), flags);
- }
-
- /**
- * Decode the Base64-encoded data in input and return the data in
- * a new byte array.
- *
- *
The padding '=' characters at the end are considered optional, but
- * if any are present, there must be the correct number of them.
- *
- * @param input the input array to decode
- * @param flags controls certain features of the decoded output.
- * Pass {@code DEFAULT} to decode standard Base64.
- *
- * @throws IllegalArgumentException if the input contains
- * incorrect padding
- */
- public static byte[] decode(byte[] input, int flags) {
- return decode(input, 0, input.length, flags);
- }
-
- /**
- * Decode the Base64-encoded data in input and return the data in
- * a new byte array.
- *
- *
The padding '=' characters at the end are considered optional, but
- * if any are present, there must be the correct number of them.
- *
- * @param input the data to decode
- * @param offset the position within the input array at which to start
- * @param len the number of bytes of input to decode
- * @param flags controls certain features of the decoded output.
- * Pass {@code DEFAULT} to decode standard Base64.
- *
- * @throws IllegalArgumentException if the input contains
- * incorrect padding
- */
- public static byte[] decode(byte[] input, int offset, int len, int flags) {
- // Allocate space for the most data the input could represent.
- // (It could contain less if it contains whitespace, etc.)
- Decoder decoder = new Decoder(flags, new byte[len*3/4]);
-
- if (!decoder.process(input, offset, len, true)) {
- throw new IllegalArgumentException("bad base-64");
- }
-
- // Maybe we got lucky and allocated exactly enough output space.
- if (decoder.op == decoder.output.length) {
- return decoder.output;
- }
-
- // Need to shorten the array, so allocate a new one of the
- // right size and copy.
- byte[] temp = new byte[decoder.op];
- System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
- return temp;
- }
-
- /* package */ static class Decoder extends Coder {
- /**
- * Lookup table for turning bytes into their position in the
- * Base64 alphabet.
- */
- private static final int DECODE[] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- };
-
- /**
- * Decode lookup table for the "web safe" variant (RFC 3548
- * sec. 4) where - and _ replace + and /.
- */
- private static final int DECODE_WEBSAFE[] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
- -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- };
-
- /** Non-data values in the DECODE arrays. */
- private static final int SKIP = -1;
- private static final int EQUALS = -2;
-
- /**
- * States 0-3 are reading through the next input tuple.
- * State 4 is having read one '=' and expecting exactly
- * one more.
- * State 5 is expecting no more data or padding characters
- * in the input.
- * State 6 is the error state; an error has been detected
- * in the input and no future input can "fix" it.
- */
- private int state; // state number (0 to 6)
- private int value;
-
- final private int[] alphabet;
-
- public Decoder(int flags, byte[] output) {
- this.output = output;
-
- alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
- state = 0;
- value = 0;
- }
-
- /**
- * @return an overestimate for the number of bytes {@code
- * len} bytes could decode to.
- */
- public int maxOutputSize(int len) {
- return len * 3/4 + 10;
- }
-
- /**
- * Decode another block of input data.
- *
- * @return true if the state machine is still healthy. false if
- * bad base-64 data has been detected in the input stream.
- */
- public boolean process(byte[] input, int offset, int len, boolean finish) {
- if (this.state == 6) return false;
-
- int p = offset;
- len += offset;
-
- // Using local variables makes the decoder about 12%
- // faster than if we manipulate the member variables in
- // the loop. (Even alphabet makes a measurable
- // difference, which is somewhat surprising to me since
- // the member variable is final.)
- int state = this.state;
- int value = this.value;
- int op = 0;
- final byte[] output = this.output;
- final int[] alphabet = this.alphabet;
-
- while (p < len) {
- // Try the fast path: we're starting a new tuple and the
- // next four bytes of the input stream are all data
- // bytes. This corresponds to going through states
- // 0-1-2-3-0. We expect to use this method for most of
- // the data.
- //
- // If any of the next four bytes of input are non-data
- // (whitespace, etc.), value will end up negative. (All
- // the non-data values in decode are small negative
- // numbers, so shifting any of them up and or'ing them
- // together will result in a value with its top bit set.)
- //
- // You can remove this whole block and the output should
- // be the same, just slower.
- if (state == 0) {
- while (p+4 <= len &&
- (value = ((alphabet[input[p] & 0xff] << 18) |
- (alphabet[input[p+1] & 0xff] << 12) |
- (alphabet[input[p+2] & 0xff] << 6) |
- (alphabet[input[p+3] & 0xff]))) >= 0) {
- output[op+2] = (byte) value;
- output[op+1] = (byte) (value >> 8);
- output[op] = (byte) (value >> 16);
- op += 3;
- p += 4;
- }
- if (p >= len) break;
- }
-
- // The fast path isn't available -- either we've read a
- // partial tuple, or the next four input bytes aren't all
- // data, or whatever. Fall back to the slower state
- // machine implementation.
-
- int d = alphabet[input[p++] & 0xff];
-
- switch (state) {
- case 0:
- if (d >= 0) {
- value = d;
- ++state;
- } else if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
-
- case 1:
- if (d >= 0) {
- value = (value << 6) | d;
- ++state;
- } else if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
-
- case 2:
- if (d >= 0) {
- value = (value << 6) | d;
- ++state;
- } else if (d == EQUALS) {
- // Emit the last (partial) output tuple;
- // expect exactly one more padding character.
- output[op++] = (byte) (value >> 4);
- state = 4;
- } else if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
-
- case 3:
- if (d >= 0) {
- // Emit the output triple and return to state 0.
- value = (value << 6) | d;
- output[op+2] = (byte) value;
- output[op+1] = (byte) (value >> 8);
- output[op] = (byte) (value >> 16);
- op += 3;
- state = 0;
- } else if (d == EQUALS) {
- // Emit the last (partial) output tuple;
- // expect no further data or padding characters.
- output[op+1] = (byte) (value >> 2);
- output[op] = (byte) (value >> 10);
- op += 2;
- state = 5;
- } else if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
-
- case 4:
- if (d == EQUALS) {
- ++state;
- } else if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
-
- case 5:
- if (d != SKIP) {
- this.state = 6;
- return false;
- }
- break;
- }
- }
-
- if (!finish) {
- // We're out of input, but a future call could provide
- // more.
- this.state = state;
- this.value = value;
- this.op = op;
- return true;
- }
-
- // Done reading input. Now figure out where we are left in
- // the state machine and finish up.
-
- switch (state) {
- case 0:
- // Output length is a multiple of three. Fine.
- break;
- case 1:
- // Read one extra input byte, which isn't enough to
- // make another output byte. Illegal.
- this.state = 6;
- return false;
- case 2:
- // Read two extra input bytes, enough to emit 1 more
- // output byte. Fine.
- output[op++] = (byte) (value >> 4);
- break;
- case 3:
- // Read three extra input bytes, enough to emit 2 more
- // output bytes. Fine.
- output[op++] = (byte) (value >> 10);
- output[op++] = (byte) (value >> 2);
- break;
- case 4:
- // Read one padding '=' when we expected 2. Illegal.
- this.state = 6;
- return false;
- case 5:
- // Read all the padding '='s we expected and no more.
- // Fine.
- break;
- }
-
- this.state = state;
- this.op = op;
- return true;
- }
- }
-
- // --------------------------------------------------------
- // encoding
- // --------------------------------------------------------
-
- /**
- * Base64-encode the given data and return a newly allocated
- * String with the result.
- *
- * @param input the data to encode
- * @param flags controls certain features of the encoded output.
- * Passing {@code DEFAULT} results in output that
- * adheres to RFC 2045.
- */
- public static String encodeToString(byte[] input, int flags) {
- try {
- return new String(encode(input, flags), "US-ASCII");
- } catch (UnsupportedEncodingException e) {
- // US-ASCII is guaranteed to be available.
- throw new AssertionError(e);
- }
- }
-
- /**
- * Base64-encode the given data and return a newly allocated
- * String with the result.
- *
- * @param input the data to encode
- * @param offset the position within the input array at which to
- * start
- * @param len the number of bytes of input to encode
- * @param flags controls certain features of the encoded output.
- * Passing {@code DEFAULT} results in output that
- * adheres to RFC 2045.
- */
- public static String encodeToString(byte[] input, int offset, int len, int flags) {
- try {
- return new String(encode(input, offset, len, flags), "US-ASCII");
- } catch (UnsupportedEncodingException e) {
- // US-ASCII is guaranteed to be available.
- throw new AssertionError(e);
- }
- }
-
- /**
- * Base64-encode the given data and return a newly allocated
- * byte[] with the result.
- *
- * @param input the data to encode
- * @param flags controls certain features of the encoded output.
- * Passing {@code DEFAULT} results in output that
- * adheres to RFC 2045.
- */
- public static byte[] encode(byte[] input, int flags) {
- return encode(input, 0, input.length, flags);
- }
-
- /**
- * Base64-encode the given data and return a newly allocated
- * byte[] with the result.
- *
- * @param input the data to encode
- * @param offset the position within the input array at which to
- * start
- * @param len the number of bytes of input to encode
- * @param flags controls certain features of the encoded output.
- * Passing {@code DEFAULT} results in output that
- * adheres to RFC 2045.
- */
- public static byte[] encode(byte[] input, int offset, int len, int flags) {
- Encoder encoder = new Encoder(flags, null);
-
- // Compute the exact length of the array we will produce.
- int output_len = len / 3 * 4;
-
- // Account for the tail of the data and the padding bytes, if any.
- if (encoder.do_padding) {
- if (len % 3 > 0) {
- output_len += 4;
- }
- } else {
- switch (len % 3) {
- case 0: break;
- case 1: output_len += 2; break;
- case 2: output_len += 3; break;
- }
- }
-
- // Account for the newlines, if any.
- if (encoder.do_newline && len > 0) {
- output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) *
- (encoder.do_cr ? 2 : 1);
- }
-
- encoder.output = new byte[output_len];
- encoder.process(input, offset, len, true);
-
- assert encoder.op == output_len;
-
- return encoder.output;
- }
-
- /* package */ static class Encoder extends Coder {
- /**
- * Emit a new line every this many output tuples. Corresponds to
- * a 76-character line length (the maximum allowable according to
- * RFC 2045).
- */
- public static final int LINE_GROUPS = 19;
-
- /**
- * Lookup table for turning Base64 alphabet positions (6 bits)
- * into output bytes.
- */
- private static final byte ENCODE[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
- };
-
- /**
- * Lookup table for turning Base64 alphabet positions (6 bits)
- * into output bytes.
- */
- private static final byte ENCODE_WEBSAFE[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
- 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
- };
-
- final private byte[] tail;
- /* package */ int tailLen;
- private int count;
-
- final public boolean do_padding;
- final public boolean do_newline;
- final public boolean do_cr;
- final private byte[] alphabet;
-
- public Encoder(int flags, byte[] output) {
- this.output = output;
-
- do_padding = (flags & NO_PADDING) == 0;
- do_newline = (flags & NO_WRAP) == 0;
- do_cr = (flags & CRLF) != 0;
- alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
-
- tail = new byte[2];
- tailLen = 0;
-
- count = do_newline ? LINE_GROUPS : -1;
- }
-
- /**
- * @return an overestimate for the number of bytes {@code
- * len} bytes could encode to.
- */
- public int maxOutputSize(int len) {
- return len * 8/5 + 10;
- }
-
- public boolean process(byte[] input, int offset, int len, boolean finish) {
- // Using local variables makes the encoder about 9% faster.
- final byte[] alphabet = this.alphabet;
- final byte[] output = this.output;
- int op = 0;
- int count = this.count;
-
- int p = offset;
- len += offset;
- int v = -1;
-
- // First we need to concatenate the tail of the previous call
- // with any input bytes available now and see if we can empty
- // the tail.
-
- switch (tailLen) {
- case 0:
- // There was no tail.
- break;
-
- case 1:
- if (p+2 <= len) {
- // A 1-byte tail with at least 2 bytes of
- // input available now.
- v = ((tail[0] & 0xff) << 16) |
- ((input[p++] & 0xff) << 8) |
- (input[p++] & 0xff);
- tailLen = 0;
- };
- break;
-
- case 2:
- if (p+1 <= len) {
- // A 2-byte tail with at least 1 byte of input.
- v = ((tail[0] & 0xff) << 16) |
- ((tail[1] & 0xff) << 8) |
- (input[p++] & 0xff);
- tailLen = 0;
- }
- break;
- }
-
- if (v != -1) {
- output[op++] = alphabet[(v >> 18) & 0x3f];
- output[op++] = alphabet[(v >> 12) & 0x3f];
- output[op++] = alphabet[(v >> 6) & 0x3f];
- output[op++] = alphabet[v & 0x3f];
- if (--count == 0) {
- if (do_cr) output[op++] = '\r';
- output[op++] = '\n';
- count = LINE_GROUPS;
- }
- }
-
- // At this point either there is no tail, or there are fewer
- // than 3 bytes of input available.
-
- // The main loop, turning 3 input bytes into 4 output bytes on
- // each iteration.
- while (p+3 <= len) {
- v = ((input[p] & 0xff) << 16) |
- ((input[p+1] & 0xff) << 8) |
- (input[p+2] & 0xff);
- output[op] = alphabet[(v >> 18) & 0x3f];
- output[op+1] = alphabet[(v >> 12) & 0x3f];
- output[op+2] = alphabet[(v >> 6) & 0x3f];
- output[op+3] = alphabet[v & 0x3f];
- p += 3;
- op += 4;
- if (--count == 0) {
- if (do_cr) output[op++] = '\r';
- output[op++] = '\n';
- count = LINE_GROUPS;
- }
- }
-
- if (finish) {
- // Finish up the tail of the input. Note that we need to
- // consume any bytes in tail before any bytes
- // remaining in input; there should be at most two bytes
- // total.
-
- if (p-tailLen == len-1) {
- int t = 0;
- v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
- tailLen -= t;
- output[op++] = alphabet[(v >> 6) & 0x3f];
- output[op++] = alphabet[v & 0x3f];
- if (do_padding) {
- output[op++] = '=';
- output[op++] = '=';
- }
- if (do_newline) {
- if (do_cr) output[op++] = '\r';
- output[op++] = '\n';
- }
- } else if (p-tailLen == len-2) {
- int t = 0;
- v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) |
- (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
- tailLen -= t;
- output[op++] = alphabet[(v >> 12) & 0x3f];
- output[op++] = alphabet[(v >> 6) & 0x3f];
- output[op++] = alphabet[v & 0x3f];
- if (do_padding) {
- output[op++] = '=';
- }
- if (do_newline) {
- if (do_cr) output[op++] = '\r';
- output[op++] = '\n';
- }
- } else if (do_newline && op > 0 && count != LINE_GROUPS) {
- if (do_cr) output[op++] = '\r';
- output[op++] = '\n';
- }
-
- assert tailLen == 0;
- assert p == len;
- } else {
- // Save the leftovers in tail to be consumed on the next
- // call to encodeInternal.
-
- if (p == len-1) {
- tail[tailLen++] = input[p];
- } else if (p == len-2) {
- tail[tailLen++] = input[p];
- tail[tailLen++] = input[p+1];
- }
- }
-
- this.op = op;
- this.count = count;
-
- return true;
- }
- }
-
- private Base64() { } // don't instantiate
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java
index bc95038fc1..6cda006c99 100644
--- a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java
@@ -1,23 +1,22 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.AttachmentId;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.events.PartProgressEvent;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.util.AttachmentUtil;
@@ -37,11 +36,10 @@ import java.io.InputStream;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class AttachmentDownloadJob extends BaseJob implements InjectableType {
+
+ public static final String KEY = "AttachmentDownloadJob";
-public class AttachmentDownloadJob extends ContextJob implements InjectableType {
- private static final long serialVersionUID = 2L;
private static final int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024;
private static final String TAG = AttachmentDownloadJob.class.getSimpleName();
@@ -50,22 +48,27 @@ public class AttachmentDownloadJob extends ContextJob implements InjectableType
private static final String KEY_PAR_UNIQUE_ID = "part_unique_id";
private static final String KEY_MANUAL = "part_manual";
- @Inject transient SignalServiceMessageReceiver messageReceiver;
+ @Inject SignalServiceMessageReceiver messageReceiver;
private long messageId;
private long partRowId;
private long partUniqueId;
private boolean manual;
- public AttachmentDownloadJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public AttachmentDownloadJob(long messageId, AttachmentId attachmentId, boolean manual) {
+ this(new Job.Parameters.Builder()
+ .setQueue("AttachmentDownloadJob" + attachmentId.getRowId() + "-" + attachmentId.getUniqueId())
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(25)
+ .build(),
+ messageId,
+ attachmentId,
+ manual);
+
}
- public AttachmentDownloadJob(Context context, long messageId, AttachmentId attachmentId, boolean manual) {
- super(context, JobParameters.newBuilder()
- .withGroupId(AttachmentDownloadJob.class.getSimpleName() + attachmentId.getRowId() + "-" + attachmentId.getUniqueId())
- .withNetworkRequirement()
- .create());
+ private AttachmentDownloadJob(@NonNull Job.Parameters parameters, long messageId, AttachmentId attachmentId, boolean manual) {
+ super(parameters);
this.messageId = messageId;
this.partRowId = attachmentId.getRowId();
@@ -74,20 +77,17 @@ public class AttachmentDownloadJob extends ContextJob implements InjectableType
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- partRowId = data.getLong(KEY_PART_ROW_ID);
- partUniqueId = data.getLong(KEY_PAR_UNIQUE_ID);
- manual = data.getBoolean(KEY_MANUAL);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putLong(KEY_PART_ROW_ID, partRowId)
+ .putLong(KEY_PAR_UNIQUE_ID, partUniqueId)
+ .putBoolean(KEY_MANUAL, manual)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putLong(KEY_PART_ROW_ID, partRowId)
- .putLong(KEY_PAR_UNIQUE_ID, partUniqueId)
- .putBoolean(KEY_MANUAL, manual)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -242,4 +242,13 @@ public class AttachmentDownloadJob extends ContextJob implements InjectableType
InvalidPartException(Exception e) {super(e);}
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull AttachmentDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new AttachmentDownloadJob(parameters,
+ data.getLong(KEY_MESSAGE_ID),
+ new AttachmentId(data.getLong(KEY_PART_ROW_ID), data.getLong(KEY_PAR_UNIQUE_ID)),
+ data.getBoolean(KEY_MANUAL));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/AttachmentUploadJob.java b/src/org/thoughtcrime/securesms/jobs/AttachmentUploadJob.java
index 2e758f34bd..c9866c390a 100644
--- a/src/org/thoughtcrime/securesms/jobs/AttachmentUploadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/AttachmentUploadJob.java
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.greenrobot.eventbus.EventBus;
@@ -12,8 +11,9 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.events.PartProgressEvent;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MediaStream;
@@ -35,10 +35,9 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.net.ssl.SSLException;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class AttachmentUploadJob extends BaseJob implements InjectableType {
-public class AttachmentUploadJob extends ContextJob implements InjectableType {
+ public static final String KEY = "AttachmentUploadJob";
private static final String TAG = AttachmentUploadJob.class.getSimpleName();
@@ -48,29 +47,30 @@ public class AttachmentUploadJob extends ContextJob implements InjectableType {
private AttachmentId attachmentId;
@Inject SignalServiceMessageSender messageSender;
- public AttachmentUploadJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public AttachmentUploadJob(AttachmentId attachmentId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ attachmentId);
}
- protected AttachmentUploadJob(@NonNull Context context, AttachmentId attachmentId) {
- super(context, new JobParameters.Builder()
- .withNetworkRequirement()
- .withRetryDuration(TimeUnit.DAYS.toMillis(1))
- .create());
-
+ private AttachmentUploadJob(@NonNull Job.Parameters parameters, @NonNull AttachmentId attachmentId) {
+ super(parameters);
this.attachmentId = attachmentId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- this.attachmentId = new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID));
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_ROW_ID, attachmentId.getRowId())
+ .putLong(KEY_UNIQUE_ID, attachmentId.getUniqueId())
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_ROW_ID, attachmentId.getRowId())
- .putLong(KEY_UNIQUE_ID, attachmentId.getUniqueId())
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -92,7 +92,7 @@ public class AttachmentUploadJob extends ContextJob implements InjectableType {
}
@Override
- protected void onCanceled() { }
+ public void onCanceled() { }
@Override
protected boolean onShouldRetry(Exception exception) {
@@ -145,4 +145,11 @@ public class AttachmentUploadJob extends ContextJob implements InjectableType {
throw new UndeliverableMessageException(e);
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull AttachmentUploadJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
+ return new AttachmentUploadJob(parameters, new AttachmentId(data.getLong(KEY_ROW_ID), data.getLong(KEY_UNIQUE_ID)));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
index 2f1af5d214..21ae4b3abe 100644
--- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
@@ -1,16 +1,15 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
import org.thoughtcrime.securesms.util.BitmapDecodingException;
@@ -29,46 +28,41 @@ import java.io.InputStream;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class AvatarDownloadJob extends BaseJob implements InjectableType {
-public class AvatarDownloadJob extends ContextJob implements InjectableType {
-
- private static final int MAX_AVATAR_SIZE = 20 * 1024 * 1024;
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "AvatarDownloadJob";
private static final String TAG = AvatarDownloadJob.class.getSimpleName();
+ private static final int MAX_AVATAR_SIZE = 20 * 1024 * 1024;
+
private static final String KEY_GROUP_ID = "group_id";
- @Inject transient SignalServiceMessageReceiver receiver;
+ @Inject SignalServiceMessageReceiver receiver;
private byte[] groupId;
- public AvatarDownloadJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public AvatarDownloadJob(@NonNull byte[] groupId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(10)
+ .build(),
+ groupId);
}
- public AvatarDownloadJob(Context context, @NonNull byte[] groupId) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .create());
-
+ private AvatarDownloadJob(@NonNull Job.Parameters parameters, @NonNull byte[] groupId) {
+ super(parameters);
this.groupId = groupId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- try {
- groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false)).build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false)).build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -122,4 +116,14 @@ public class AvatarDownloadJob extends ContextJob implements InjectableType {
return false;
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull AvatarDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ try {
+ return new AvatarDownloadJob(parameters, GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID)));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/BaseJob.java b/src/org/thoughtcrime/securesms/jobs/BaseJob.java
new file mode 100644
index 0000000000..9d4e76b032
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/jobs/BaseJob.java
@@ -0,0 +1,36 @@
+package org.thoughtcrime.securesms.jobs;
+
+import android.support.annotation.NonNull;
+
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.JobLogger;
+import org.thoughtcrime.securesms.logging.Log;
+
+public abstract class BaseJob extends Job {
+
+ private static final String TAG = BaseJob.class.getSimpleName();
+
+ public BaseJob(@NonNull Parameters parameters) {
+ super(parameters);
+ }
+
+ @Override
+ public @NonNull Result run() {
+ try {
+ onRun();
+ return Result.SUCCESS;
+ } catch (Exception e) {
+ if (onShouldRetry(e)) {
+ Log.i(TAG, JobLogger.format(this, "Encountered a retryable exception."), e);
+ return Result.RETRY;
+ } else {
+ Log.w(TAG, JobLogger.format(this, "Encountered a failing exception."), e);
+ return Result.FAILURE;
+ }
+ }
+ }
+
+ protected abstract void onRun() throws Exception;
+
+ protected abstract boolean onShouldRetry(@NonNull Exception e);
+}
diff --git a/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java b/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java
index c83377f390..d239a9d7ce 100644
--- a/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/CleanPreKeysJob.java
@@ -1,15 +1,13 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.whispersystems.libsignal.InvalidKeyIdException;
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
import org.whispersystems.libsignal.state.SignedPreKeyStore;
@@ -26,38 +24,38 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
import static org.thoughtcrime.securesms.dependencies.AxolotlStorageModule.SignedPreKeyStoreFactory;
-public class CleanPreKeysJob extends ContextJob implements InjectableType {
+public class CleanPreKeysJob extends BaseJob implements InjectableType {
+
+ public static final String KEY = "CleanPreKeysJob";
private static final String TAG = CleanPreKeysJob.class.getSimpleName();
private static final long ARCHIVE_AGE = TimeUnit.DAYS.toMillis(7);
- @Inject transient SignalServiceAccountManager accountManager;
- @Inject transient SignedPreKeyStoreFactory signedPreKeyStoreFactory;
+ @Inject SignalServiceAccountManager accountManager;
+ @Inject SignedPreKeyStoreFactory signedPreKeyStoreFactory;
- public CleanPreKeysJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public CleanPreKeysJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("CleanPreKeysJob")
+ .setMaxAttempts(5)
+ .build());
}
- public CleanPreKeysJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId(CleanPreKeysJob.class.getSimpleName())
- .withRetryCount(5)
- .create());
+ private CleanPreKeysJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -134,4 +132,10 @@ public class CleanPreKeysJob extends ContextJob implements InjectableType {
}
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull CleanPreKeysJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new CleanPreKeysJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/ContextJob.java b/src/org/thoughtcrime/securesms/jobs/ContextJob.java
deleted file mode 100644
index d9f38e0880..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/ContextJob.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.Job;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-
-import androidx.work.WorkerParameters;
-
-public abstract class ContextJob extends Job implements ContextDependent {
-
- protected transient Context context;
-
- public ContextJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
- protected ContextJob(@NonNull Context context, @NonNull JobParameters parameters) {
- super(context, parameters);
- this.context = context;
- }
-
- public void setContext(Context context) {
- this.context = context;
- }
-
- protected Context getContext() {
- return context;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java b/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java
index c4e7f28dbe..cfb5a9fdf5 100644
--- a/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java
@@ -4,11 +4,11 @@ import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKeyPair;
@@ -20,35 +20,35 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-public class CreateSignedPreKeyJob extends ContextJob implements InjectableType {
+public class CreateSignedPreKeyJob extends BaseJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "CreateSignedPreKeyJob";
private static final String TAG = CreateSignedPreKeyJob.class.getSimpleName();
- @Inject transient SignalServiceAccountManager accountManager;
-
- public CreateSignedPreKeyJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
+ @Inject SignalServiceAccountManager accountManager;
public CreateSignedPreKeyJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(CreateSignedPreKeyJob.class.getSimpleName())
- .create());
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("CreateSignedPreKeyJob")
+ .setMaxAttempts(25)
+ .build());
+ }
+
+ private CreateSignedPreKeyJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -78,4 +78,11 @@ public class CreateSignedPreKeyJob extends ContextJob implements InjectableType
if (exception instanceof PushNetworkException) return true;
return false;
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull CreateSignedPreKeyJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new CreateSignedPreKeyJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java
index 9fa70d9881..a7074187f3 100644
--- a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java
@@ -1,68 +1,66 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
+import android.app.Application;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DirectoryHelper;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class DirectoryRefreshJob extends BaseJob {
-public class DirectoryRefreshJob extends ContextJob {
+ public static final String KEY = "DirectoryRefreshJob";
private static final String TAG = DirectoryRefreshJob.class.getSimpleName();
private static final String KEY_ADDRESS = "address";
private static final String KEY_NOTIFY_OF_NEW_USERS = "notify_of_new_users";
- @Nullable private transient Recipient recipient;
- private transient boolean notifyOfNewUsers;
+ @Nullable private Recipient recipient;
+ private boolean notifyOfNewUsers;
- public DirectoryRefreshJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public DirectoryRefreshJob(boolean notifyOfNewUsers) {
+ this(null, notifyOfNewUsers);
}
- public DirectoryRefreshJob(@NonNull Context context, boolean notifyOfNewUsers) {
- this(context, null, notifyOfNewUsers);
- }
-
- public DirectoryRefreshJob(@NonNull Context context,
- @Nullable Recipient recipient,
- boolean notifyOfNewUsers)
+ public DirectoryRefreshJob(@Nullable Recipient recipient,
+ boolean notifyOfNewUsers)
{
- super(context, JobParameters.newBuilder()
- .withGroupId(DirectoryRefreshJob.class.getSimpleName())
- .withNetworkRequirement()
- .create());
+ this(new Job.Parameters.Builder()
+ .setQueue("DirectoryRefreshJob")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(10)
+ .build(),
+ recipient,
+ notifyOfNewUsers);
+ }
+
+ private DirectoryRefreshJob(@NonNull Job.Parameters parameters, @Nullable Recipient recipient, boolean notifyOfNewUsers) {
+ super(parameters);
this.recipient = recipient;
this.notifyOfNewUsers = notifyOfNewUsers;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- String serializedAddress = data.getString(KEY_ADDRESS);
- Address address = serializedAddress != null ? Address.fromSerialized(serializedAddress) : null;
-
- recipient = address != null ? Recipient.from(context, address, true) : null;
- notifyOfNewUsers = data.getBoolean(KEY_NOTIFY_OF_NEW_USERS);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_ADDRESS, recipient != null ? recipient.getAddress().serialize() : null)
+ .putBoolean(KEY_NOTIFY_OF_NEW_USERS, notifyOfNewUsers)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_ADDRESS, recipient != null ? recipient.getAddress().serialize() : null)
- .putBoolean(KEY_NOTIFY_OF_NEW_USERS, notifyOfNewUsers)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -84,4 +82,23 @@ public class DirectoryRefreshJob extends ContextJob {
@Override
public void onCanceled() {}
+
+ public static final class Factory implements Job.Factory {
+
+ private final Application application;
+
+ public Factory(@NonNull Application application) {
+ this.application = application;
+ }
+
+ @Override
+ public @NonNull DirectoryRefreshJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ String serializedAddress = data.getString(KEY_ADDRESS);
+ Address address = serializedAddress != null ? Address.fromSerialized(serializedAddress) : null;
+ Recipient recipient = address != null ? Recipient.from(application, address, true) : null;
+ boolean notifyOfNewUsers = data.getBoolean(KEY_NOTIFY_OF_NEW_USERS);
+
+ return new DirectoryRefreshJob(parameters, recipient, notifyOfNewUsers);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/FastJobStorage.java b/src/org/thoughtcrime/securesms/jobs/FastJobStorage.java
new file mode 100644
index 0000000000..90a3243aed
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/jobs/FastJobStorage.java
@@ -0,0 +1,259 @@
+package org.thoughtcrime.securesms.jobs;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.annimon.stream.Stream;
+
+import org.thoughtcrime.securesms.database.JobDatabase;
+import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage;
+import org.thoughtcrime.securesms.util.Util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+
+public class FastJobStorage implements JobStorage {
+
+ private final JobDatabase jobDatabase;
+
+ private final List jobs;
+ private final Map> constraintsByJobId;
+ private final Map> dependenciesByJobId;
+
+ public FastJobStorage(@NonNull JobDatabase jobDatabase) {
+ this.jobDatabase = jobDatabase;
+ this.jobs = new ArrayList<>();
+ this.constraintsByJobId = new HashMap<>();
+ this.dependenciesByJobId = new HashMap<>();
+ }
+
+ @Override
+ public synchronized void init() {
+ List jobSpecs = jobDatabase.getAllJobSpecs();
+ List constraintSpecs = jobDatabase.getAllConstraintSpecs();
+ List dependencySpecs = jobDatabase.getAllDependencySpecs();
+
+ jobs.addAll(jobSpecs);
+
+ for (ConstraintSpec constraintSpec: constraintSpecs) {
+ List jobConstraints = Util.getOrDefault(constraintsByJobId, constraintSpec.getJobSpecId(), new LinkedList<>());
+ jobConstraints.add(constraintSpec);
+ constraintsByJobId.put(constraintSpec.getJobSpecId(), jobConstraints);
+ }
+
+ for (DependencySpec dependencySpec : dependencySpecs) {
+ List jobDependencies = Util.getOrDefault(dependenciesByJobId, dependencySpec.getJobId(), new LinkedList<>());
+ jobDependencies.add(dependencySpec);
+ dependenciesByJobId.put(dependencySpec.getJobId(), jobDependencies);
+ }
+ }
+
+ @Override
+ public synchronized void insertJobs(@NonNull List fullSpecs) {
+ jobDatabase.insertJobs(fullSpecs);
+
+ for (FullSpec fullSpec : fullSpecs) {
+ jobs.add(fullSpec.getJobSpec());
+ constraintsByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getConstraintSpecs());
+ dependenciesByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getDependencySpecs());
+ }
+ }
+
+ @Override
+ public synchronized @Nullable JobSpec getJobSpec(@NonNull String id) {
+ for (JobSpec jobSpec : jobs) {
+ if (jobSpec.getId().equals(id)) {
+ return jobSpec;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public synchronized @NonNull List getAllJobSpecs() {
+ return new ArrayList<>(jobs);
+ }
+
+ @Override
+ public synchronized @NonNull List getPendingJobsWithNoDependenciesInCreatedOrder(long currentTime) {
+ return Stream.of(jobs)
+ .filterNot(JobSpec::isRunning)
+ .filter(this::firstInQueue)
+ .filter(j -> !dependenciesByJobId.containsKey(j.getId()) || dependenciesByJobId.get(j.getId()).isEmpty())
+ .filter(j -> j.getNextRunAttemptTime() <= currentTime)
+ .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime()))
+ .toList();
+ }
+
+ private boolean firstInQueue(@NonNull JobSpec job) {
+ if (job.getQueueKey() == null) {
+ return true;
+ }
+
+ return Stream.of(jobs)
+ .filter(j -> Util.equals(j.getQueueKey(), job.getQueueKey()))
+ .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime()))
+ .toList()
+ .get(0)
+ .equals(job);
+ }
+
+ @Override
+ public synchronized int getJobInstanceCount(@NonNull String factoryKey) {
+ return (int) Stream.of(jobs)
+ .filter(j -> j.getFactoryKey().equals(factoryKey))
+ .count();
+ }
+
+ @Override
+ public synchronized void updateJobRunningState(@NonNull String id, boolean isRunning) {
+ jobDatabase.updateJobRunningState(id, isRunning);
+
+ ListIterator iter = jobs.listIterator();
+
+ while (iter.hasNext()) {
+ JobSpec existing = iter.next();
+ if (existing.getId().equals(id)) {
+ JobSpec updated = new JobSpec(existing.getId(),
+ existing.getFactoryKey(),
+ existing.getQueueKey(),
+ existing.getCreateTime(),
+ existing.getNextRunAttemptTime(),
+ existing.getRunAttempt(),
+ existing.getMaxAttempts(),
+ existing.getMaxBackoff(),
+ existing.getLifespan(),
+ existing.getMaxInstances(),
+ existing.getSerializedData(),
+ isRunning);
+ iter.set(updated);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime) {
+ jobDatabase.updateJobAfterRetry(id, isRunning, runAttempt, nextRunAttemptTime);
+
+ ListIterator iter = jobs.listIterator();
+
+ while (iter.hasNext()) {
+ JobSpec existing = iter.next();
+ if (existing.getId().equals(id)) {
+ JobSpec updated = new JobSpec(existing.getId(),
+ existing.getFactoryKey(),
+ existing.getQueueKey(),
+ existing.getCreateTime(),
+ nextRunAttemptTime,
+ runAttempt,
+ existing.getMaxAttempts(),
+ existing.getMaxBackoff(),
+ existing.getLifespan(),
+ existing.getMaxInstances(),
+ existing.getSerializedData(),
+ isRunning);
+ iter.set(updated);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void updateAllJobsToBePending() {
+ jobDatabase.updateAllJobsToBePending();
+
+ ListIterator iter = jobs.listIterator();
+
+ while (iter.hasNext()) {
+ JobSpec existing = iter.next();
+ JobSpec updated = new JobSpec(existing.getId(),
+ existing.getFactoryKey(),
+ existing.getQueueKey(),
+ existing.getCreateTime(),
+ existing.getNextRunAttemptTime(),
+ existing.getRunAttempt(),
+ existing.getMaxAttempts(),
+ existing.getMaxBackoff(),
+ existing.getLifespan(),
+ existing.getMaxInstances(),
+ existing.getSerializedData(),
+ false);
+ iter.set(updated);
+ }
+ }
+
+ @Override
+ public synchronized void deleteJob(@NonNull String jobId) {
+ deleteJobs(Collections.singletonList(jobId));
+ }
+
+ @Override
+ public synchronized void deleteJobs(@NonNull List jobIds) {
+ jobDatabase.deleteJobs(jobIds);
+
+ Set deleteIds = new HashSet<>(jobIds);
+
+ Iterator jobIter = jobs.iterator();
+ while (jobIter.hasNext()) {
+ if (deleteIds.contains(jobIter.next().getId())) {
+ jobIter.remove();
+ }
+ }
+
+ for (String jobId : jobIds) {
+ constraintsByJobId.remove(jobId);
+ dependenciesByJobId.remove(jobId);
+
+ for (Map.Entry> entry : dependenciesByJobId.entrySet()) {
+ Iterator depedencyIter = entry.getValue().iterator();
+
+ while (depedencyIter.hasNext()) {
+ if (depedencyIter.next().getDependsOnJobId().equals(jobId)) {
+ depedencyIter.remove();
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public synchronized @NonNull List getConstraintSpecs(@NonNull String jobId) {
+ return Util.getOrDefault(constraintsByJobId, jobId, new LinkedList<>());
+ }
+
+ @Override
+ public synchronized @NonNull List getAllConstraintSpecs() {
+ return Stream.of(constraintsByJobId)
+ .map(Map.Entry::getValue)
+ .flatMap(Stream::of)
+ .toList();
+ }
+
+ @Override
+ public synchronized @NonNull List getDependencySpecsThatDependOnJob(@NonNull String jobSpecId) {
+ return Stream.of(dependenciesByJobId.entrySet())
+ .map(Map.Entry::getValue)
+ .flatMap(Stream::of)
+ .filter(j -> j.getDependsOnJobId().equals(jobSpecId))
+ .toList();
+ }
+
+ @Override
+ public @NonNull List getAllDependencySpecs() {
+ return Stream.of(dependenciesByJobId)
+ .map(Map.Entry::getValue)
+ .flatMap(Stream::of)
+ .toList();
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java
index 8a16b4acb6..245a222ea4 100644
--- a/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/FcmRefreshJob.java
@@ -28,13 +28,14 @@ import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import org.thoughtcrime.securesms.gcm.FcmUtil;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.PlayServicesProblemActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -43,38 +44,40 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class FcmRefreshJob extends BaseJob implements InjectableType {
-public class FcmRefreshJob extends ContextJob implements InjectableType {
+ public static final String KEY = "FcmRefreshJob";
private static final String TAG = FcmRefreshJob.class.getSimpleName();
- @Inject transient SignalServiceAccountManager textSecureAccountManager;
+ @Inject SignalServiceAccountManager textSecureAccountManager;
- public FcmRefreshJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public FcmRefreshJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("FcmRefreshJob")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(1)
+ .setLifespan(TimeUnit.MINUTES.toMillis(5))
+ .setMaxInstances(1)
+ .build());
}
- public FcmRefreshJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId(FcmRefreshJob.class.getSimpleName())
- .withDuplicatesIgnored(true)
- .withNetworkRequirement()
- .withRetryCount(1)
- .create());
+ private FcmRefreshJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -139,4 +142,10 @@ public class FcmRefreshJob extends ContextJob implements InjectableType {
.notify(12, builder.build());
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull FcmRefreshJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new FcmRefreshJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
new file mode 100644
index 0000000000..8a5912cf8d
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/jobs/JobManagerFactories.java
@@ -0,0 +1,86 @@
+package org.thoughtcrime.securesms.jobs;
+
+import android.app.Application;
+import android.support.annotation.NonNull;
+
+import org.thoughtcrime.securesms.jobmanager.Constraint;
+import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public final class JobManagerFactories {
+
+ public static Map getJobFactories(@NonNull Application application) {
+ return new HashMap() {{
+ put(AttachmentDownloadJob.KEY, new AttachmentDownloadJob.Factory());
+ put(AttachmentUploadJob.KEY, new AttachmentUploadJob.Factory());
+ put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory());
+ put(CleanPreKeysJob.KEY, new CleanPreKeysJob.Factory());
+ put(CreateSignedPreKeyJob.KEY, new CreateSignedPreKeyJob.Factory());
+ put(DirectoryRefreshJob.KEY, new DirectoryRefreshJob.Factory(application));
+ put(FcmRefreshJob.KEY, new FcmRefreshJob.Factory());
+ put(LocalBackupJob.KEY, new LocalBackupJob.Factory());
+ put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
+ put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory());
+ put(MmsSendJob.KEY, new MmsSendJob.Factory());
+ put(MultiDeviceBlockedUpdateJob.KEY, new MultiDeviceBlockedUpdateJob.Factory());
+ put(MultiDeviceConfigurationUpdateJob.KEY, new MultiDeviceConfigurationUpdateJob.Factory());
+ put(MultiDeviceContactUpdateJob.KEY, new MultiDeviceContactUpdateJob.Factory());
+ put(MultiDeviceGroupUpdateJob.KEY, new MultiDeviceGroupUpdateJob.Factory());
+ put(MultiDeviceProfileKeyUpdateJob.KEY, new MultiDeviceProfileKeyUpdateJob.Factory());
+ put(MultiDeviceReadUpdateJob.KEY, new MultiDeviceReadUpdateJob.Factory());
+ put(MultiDeviceVerifiedUpdateJob.KEY, new MultiDeviceVerifiedUpdateJob.Factory());
+ put(PushContentReceiveJob.KEY, new PushContentReceiveJob.Factory());
+ put(PushDecryptJob.KEY, new PushDecryptJob.Factory());
+ put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory());
+ put(PushGroupUpdateJob.KEY, new PushGroupUpdateJob.Factory());
+ put(PushMediaSendJob.KEY, new PushMediaSendJob.Factory());
+ put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory());
+ put(PushTextSendJob.KEY, new PushTextSendJob.Factory());
+ put(RefreshAttributesJob.KEY, new RefreshAttributesJob.Factory());
+ put(RefreshPreKeysJob.KEY, new RefreshPreKeysJob.Factory());
+ put(RefreshUnidentifiedDeliveryAbilityJob.KEY, new RefreshUnidentifiedDeliveryAbilityJob.Factory());
+ put(RequestGroupInfoJob.KEY, new RequestGroupInfoJob.Factory());
+ put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application));
+ put(RetrieveProfileJob.KEY, new RetrieveProfileJob.Factory(application));
+ put(RotateCertificateJob.KEY, new RotateCertificateJob.Factory());
+ put(RotateProfileKeyJob.KEY, new RotateProfileKeyJob.Factory());
+ put(RotateSignedPreKeyJob.KEY, new RotateSignedPreKeyJob.Factory());
+ put(SendDeliveryReceiptJob.KEY, new SendDeliveryReceiptJob.Factory());
+ put(SendReadReceiptJob.KEY, new SendReadReceiptJob.Factory());
+ put(ServiceOutageDetectionJob.KEY, new ServiceOutageDetectionJob.Factory());
+ put(SmsReceiveJob.KEY, new SmsReceiveJob.Factory());
+ put(SmsSendJob.KEY, new SmsSendJob.Factory());
+ put(SmsSentJob.KEY, new SmsSentJob.Factory());
+ put(TrimThreadJob.KEY, new TrimThreadJob.Factory());
+ put(TypingSendJob.KEY, new TypingSendJob.Factory());
+ put(UpdateApkJob.KEY, new UpdateApkJob.Factory());
+ }};
+ }
+
+ public static Map getConstraintFactories(@NonNull Application application) {
+ return new HashMap() {{
+ put(CellServiceConstraint.KEY, new CellServiceConstraint.Factory(application));
+ put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application));
+ put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application));
+ put(SqlCipherMigrationConstraint.KEY, new SqlCipherMigrationConstraint.Factory(application));
+ }};
+ }
+
+ public static List getConstraintObservers(@NonNull Application application) {
+ return Arrays.asList(new CellServiceConstraintObserver(application),
+ new NetworkConstraintObserver(application),
+ new SqlCipherMigrationConstraintObserver());
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
index a3b956ba32..4fe6ecf613 100644
--- a/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/LocalBackupJob.java
@@ -2,11 +2,11 @@ package org.thoughtcrime.securesms.jobs;
import android.Manifest;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.backup.BackupPassphrase;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.R;
@@ -14,13 +14,11 @@ import org.thoughtcrime.securesms.backup.FullBackupExporter;
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoExternalStorageException;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.util.BackupUtil;
import org.thoughtcrime.securesms.util.StorageUtil;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.File;
import java.io.IOException;
@@ -28,31 +26,32 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class LocalBackupJob extends BaseJob {
-public class LocalBackupJob extends ContextJob {
+ public static final String KEY = "LocalBackupJob";
private static final String TAG = LocalBackupJob.class.getSimpleName();
- public LocalBackupJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public LocalBackupJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("__LOCAL_BACKUP__")
+ .setMaxInstances(1)
+ .setMaxAttempts(3)
+ .build());
}
- public LocalBackupJob(@NonNull Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId("__LOCAL_BACKUP__")
- .withDuplicatesIgnored(true)
- .create());
+ private LocalBackupJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -109,6 +108,12 @@ public class LocalBackupJob extends ContextJob {
@Override
public void onCanceled() {
+ }
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull LocalBackupJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new LocalBackupJob(parameters);
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
index 603f250261..e418d416a1 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsDownloadJob.java
@@ -1,11 +1,11 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import com.google.android.mms.pdu_alt.CharacterSets;
@@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
@@ -46,12 +45,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MmsDownloadJob extends BaseJob {
-public class MmsDownloadJob extends ContextJob {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "MmsDownloadJob";
private static final String TAG = MmsDownloadJob.class.getSimpleName();
@@ -63,14 +59,19 @@ public class MmsDownloadJob extends ContextJob {
private long threadId;
private boolean automatic;
- public MmsDownloadJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MmsDownloadJob(long messageId, long threadId, boolean automatic) {
+ this(new Job.Parameters.Builder()
+ .setQueue("mms-operation")
+ .setMaxAttempts(25)
+ .build(),
+ messageId,
+ threadId,
+ automatic);
+
}
- public MmsDownloadJob(Context context, long messageId, long threadId, boolean automatic) {
- super(context, JobParameters.newBuilder()
- .withGroupId("mms-operation")
- .create());
+ private MmsDownloadJob(@NonNull Job.Parameters parameters, long messageId, long threadId, boolean automatic) {
+ super(parameters);
this.messageId = messageId;
this.threadId = threadId;
@@ -78,18 +79,16 @@ public class MmsDownloadJob extends ContextJob {
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- threadId = data.getLong(KEY_THREAD_ID);
- automatic = data.getBoolean(KEY_AUTOMATIC);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putLong(KEY_THREAD_ID, threadId)
+ .putBoolean(KEY_AUTOMATIC, automatic)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putLong(KEY_THREAD_ID, threadId)
- .putBoolean(KEY_AUTOMATIC, automatic)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -269,4 +268,14 @@ public class MmsDownloadJob extends ContextJob {
MessageNotifier.updateNotification(context, threadId);
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MmsDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MmsDownloadJob(parameters,
+ data.getLong(KEY_MESSAGE_ID),
+ data.getLong(KEY_THREAD_ID),
+ data.getBoolean(KEY_AUTOMATIC));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
index 7518e3e052..d445ba5683 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsReceiveJob.java
@@ -1,8 +1,7 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
-
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import android.support.annotation.NonNull;
@@ -17,19 +16,15 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.Util;
import java.io.IOException;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MmsReceiveJob extends BaseJob {
-public class MmsReceiveJob extends ContextJob {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "MmsReceiveJob";
private static final String TAG = MmsReceiveJob.class.getSimpleName();
@@ -39,32 +34,27 @@ public class MmsReceiveJob extends ContextJob {
private byte[] data;
private int subscriptionId;
- public MmsReceiveJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MmsReceiveJob(byte[] data, int subscriptionId) {
+ this(new Job.Parameters.Builder().setMaxAttempts(25).build(), data, subscriptionId);
}
- public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
- super(context, JobParameters.newBuilder().create());
+ private MmsReceiveJob(@NonNull Job.Parameters parameters, byte[] data, int subscriptionId) {
+ super(parameters);
this.data = data;
this.subscriptionId = subscriptionId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- try {
- this.data = Base64.decode(data.getString(KEY_DATA));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_DATA, Base64.encodeBytes(data))
+ .putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_DATA, Base64.encodeBytes(data))
- .putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -91,8 +81,7 @@ public class MmsReceiveJob extends ContextJob {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MmsDownloadJob(context,
- messageAndThreadId.first,
+ .add(new MmsDownloadJob(messageAndThreadId.first,
messageAndThreadId.second,
true));
} else if (isNotification(pdu)) {
@@ -122,4 +111,15 @@ public class MmsReceiveJob extends ContextJob {
private boolean isNotification(GenericPdu pdu) {
return pdu != null && pdu.getMessageType() == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MmsReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ try {
+ return new MmsReceiveJob(parameters, Base64.decode(data.getString(KEY_DATA)), data.getInt(KEY_SUBSCRIPTION_ID));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
index aa9fc8be1b..bacda8b029 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
@@ -4,7 +4,9 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.text.TextUtils;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import android.webkit.MimeTypeMap;
@@ -28,7 +30,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.ThreadDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MmsException;
@@ -49,12 +50,9 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class MmsSendJob extends SendJob {
- private static final long serialVersionUID = 0L;
+ public static final String KEY = "MmsSendJob";
private static final String TAG = MmsSendJob.class.getSimpleName();
@@ -62,28 +60,28 @@ public class MmsSendJob extends SendJob {
private long messageId;
- public MmsSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MmsSendJob(long messageId) {
+ this(new Job.Parameters.Builder()
+ .setQueue("mms-operation")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(15)
+ .build(),
+ messageId);
}
- public MmsSendJob(Context context, long messageId) {
- super(context, JobParameters.newBuilder()
- .withGroupId("mms-operation")
- .withNetworkRequirement()
- .withRetryCount(15)
- .create());
-
+ private MmsSendJob(@NonNull Job.Parameters parameters, long messageId) {
+ super(parameters);
this.messageId = messageId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId).build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -318,4 +316,11 @@ public class MmsSendJob extends SendJob {
throw new UndeliverableMessageException(e);
}
}
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull MmsSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MmsSendJob(parameters, data.getLong(KEY_MESSAGE_ID));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
index 81e2831353..f575a63b7e 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java
@@ -1,16 +1,15 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientReader;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -24,39 +23,40 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceBlockedUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceBlockedUpdateJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "MultiDeviceBlockedUpdateJob";
@SuppressWarnings("unused")
private static final String TAG = MultiDeviceBlockedUpdateJob.class.getSimpleName();
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
- public MultiDeviceBlockedUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MultiDeviceBlockedUpdateJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("MultiDeviceBlockedUpdateJob")
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build());
}
- public MultiDeviceBlockedUpdateJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(MultiDeviceBlockedUpdateJob.class.getSimpleName())
- .create());
+ private MultiDeviceBlockedUpdateJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -97,6 +97,12 @@ public class MultiDeviceBlockedUpdateJob extends ContextJob implements Injectabl
@Override
public void onCanceled() {
+ }
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceBlockedUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MultiDeviceBlockedUpdateJob(parameters);
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceConfigurationUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceConfigurationUpdateJob.java
index fe09ad61ff..b960815578 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceConfigurationUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceConfigurationUpdateJob.java
@@ -1,13 +1,13 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -21,12 +21,9 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceConfigurationUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceConfigurationUpdateJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "MultiDeviceConfigurationUpdateJob";
private static final String TAG = MultiDeviceConfigurationUpdateJob.class.getSimpleName();
@@ -35,27 +32,37 @@ public class MultiDeviceConfigurationUpdateJob extends ContextJob implements Inj
private static final String KEY_UNIDENTIFIED_DELIVERY_INDICATORS_ENABLED = "unidentified_delivery_indicators_enabled";
private static final String KEY_LINK_PREVIEWS_ENABLED = "link_previews_enabled";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private boolean readReceiptsEnabled;
private boolean typingIndicatorsEnabled;
private boolean unidentifiedDeliveryIndicatorsEnabled;
private boolean linkPreviewsEnabled;
- public MultiDeviceConfigurationUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
- public MultiDeviceConfigurationUpdateJob(Context context,
- boolean readReceiptsEnabled,
+ public MultiDeviceConfigurationUpdateJob(boolean readReceiptsEnabled,
boolean typingIndicatorsEnabled,
boolean unidentifiedDeliveryIndicatorsEnabled,
boolean linkPreviewsEnabled)
{
- super(context, JobParameters.newBuilder()
- .withGroupId("__MULTI_DEVICE_CONFIGURATION_UPDATE_JOB__")
- .withNetworkRequirement()
- .create());
+ this(new Job.Parameters.Builder()
+ .setQueue("__MULTI_DEVICE_CONFIGURATION_UPDATE_JOB__")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(10)
+ .build(),
+ readReceiptsEnabled,
+ typingIndicatorsEnabled,
+ unidentifiedDeliveryIndicatorsEnabled,
+ linkPreviewsEnabled);
+
+ }
+
+ private MultiDeviceConfigurationUpdateJob(@NonNull Job.Parameters parameters,
+ boolean readReceiptsEnabled,
+ boolean typingIndicatorsEnabled,
+ boolean unidentifiedDeliveryIndicatorsEnabled,
+ boolean linkPreviewsEnabled)
+ {
+ super(parameters);
this.readReceiptsEnabled = readReceiptsEnabled;
this.typingIndicatorsEnabled = typingIndicatorsEnabled;
@@ -64,20 +71,17 @@ public class MultiDeviceConfigurationUpdateJob extends ContextJob implements Inj
}
@Override
- protected void initialize(@NonNull SafeData data) {
- readReceiptsEnabled = data.getBoolean(KEY_READ_RECEIPTS_ENABLED);
- typingIndicatorsEnabled = data.getBoolean(KEY_TYPING_INDICATORS_ENABLED);
- unidentifiedDeliveryIndicatorsEnabled = data.getBoolean(KEY_UNIDENTIFIED_DELIVERY_INDICATORS_ENABLED);
- linkPreviewsEnabled = data.getBoolean(KEY_LINK_PREVIEWS_ENABLED);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putBoolean(KEY_READ_RECEIPTS_ENABLED, readReceiptsEnabled)
+ .putBoolean(KEY_TYPING_INDICATORS_ENABLED, typingIndicatorsEnabled)
+ .putBoolean(KEY_UNIDENTIFIED_DELIVERY_INDICATORS_ENABLED, unidentifiedDeliveryIndicatorsEnabled)
+ .putBoolean(KEY_LINK_PREVIEWS_ENABLED, linkPreviewsEnabled)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putBoolean(KEY_READ_RECEIPTS_ENABLED, readReceiptsEnabled)
- .putBoolean(KEY_TYPING_INDICATORS_ENABLED, typingIndicatorsEnabled)
- .putBoolean(KEY_UNIDENTIFIED_DELIVERY_INDICATORS_ENABLED, unidentifiedDeliveryIndicatorsEnabled)
- .putBoolean(KEY_LINK_PREVIEWS_ENABLED, linkPreviewsEnabled)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -103,4 +107,15 @@ public class MultiDeviceConfigurationUpdateJob extends ContextJob implements Inj
public void onCanceled() {
Log.w(TAG, "**** Failed to synchronize read receipts state!");
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceConfigurationUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MultiDeviceConfigurationUpdateJob(parameters,
+ data.getBooleanOrDefault(KEY_READ_RECEIPTS_ENABLED, false),
+ data.getBooleanOrDefault(KEY_TYPING_INDICATORS_ENABLED, false),
+ data.getBooleanOrDefault(KEY_UNIDENTIFIED_DELIVERY_INDICATORS_ENABLED, false),
+ data.getBooleanOrDefault(KEY_LINK_PREVIEWS_ENABLED, false));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
index 2ed85cfabf..d39bd68254 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
@@ -5,7 +5,6 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Build;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -19,8 +18,9 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.Recipient;
@@ -49,12 +49,9 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceContactUpdateJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 2L;
+ public static final String KEY = "MultiDeviceContactUpdateJob";
private static final String TAG = MultiDeviceContactUpdateJob.class.getSimpleName();
@@ -63,16 +60,12 @@ public class MultiDeviceContactUpdateJob extends ContextJob implements Injectabl
private static final String KEY_ADDRESS = "address";
private static final String KEY_FORCE_SYNC = "force_sync";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private @Nullable String address;
private boolean forceSync;
- public MultiDeviceContactUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
public MultiDeviceContactUpdateJob(@NonNull Context context) {
this(context, false);
}
@@ -86,10 +79,18 @@ public class MultiDeviceContactUpdateJob extends ContextJob implements Injectabl
}
public MultiDeviceContactUpdateJob(@NonNull Context context, @Nullable Address address, boolean forceSync) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(MultiDeviceContactUpdateJob.class.getSimpleName())
- .create());
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("MultiDeviceContactUpdateJob")
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ address,
+ forceSync);
+ }
+
+ private MultiDeviceContactUpdateJob(@NonNull Job.Parameters parameters, @Nullable Address address, boolean forceSync) {
+ super(parameters);
this.forceSync = forceSync;
@@ -98,16 +99,15 @@ public class MultiDeviceContactUpdateJob extends ContextJob implements Injectabl
}
@Override
- protected void initialize(@NonNull SafeData data) {
- address = data.getString(KEY_ADDRESS);
- forceSync = data.getBoolean(KEY_FORCE_SYNC);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_ADDRESS, address)
+ .putBoolean(KEY_FORCE_SYNC, forceSync)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_ADDRESS, address)
- .putBoolean(KEY_FORCE_SYNC, forceSync)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -335,4 +335,13 @@ public class MultiDeviceContactUpdateJob extends ContextJob implements Injectabl
}
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceContactUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ String serialized = data.getString(KEY_ADDRESS);
+ Address address = serialized != null ? Address.fromSerialized(serialized) : null;
+
+ return new MultiDeviceContactUpdateJob(parameters, address, data.getBoolean(KEY_FORCE_SYNC));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
index 22953b7ee3..3611ef6c55 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceGroupUpdateJob.java
@@ -1,20 +1,19 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.GroupUtil;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@@ -33,37 +32,39 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceGroupUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceGroupUpdateJob extends ContextJob implements InjectableType {
+ public static final String KEY = "MultiDeviceGroupUpdateJob";
- private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceGroupUpdateJob.class.getSimpleName();
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
- public MultiDeviceGroupUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MultiDeviceGroupUpdateJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("MultiDeviceGroupUpdateJob")
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build());
}
- public MultiDeviceGroupUpdateJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(MultiDeviceGroupUpdateJob.class.getSimpleName())
- .create());
+ private MultiDeviceGroupUpdateJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
@@ -160,5 +161,10 @@ public class MultiDeviceGroupUpdateJob extends ContextJob implements InjectableT
return file;
}
-
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceGroupUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MultiDeviceGroupUpdateJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java
index f9782d60f8..593479a2a0 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceProfileKeyUpdateJob.java
@@ -1,17 +1,16 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@@ -27,51 +26,53 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceProfileKeyUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceProfileKeyUpdateJob extends ContextJob implements InjectableType {
+ public static String KEY = "MultiDeviceProfileKeyUpdateJob";
- private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceProfileKeyUpdateJob.class.getSimpleName();
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
- public MultiDeviceProfileKeyUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MultiDeviceProfileKeyUpdateJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("MultiDeviceProfileKeyUpdateJob")
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build());
}
- public MultiDeviceProfileKeyUpdateJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(MultiDeviceProfileKeyUpdateJob.class.getSimpleName())
- .create());
+ private MultiDeviceProfileKeyUpdateJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
public void onRun() throws IOException, UntrustedIdentityException {
- if (!TextSecurePreferences.isMultiDevice(getContext())) {
+ if (!TextSecurePreferences.isMultiDevice(context)) {
Log.i(TAG, "Not multi device...");
return;
}
- Optional profileKey = Optional.of(ProfileKeyUtil.getProfileKey(getContext()));
+ Optional profileKey = Optional.of(ProfileKeyUtil.getProfileKey(context));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DeviceContactsOutputStream out = new DeviceContactsOutputStream(baos);
- out.write(new DeviceContact(TextSecurePreferences.getLocalNumber(getContext()),
+ out.write(new DeviceContact(TextSecurePreferences.getLocalNumber(context),
Optional.absent(),
Optional.absent(),
Optional.absent(),
@@ -101,4 +102,11 @@ public class MultiDeviceProfileKeyUpdateJob extends ContextJob implements Inject
public void onCanceled() {
Log.w(TAG, "Profile key sync failed!");
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceProfileKeyUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new MultiDeviceProfileKeyUpdateJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java
deleted file mode 100644
index dac32d10f2..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadReceiptUpdateJob.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package org.thoughtcrime.securesms.jobs;
-
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
-import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
-import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.libsignal.util.guava.Optional;
-import org.whispersystems.signalservice.api.SignalServiceMessageSender;
-import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
-import org.whispersystems.signalservice.api.messages.multidevice.ConfigurationMessage;
-import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
-import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
-
-import java.io.IOException;
-
-import javax.inject.Inject;
-
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
-/**
- * Use {@link MultiDeviceConfigurationUpdateJob}.
- */
-@Deprecated
-public class MultiDeviceReadReceiptUpdateJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
-
- private static final String TAG = MultiDeviceReadReceiptUpdateJob.class.getSimpleName();
-
- private static final String KEY_ENABLED = "enabled";
-
- @Inject transient SignalServiceMessageSender messageSender;
-
- private boolean enabled;
-
- public MultiDeviceReadReceiptUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
- public MultiDeviceReadReceiptUpdateJob(Context context, boolean enabled) {
- super(context, JobParameters.newBuilder()
- .withGroupId("__MULTI_DEVICE_READ_RECEIPT_UPDATE_JOB__")
- .withNetworkRequirement()
- .create());
-
- this.enabled = enabled;
- }
-
- @Override
- protected void initialize(@NonNull SafeData data) {
- enabled = data.getBoolean(KEY_ENABLED);
- }
-
- @Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putBoolean(KEY_ENABLED, enabled).build();
- }
-
- @Override
- public void onRun() throws IOException, UntrustedIdentityException {
- if (!TextSecurePreferences.isMultiDevice(context)) {
- Log.i(TAG, "Not multi device, aborting...");
- return;
- }
-
- messageSender.sendMessage(SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.of(enabled), Optional.absent(), Optional.absent(), Optional.absent())),
- UnidentifiedAccessUtil.getAccessForSync(context));
- }
-
- @Override
- public boolean onShouldRetry(Exception e) {
- return e instanceof PushNetworkException;
- }
-
- @Override
- public void onCanceled() {
- Log.w(TAG, "**** Failed to synchronize read receipts state!");
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
index 9df30509cc..82e269c899 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceReadUpdateJob.java
@@ -1,21 +1,21 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
+import com.annimon.stream.Stream;
import com.fasterxml.jackson.annotation.JsonProperty;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.database.Address;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.multidevice.ReadMessage;
@@ -24,34 +24,35 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.IOException;
import java.io.Serializable;
-import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceReadUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceReadUpdateJob extends ContextJob implements InjectableType {
+ public static final String KEY = "MultiDeviceReadUpdateJob";
- private static final long serialVersionUID = 1L;
private static final String TAG = MultiDeviceReadUpdateJob.class.getSimpleName();
private static final String KEY_MESSAGE_IDS = "message_ids";
private List messageIds;
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
- public MultiDeviceReadUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MultiDeviceReadUpdateJob(List messageIds) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ messageIds);
}
- public MultiDeviceReadUpdateJob(Context context, List messageIds) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .create());
+ private MultiDeviceReadUpdateJob(@NonNull Job.Parameters parameters, @NonNull List messageIds) {
+ super(parameters);
this.messageIds = new LinkedList<>();
@@ -61,21 +62,7 @@ public class MultiDeviceReadUpdateJob extends ContextJob implements InjectableTy
}
@Override
- protected void initialize(@NonNull SafeData data) {
- String[] ids = data.getStringArray(KEY_MESSAGE_IDS);
-
- messageIds = new ArrayList<>(ids.length);
- for (String id : ids) {
- try {
- messageIds.add(JsonUtils.fromJson(id, SerializableSyncMessageId.class));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
- }
-
- @Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
+ public @NonNull Data serialize() {
String[] ids = new String[messageIds.size()];
for (int i = 0; i < ids.length; i++) {
@@ -86,7 +73,12 @@ public class MultiDeviceReadUpdateJob extends ContextJob implements InjectableTy
}
}
- return dataBuilder.putStringArray(KEY_MESSAGE_IDS, ids).build();
+ return new Data.Builder().putStringArray(KEY_MESSAGE_IDS, ids).build();
+ }
+
+ @Override
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -130,4 +122,23 @@ public class MultiDeviceReadUpdateJob extends ContextJob implements InjectableTy
this.timestamp = timestamp;
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceReadUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ List ids = Stream.of(data.getStringArray(KEY_MESSAGE_IDS))
+ .map(id -> {
+ try {
+ return JsonUtils.fromJson(id, SerializableSyncMessageId.class);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ })
+ .map(id -> new SyncMessageId(Address.fromSerialized(id.sender), id.timestamp))
+ .toList();
+
+ return new MultiDeviceReadUpdateJob(parameters, ids);
+
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
index 862a117b39..a23fa062f3 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceVerifiedUpdateJob.java
@@ -1,19 +1,18 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.util.Base64;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKey;
@@ -25,15 +24,13 @@ import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class MultiDeviceVerifiedUpdateJob extends BaseJob implements InjectableType {
-public class MultiDeviceVerifiedUpdateJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "MultiDeviceVerifiedUpdateJob";
private static final String TAG = MultiDeviceVerifiedUpdateJob.class.getSimpleName();
@@ -42,50 +39,52 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
private static final String KEY_VERIFIED_STATUS = "verified_status";
private static final String KEY_TIMESTAMP = "timestamp";
- @Inject
- transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private String destination;
private byte[] identityKey;
private VerifiedStatus verifiedStatus;
private long timestamp;
- public MultiDeviceVerifiedUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public MultiDeviceVerifiedUpdateJob(Address destination, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("__MULTI_DEVICE_VERIFIED_UPDATE__")
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ destination,
+ identityKey.serialize(),
+ verifiedStatus,
+ System.currentTimeMillis());
}
- public MultiDeviceVerifiedUpdateJob(Context context, Address destination, IdentityKey identityKey, VerifiedStatus verifiedStatus) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId("__MULTI_DEVICE_VERIFIED_UPDATE__")
- .create());
+ private MultiDeviceVerifiedUpdateJob(@NonNull Job.Parameters parameters,
+ @NonNull Address destination,
+ @NonNull byte[] identityKey,
+ @NonNull VerifiedStatus verifiedStatus,
+ long timestamp)
+ {
+ super(parameters);
this.destination = destination.serialize();
- this.identityKey = identityKey.serialize();
+ this.identityKey = identityKey;
this.verifiedStatus = verifiedStatus;
- this.timestamp = System.currentTimeMillis();
+ this.timestamp = timestamp;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- destination = data.getString(KEY_DESTINATION);
- verifiedStatus = VerifiedStatus.forState(data.getInt(KEY_VERIFIED_STATUS));
- timestamp = data.getLong(KEY_TIMESTAMP);
-
- try {
- identityKey = Base64.decode(data.getString(KEY_IDENTITY_KEY));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_DESTINATION, destination)
+ .putString(KEY_IDENTITY_KEY, Base64.encodeBytes(identityKey))
+ .putInt(KEY_VERIFIED_STATUS, verifiedStatus.toInt())
+ .putLong(KEY_TIMESTAMP, timestamp)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_DESTINATION, destination)
- .putString(KEY_IDENTITY_KEY, Base64.encodeBytes(identityKey))
- .putInt(KEY_VERIFIED_STATUS, verifiedStatus.toInt())
- .putLong(KEY_TIMESTAMP, timestamp)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -134,4 +133,20 @@ public class MultiDeviceVerifiedUpdateJob extends ContextJob implements Injectab
public void onCanceled() {
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull MultiDeviceVerifiedUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ try {
+ Address destination = Address.fromSerialized(data.getString(KEY_DESTINATION));
+ VerifiedStatus verifiedStatus = VerifiedStatus.forState(data.getInt(KEY_VERIFIED_STATUS));
+ long timestamp = data.getLong(KEY_TIMESTAMP);
+ byte[] identityKey = Base64.decode(data.getString(KEY_IDENTITY_KEY));
+
+ return new MultiDeviceVerifiedUpdateJob(parameters, destination, identityKey, verifiedStatus, timestamp);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java
index 55b7afac4f..060f36c10c 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushContentReceiveJob.java
@@ -3,37 +3,30 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
-import org.thoughtcrime.securesms.logging.Log;
-
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.whispersystems.libsignal.InvalidVersionException;
-import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
-
-import java.io.IOException;
-
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
public class PushContentReceiveJob extends PushReceivedJob {
- private static final long serialVersionUID = 5685475456901715638L;
-
- public PushContentReceiveJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
+ public static final String KEY = "PushContentReceiveJob";
public PushContentReceiveJob(Context context) {
- super(context, JobParameters.newBuilder().create());
+ this(new Job.Parameters.Builder().build());
+ setContext(context);
+ }
+
+ private PushContentReceiveJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) { }
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
+ }
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -46,4 +39,11 @@ public class PushContentReceiveJob extends PushReceivedJob {
public boolean onShouldRetry(Exception exception) {
return false;
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushContentReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new PushContentReceiveJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index a33d07121a..2ac05bc40c 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -55,8 +55,8 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.groups.GroupMessageProcessor;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.linkpreview.Link;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
@@ -112,12 +112,9 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class PushDecryptJob extends BaseJob {
-public class PushDecryptJob extends ContextJob {
-
- private static final long serialVersionUID = 2L;
+ public static final String KEY = "PushDecryptJob";
public static final String TAG = PushDecryptJob.class.getSimpleName();
@@ -127,10 +124,6 @@ public class PushDecryptJob extends ContextJob {
private long messageId;
private long smsMessageId;
- public PushDecryptJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
public PushDecryptJob(Context context) {
this(context, -1);
}
@@ -140,24 +133,32 @@ public class PushDecryptJob extends ContextJob {
}
public PushDecryptJob(Context context, long pushMessageId, long smsMessageId) {
- super(context, JobParameters.newBuilder()
- .withGroupId("__PUSH_DECRYPT_JOB__")
- .create());
+ this(new Job.Parameters.Builder()
+ .setQueue("__PUSH_DECRYPT_JOB__")
+ .setMaxAttempts(10)
+ .build(),
+ pushMessageId,
+ smsMessageId);
+ setContext(context);
+ }
+
+ private PushDecryptJob(@NonNull Job.Parameters parameters, long pushMessageId, long smsMessageId) {
+ super(parameters);
+
this.messageId = pushMessageId;
this.smsMessageId = smsMessageId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- smsMessageId = data.getLong(KEY_SMS_MESSAGE_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putLong(KEY_SMS_MESSAGE_ID, smsMessageId)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putLong(KEY_SMS_MESSAGE_ID, smsMessageId)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -287,7 +288,7 @@ public class PushDecryptJob extends ContextJob {
resetRecipientToPush(Recipient.from(context, Address.fromExternal(context, content.getSender()), false));
if (envelope.isPreKeySignalMessage()) {
- ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
+ ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob());
}
} catch (ProtocolInvalidVersionException e) {
Log.w(TAG, e);
@@ -475,7 +476,7 @@ public class PushDecryptJob extends ContextJob {
{
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RequestGroupInfoJob(context, content.getSender(), group.getGroupId()));
+ .add(new RequestGroupInfoJob(content.getSender(), group.getGroupId()));
}
private void handleExpirationUpdate(@NonNull SignalServiceContent content,
@@ -552,8 +553,8 @@ public class PushDecryptJob extends ContextJob {
}
if (threadId != null) {
- DatabaseFactory.getThreadDatabase(getContext()).setRead(threadId, true);
- MessageNotifier.updateNotification(getContext());
+ DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
+ MessageNotifier.updateNotification(context);
}
MessageNotifier.setLastDesktopActivityTimestamp(message.getTimestamp());
@@ -567,33 +568,32 @@ public class PushDecryptJob extends ContextJob {
if (message.isContactsRequest()) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceContactUpdateJob(getContext(), true));
+ .add(new MultiDeviceContactUpdateJob(context, true));
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RefreshUnidentifiedDeliveryAbilityJob(context));
+ .add(new RefreshUnidentifiedDeliveryAbilityJob());
}
if (message.isGroupsRequest()) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceGroupUpdateJob(getContext()));
+ .add(new MultiDeviceGroupUpdateJob());
}
if (message.isBlockedListRequest()) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceBlockedUpdateJob(getContext()));
+ .add(new MultiDeviceBlockedUpdateJob());
}
if (message.isConfigurationRequest()) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceConfigurationUpdateJob(getContext(),
- TextSecurePreferences.isReadReceiptsEnabled(getContext()),
- TextSecurePreferences.isTypingIndicatorsEnabled(getContext()),
- TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()),
- TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
+ .add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(context),
+ TextSecurePreferences.isTypingIndicatorsEnabled(context),
+ TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(context),
+ TextSecurePreferences.isLinkPreviewsEnabled(context)));
}
}
@@ -652,7 +652,7 @@ public class PushDecryptJob extends ContextJob {
for (DatabaseAttachment attachment : attachments) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new AttachmentDownloadJob(context, insertResult.get().getMessageId(), attachment.getAttachmentId(), false));
+ .add(new AttachmentDownloadJob(insertResult.get().getMessageId(), attachment.getAttachmentId(), false));
}
if (smsMessageId.isPresent()) {
@@ -725,7 +725,7 @@ public class PushDecryptJob extends ContextJob {
for (DatabaseAttachment attachment : DatabaseFactory.getAttachmentDatabase(context).getAttachmentsForMessage(messageId)) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new AttachmentDownloadJob(context, messageId, attachment.getAttachmentId(), false));
+ .add(new AttachmentDownloadJob(messageId, attachment.getAttachmentId(), false));
}
if (message.getMessage().getExpiresInSeconds() > 0) {
@@ -938,7 +938,7 @@ public class PushDecryptJob extends ContextJob {
if (recipient.getProfileKey() == null || !MessageDigest.isEqual(recipient.getProfileKey(), message.getProfileKey().get())) {
database.setProfileKey(recipient, message.getProfileKey().get());
database.setUnidentifiedAccessMode(recipient, RecipientDatabase.UnidentifiedAccessMode.UNKNOWN);
- ApplicationContext.getInstance(context).getJobManager().add(new RetrieveProfileJob(context, recipient));
+ ApplicationContext.getInstance(context).getJobManager().add(new RetrieveProfileJob(recipient));
}
}
@@ -947,7 +947,7 @@ public class PushDecryptJob extends ContextJob {
{
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new SendDeliveryReceiptJob(context, Address.fromExternal(context, content.getSender()), message.getTimestamp()));
+ .add(new SendDeliveryReceiptJob(Address.fromExternal(context, content.getSender()), message.getTimestamp()));
}
@SuppressLint("DefaultLocale")
@@ -1191,4 +1191,10 @@ public class PushDecryptJob extends ContextJob {
}
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushDecryptJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new PushDecryptJob(parameters, data.getLong(KEY_MESSAGE_ID), data.getLong(KEY_SMS_MESSAGE_ID));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
index ba24f4467d..6c2fa39fb2 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
@@ -20,17 +20,15 @@ import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.ChainParameters;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
-import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
-import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -46,7 +44,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Qu
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
import java.io.IOException;
@@ -58,38 +55,36 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class PushGroupSendJob extends PushSendJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "PushGroupSendJob";
private static final String TAG = PushGroupSendJob.class.getSimpleName();
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_FILTER_ADDRESS = "filter_address";
private long messageId;
- private long filterRecipientId; // Deprecated
private String filterAddress;
- public PushGroupSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public PushGroupSendJob(long messageId, @NonNull Address destination, @Nullable Address filterAddress) {
+ this(new Job.Parameters.Builder()
+ .setQueue(destination.toGroupString())
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ messageId, filterAddress);
+
}
- public PushGroupSendJob(Context context, long messageId, @NonNull Address destination, @Nullable Address filterAddress) {
- super(context, JobParameters.newBuilder()
- .withGroupId(destination.toGroupString())
- .withNetworkRequirement()
- .withRetryDuration(TimeUnit.DAYS.toMillis(1))
- .create());
+ private PushGroupSendJob(@NonNull Job.Parameters parameters, long messageId, @Nullable Address filterAddress) {
+ super(parameters);
- this.messageId = messageId;
- this.filterAddress = filterAddress == null ? null :filterAddress.toPhoneString();
- this.filterRecipientId = -1;
+ this.messageId = messageId;
+ this.filterAddress = filterAddress == null ? null :filterAddress.toPhoneString();
}
@WorkerThread
@@ -103,15 +98,14 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
attachments.addAll(Stream.of(message.getLinkPreviews()).filter(p -> p.getThumbnail().isPresent()).map(p -> p.getThumbnail().get()).toList());
attachments.addAll(Stream.of(message.getSharedContacts()).filter(c -> c.getAvatar() != null).map(c -> c.getAvatar().getAttachment()).withoutNulls().toList());
- List attachmentJobs = Stream.of(attachments).map(a -> new AttachmentUploadJob(context, ((DatabaseAttachment) a).getAttachmentId())).toList();
- ChainParameters chainParams = new ChainParameters.Builder().setGroupId(destination.serialize()).build();
+ List attachmentJobs = Stream.of(attachments).map(a -> new AttachmentUploadJob(((DatabaseAttachment) a).getAttachmentId())).toList();
if (attachmentJobs.isEmpty()) {
- jobManager.add(new PushGroupSendJob(context, messageId, destination, filterAddress));
+ jobManager.add(new PushGroupSendJob(messageId, destination, filterAddress));
} else {
jobManager.startChain(attachmentJobs)
- .then(new PushGroupSendJob(context, messageId, destination, filterAddress))
- .enqueue(chainParams);
+ .then(new PushGroupSendJob(messageId, destination, filterAddress))
+ .enqueue();
}
} catch (NoSuchMessageException | MmsException e) {
@@ -122,20 +116,19 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- filterAddress = data.getString(KEY_FILTER_ADDRESS);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putString(KEY_FILTER_ADDRESS, filterAddress)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putString(KEY_FILTER_ADDRESS, filterAddress)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
- protected void onAdded() {
+ public void onAdded() {
DatabaseFactory.getMmsDatabase(context).markAsSending(messageId);
}
@@ -287,4 +280,14 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
List members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
return Stream.of(members).map(Recipient::getAddress).toList();
}
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushGroupSendJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
+ String address = data.getString(KEY_FILTER_ADDRESS);
+ Address filter = address != null ? Address.fromSerialized(data.getString(KEY_FILTER_ADDRESS)) : null;
+
+ return new PushGroupSendJob(parameters, data.getLong(KEY_MESSAGE_ID), filter);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
index 420ea39730..4935e18010 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushGroupUpdateJob.java
@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
@@ -10,8 +9,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -34,52 +34,47 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class PushGroupUpdateJob extends BaseJob implements InjectableType {
-public class PushGroupUpdateJob extends ContextJob implements InjectableType {
+ public static final String KEY = "PushGroupUpdateJob";
private static final String TAG = PushGroupUpdateJob.class.getSimpleName();
- private static final long serialVersionUID = 0L;
-
private static final String KEY_SOURCE = "source";
private static final String KEY_GROUP_ID = "group_id";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private String source;
private byte[] groupId;
- public PushGroupUpdateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public PushGroupUpdateJob(String source, byte[] groupId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ source,
+ groupId);
}
- public PushGroupUpdateJob(Context context, String source, byte[] groupId) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withRetryDuration(TimeUnit.DAYS.toMillis(1))
- .create());
+ private PushGroupUpdateJob(@NonNull Job.Parameters parameters, String source, byte[] groupId) {
+ super(parameters);
this.source = source;
this.groupId = groupId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- source = data.getString(KEY_SOURCE);
- try {
- groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_SOURCE, source)
+ .putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_SOURCE, source)
- .putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -138,4 +133,17 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
public void onCanceled() {
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushGroupUpdateJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
+ try {
+ return new PushGroupUpdateJob(parameters,
+ data.getString(KEY_SOURCE),
+ GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID)));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
index fcbead5371..e09de2e3a3 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
@@ -17,9 +17,9 @@ import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.ChainParameters;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.JobManager;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@@ -48,27 +48,24 @@ import java.util.List;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class PushMediaSendJob extends PushSendJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "PushMediaSendJob";
private static final String TAG = PushMediaSendJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private long messageId;
- public PushMediaSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public PushMediaSendJob(long messageId, Address destination) {
+ this(constructParameters(destination), messageId);
}
- public PushMediaSendJob(Context context, long messageId, Address destination) {
- super(context, constructParameters(destination));
+ private PushMediaSendJob(Job.Parameters parameters, long messageId) {
+ super(parameters);
this.messageId = messageId;
}
@@ -83,15 +80,14 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
attachments.addAll(Stream.of(message.getLinkPreviews()).filter(p -> p.getThumbnail().isPresent()).map(p -> p.getThumbnail().get()).toList());
attachments.addAll(Stream.of(message.getSharedContacts()).filter(c -> c.getAvatar() != null).map(c -> c.getAvatar().getAttachment()).withoutNulls().toList());
- List attachmentJobs = Stream.of(attachments).map(a -> new AttachmentUploadJob(context, ((DatabaseAttachment) a).getAttachmentId())).toList();
- ChainParameters chainParams = new ChainParameters.Builder().setGroupId(destination.serialize()).build();
+ List attachmentJobs = Stream.of(attachments).map(a -> new AttachmentUploadJob(((DatabaseAttachment) a).getAttachmentId())).toList();
if (attachmentJobs.isEmpty()) {
- jobManager.add(new PushMediaSendJob(context, messageId, destination));
+ jobManager.add(new PushMediaSendJob(messageId, destination));
} else {
jobManager.startChain(attachmentJobs)
- .then(new PushMediaSendJob(context, messageId, destination))
- .enqueue(chainParams);
+ .then(new PushMediaSendJob(messageId, destination))
+ .enqueue();
}
} catch (NoSuchMessageException | MmsException e) {
@@ -102,17 +98,17 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId).build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
- protected void onAdded() {
+ public void onAdded() {
DatabaseFactory.getMmsDatabase(context).markAsSending(messageId);
}
@@ -173,7 +169,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
warn(TAG, "Failure", ifae);
database.markAsPendingInsecureSmsFallback(messageId);
notifyMediaMessageDeliveryFailed(context, messageId);
- ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, false));
+ ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(false));
} catch (UntrustedIdentityException uie) {
warn(TAG, "Failure", uie);
database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
@@ -242,4 +238,11 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
throw new RetryLaterException(e);
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushMediaSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new PushMediaSendJob(parameters, data.getLong(KEY_MESSAGE_ID));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java
index 524e42b6c9..fd1af3f614 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushNotificationReceiveJob.java
@@ -3,10 +3,10 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.support.annotation.NonNull;
-import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
@@ -16,33 +16,36 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class PushNotificationReceiveJob extends PushReceivedJob implements InjectableType {
+ public static final String KEY = "PushNotificationReceiveJob";
+
private static final String TAG = PushNotificationReceiveJob.class.getSimpleName();
- @Inject transient SignalServiceMessageReceiver receiver;
-
- public PushNotificationReceiveJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
+ @Inject SignalServiceMessageReceiver receiver;
public PushNotificationReceiveJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId("__notification_received")
- .create());
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("__notification_received")
+ .setMaxAttempts(3)
+ .setMaxInstances(1)
+ .build());
+ setContext(context);
+ }
+
+ private PushNotificationReceiveJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -75,4 +78,11 @@ public class PushNotificationReceiveJob extends PushReceivedJob implements Injec
private static String timeSuffix(long startTime) {
return " (" + (System.currentTimeMillis() - startTime) + " ms elapsed)";
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushNotificationReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new PushNotificationReceiveJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
index 74a605f593..53641a080e 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushReceivedJob.java
@@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.jobs;
import android.annotation.SuppressLint;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
@@ -9,25 +8,19 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.RecipientDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
-import androidx.work.WorkerParameters;
-
-public abstract class PushReceivedJob extends ContextJob {
+public abstract class PushReceivedJob extends BaseJob {
private static final String TAG = PushReceivedJob.class.getSimpleName();
public static final Object RECEIVE_LOCK = new Object();
- protected PushReceivedJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
- protected PushReceivedJob(Context context, JobParameters parameters) {
- super(context, parameters);
+ protected PushReceivedJob(Job.Parameters parameters) {
+ super(parameters);
}
public void processEnvelope(@NonNull SignalServiceEnvelope envelope) {
@@ -38,7 +31,7 @@ public abstract class PushReceivedJob extends ContextJob {
if (!isActiveNumber(recipient)) {
DatabaseFactory.getRecipientDatabase(context).setRegistered(recipient, RecipientDatabase.RegisteredState.REGISTERED);
- ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, recipient, false));
+ ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(recipient, false));
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
index e53865bd2b..ac0ea2afcb 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
@@ -19,7 +19,8 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.events.PartProgressEvent;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@@ -51,29 +52,22 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-import androidx.work.WorkerParameters;
-
public abstract class PushSendJob extends SendJob {
- private static final long serialVersionUID = 5906098204770900739L;
private static final String TAG = PushSendJob.class.getSimpleName();
private static final long CERTIFICATE_EXPIRATION_BUFFER = TimeUnit.DAYS.toMillis(1);
- public PushSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ protected PushSendJob(Job.Parameters parameters) {
+ super(parameters);
}
- protected PushSendJob(Context context, JobParameters parameters) {
- super(context, parameters);
- }
-
- protected static JobParameters constructParameters(Address destination) {
- JobParameters.Builder builder = JobParameters.newBuilder();
- builder.withGroupId(destination.serialize());
- builder.withNetworkRequirement();
- builder.withRetryDuration(TimeUnit.DAYS.toMillis(1));
-
- return builder.create();
+ protected static Job.Parameters constructParameters(Address destination) {
+ return new Parameters.Builder()
+ .setQueue(destination.serialize())
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build();
}
@Override
@@ -81,7 +75,7 @@ public abstract class PushSendJob extends SendJob {
if (TextSecurePreferences.getSignedPreKeyFailureCount(context) > 5) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RotateSignedPreKeyJob(context));
+ .add(new RotateSignedPreKeyJob());
throw new TextSecureExpiredException("Too many signed prekey rotation failures");
}
@@ -94,9 +88,9 @@ public abstract class PushSendJob extends SendJob {
super.onRetry();
Log.i(TAG, "onRetry()");
- if (getRunAttemptCount() > 1) {
+ if (getRunAttempt() > 1) {
Log.i(TAG, "Scheduling service outage detection job.");
- ApplicationContext.getInstance(context).getJobManager().add(new ServiceOutageDetectionJob(context));
+ ApplicationContext.getInstance(context).getJobManager().add(new ServiceOutageDetectionJob());
}
}
@@ -278,7 +272,6 @@ public abstract class PushSendJob extends SendJob {
Log.w(TAG, "Certificate was invalid at send time. Fetching a new one.", e);
RotateCertificateJob certificateJob = new RotateCertificateJob(context);
ApplicationContext.getInstance(context).injectDependencies(certificateJob);
- certificateJob.setContext(context);
certificateJob.onRun();
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
index 38dfda7667..55532af70a 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
@@ -1,11 +1,9 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
@@ -15,6 +13,8 @@ import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.dependencies.InjectableType;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
@@ -34,38 +34,36 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class PushTextSendJob extends PushSendJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "PushTextSendJob";
private static final String TAG = PushTextSendJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private long messageId;
- public PushTextSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public PushTextSendJob(long messageId, Address destination) {
+ this(constructParameters(destination), messageId);
}
- public PushTextSendJob(Context context, long messageId, Address destination) {
- super(context, constructParameters(destination));
+ private PushTextSendJob(@NonNull Job.Parameters parameters, long messageId) {
+ super(parameters);
this.messageId = messageId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId).build();
}
+ @NonNull
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId).build();
+ public String getFactoryKey() {
+ return KEY;
}
@Override
@@ -126,7 +124,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
warn(TAG, "Failure", e);
database.markAsPendingInsecureSmsFallback(record.getId());
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
- ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, false));
+ ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(false));
} catch (UntrustedIdentityException e) {
warn(TAG, "Failure", e);
database.addMismatchedIdentity(record.getId(), Address.fromSerialized(e.getE164Number()), e.getIdentityKey());
@@ -191,4 +189,11 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
throw new RetryLaterException(e);
}
}
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull PushTextSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new PushTextSendJob(parameters, data.getLong(KEY_MESSAGE_ID));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java
index 5b5b71805b..058960a8b0 100644
--- a/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java
@@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -19,35 +19,33 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RefreshAttributesJob extends BaseJob implements InjectableType {
-public class RefreshAttributesJob extends ContextJob implements InjectableType {
-
- public static final long serialVersionUID = 1L;
+ public static final String KEY = "RefreshAttributesJob";
private static final String TAG = RefreshAttributesJob.class.getSimpleName();
- @Inject transient SignalServiceAccountManager signalAccountManager;
+ @Inject SignalServiceAccountManager signalAccountManager;
- public RefreshAttributesJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RefreshAttributesJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setQueue("RefreshAttributesJob")
+ .build());
}
- public RefreshAttributesJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withGroupId(RefreshAttributesJob.class.getName())
- .create());
+ private RefreshAttributesJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -63,7 +61,7 @@ public class RefreshAttributesJob extends ContextJob implements InjectableType {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RefreshUnidentifiedDeliveryAbilityJob(context));
+ .add(new RefreshUnidentifiedDeliveryAbilityJob());
}
@Override
@@ -75,4 +73,11 @@ public class RefreshAttributesJob extends ContextJob implements InjectableType {
public void onCanceled() {
Log.w(TAG, "Failed to update account attributes!");
}
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull RefreshAttributesJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
+ return new RefreshAttributesJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java
index e377644318..362942107c 100644
--- a/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java
@@ -1,15 +1,14 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKeyPair;
@@ -24,36 +23,36 @@ import java.util.List;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RefreshPreKeysJob extends BaseJob implements InjectableType {
-public class RefreshPreKeysJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RefreshPreKeysJob";
private static final String TAG = RefreshPreKeysJob.class.getSimpleName();
private static final int PREKEY_MINIMUM = 10;
- @Inject transient SignalServiceAccountManager accountManager;
+ @Inject SignalServiceAccountManager accountManager;
- public RefreshPreKeysJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RefreshPreKeysJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("RefreshPreKeysJob")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(5)
+ .build());
}
- public RefreshPreKeysJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId(RefreshPreKeysJob.class.getSimpleName())
- .withNetworkRequirement()
- .withRetryCount(5)
- .create());
+ private RefreshPreKeysJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -80,7 +79,7 @@ public class RefreshPreKeysJob extends ContextJob implements InjectableType {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new CleanPreKeysJob(context));
+ .add(new CleanPreKeysJob());
}
@Override
@@ -93,7 +92,12 @@ public class RefreshPreKeysJob extends ContextJob implements InjectableType {
@Override
public void onCanceled() {
-
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull RefreshPreKeysJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RefreshPreKeysJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RefreshUnidentifiedDeliveryAbilityJob.java b/src/org/thoughtcrime/securesms/jobs/RefreshUnidentifiedDeliveryAbilityJob.java
index 8f210a3ea7..b3977a07cb 100644
--- a/src/org/thoughtcrime/securesms/jobs/RefreshUnidentifiedDeliveryAbilityJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RefreshUnidentifiedDeliveryAbilityJob.java
@@ -1,12 +1,12 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.service.IncomingMessageObserver;
import org.thoughtcrime.securesms.util.Base64;
@@ -23,31 +23,33 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RefreshUnidentifiedDeliveryAbilityJob extends BaseJob implements InjectableType {
-public class RefreshUnidentifiedDeliveryAbilityJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RefreshUnidentifiedDeliveryAbilityJob";
private static final String TAG = RefreshUnidentifiedDeliveryAbilityJob.class.getSimpleName();
- @Inject transient SignalServiceMessageReceiver receiver;
+ @Inject SignalServiceMessageReceiver receiver;
- public RefreshUnidentifiedDeliveryAbilityJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RefreshUnidentifiedDeliveryAbilityJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(10)
+ .build());
}
- public RefreshUnidentifiedDeliveryAbilityJob(Context context) {
- super(context, new JobParameters.Builder()
- .withNetworkRequirement()
- .create());
+ private RefreshUnidentifiedDeliveryAbilityJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) { }
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
+ }
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -62,8 +64,7 @@ public class RefreshUnidentifiedDeliveryAbilityJob extends ContextJob implements
}
@Override
- protected void onCanceled() {
-
+ public void onCanceled() {
}
@Override
@@ -94,4 +95,11 @@ public class RefreshUnidentifiedDeliveryAbilityJob extends ContextJob implements
return false;
}
}
+
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull RefreshUnidentifiedDeliveryAbilityJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RefreshUnidentifiedDeliveryAbilityJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java
index 6ff58a84cb..31dd8b81f6 100644
--- a/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RequestGroupInfoJob.java
@@ -1,15 +1,14 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.util.GroupUtil;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
@@ -20,56 +19,53 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RequestGroupInfoJob extends BaseJob implements InjectableType {
-public class RequestGroupInfoJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RequestGroupInfoJob";
@SuppressWarnings("unused")
private static final String TAG = RequestGroupInfoJob.class.getSimpleName();
- private static final long serialVersionUID = 0L;
-
private static final String KEY_SOURCE = "source";
private static final String KEY_GROUP_ID = "group_id";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private String source;
private byte[] groupId;
- public RequestGroupInfoJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RequestGroupInfoJob(@NonNull String source, @NonNull byte[] groupId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ source,
+ groupId);
+
}
- public RequestGroupInfoJob(@NonNull Context context, @NonNull String source, @NonNull byte[] groupId) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withRetryCount(50)
- .create());
+ private RequestGroupInfoJob(@NonNull Job.Parameters parameters, @NonNull String source, @NonNull byte[] groupId) {
+ super(parameters);
this.source = source;
this.groupId = groupId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- source = data.getString(KEY_SOURCE);
- try {
- groupId = GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID));
- } catch (IOException e) {
- throw new AssertionError(e);
- }
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_SOURCE, source)
+ .putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_SOURCE, source)
- .putString(KEY_GROUP_ID, GroupUtil.getEncodedId(groupId, false))
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -97,4 +93,18 @@ public class RequestGroupInfoJob extends ContextJob implements InjectableType {
public void onCanceled() {
}
+
+ public static final class Factory implements Job.Factory {
+
+ @Override
+ public @NonNull RequestGroupInfoJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ try {
+ return new RequestGroupInfoJob(parameters,
+ data.getString(KEY_SOURCE),
+ GroupUtil.getDecodedId(data.getString(KEY_GROUP_ID)));
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
index 45f38f1b32..443c11ea32 100644
--- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java
@@ -1,18 +1,19 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
+import android.app.Application;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import org.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.Util;
@@ -23,13 +24,13 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RetrieveProfileAvatarJob extends BaseJob implements InjectableType {
-public class RetrieveProfileAvatarJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RetrieveProfileAvatarJob";
private static final String TAG = RetrieveProfileAvatarJob.class.getSimpleName();
@@ -43,32 +44,34 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
private String profileAvatar;
private Recipient recipient;
- public RetrieveProfileAvatarJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RetrieveProfileAvatarJob(Recipient recipient, String profileAvatar) {
+ this(new Job.Parameters.Builder()
+ .setQueue("RetrieveProfileAvatarJob" + recipient.getAddress().serialize())
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.HOURS.toMillis(1))
+ .setMaxInstances(1)
+ .build(),
+ recipient,
+ profileAvatar);
}
- public RetrieveProfileAvatarJob(Context context, Recipient recipient, String profileAvatar) {
- super(context, JobParameters.newBuilder()
- .withGroupId(RetrieveProfileAvatarJob.class.getSimpleName() + recipient.getAddress().serialize())
- .withDuplicatesIgnored(true)
- .withNetworkRequirement()
- .create());
+ private RetrieveProfileAvatarJob(@NonNull Job.Parameters parameters, @NonNull Recipient recipient, String profileAvatar) {
+ super(parameters);
this.recipient = recipient;
this.profileAvatar = profileAvatar;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- profileAvatar = data.getString(KEY_PROFILE_AVATAR);
- recipient = Recipient.from(context, Address.fromSerialized(data.getString(KEY_ADDRESS)), true);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_PROFILE_AVATAR, profileAvatar)
+ .putString(KEY_ADDRESS, recipient.getAddress().serialize())
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_PROFILE_AVATAR, profileAvatar)
- .putString(KEY_ADDRESS, recipient.getAddress().serialize())
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -110,13 +113,27 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
@Override
public boolean onShouldRetry(Exception e) {
- Log.w(TAG, e);
if (e instanceof PushNetworkException) return true;
return false;
}
@Override
public void onCanceled() {
+ }
+ public static final class Factory implements Job.Factory {
+
+ private final Application application;
+
+ public Factory(Application application) {
+ this.application = application;
+ }
+
+ @Override
+ public @NonNull RetrieveProfileAvatarJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RetrieveProfileAvatarJob(parameters,
+ Recipient.from(application, Address.fromSerialized(data.getString(KEY_ADDRESS)), true),
+ data.getString(KEY_PROFILE_AVATAR));
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
index 73dbd716cd..a090616711 100644
--- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java
@@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
+import android.app.Application;
import android.support.annotation.NonNull;
import android.text.TextUtils;
@@ -12,8 +12,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.IncomingMessageObserver;
@@ -38,40 +39,39 @@ import java.util.List;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RetrieveProfileJob extends BaseJob implements InjectableType {
-public class RetrieveProfileJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RetrieveProfileJob";
private static final String TAG = RetrieveProfileJob.class.getSimpleName();
private static final String KEY_ADDRESS = "address";
- @Inject transient SignalServiceMessageReceiver receiver;
+ @Inject SignalServiceMessageReceiver receiver;
private Recipient recipient;
- public RetrieveProfileJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RetrieveProfileJob(@NonNull Recipient recipient) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(3)
+ .build(),
+ recipient);
}
- public RetrieveProfileJob(Context context, Recipient recipient) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withRetryCount(3)
- .create());
-
+ private RetrieveProfileJob(@NonNull Job.Parameters parameters, @NonNull Recipient recipient) {
+ super(parameters);
this.recipient = recipient;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- recipient = Recipient.from(context, Address.fromSerialized(data.getString(KEY_ADDRESS)), true);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_ADDRESS, recipient.getAddress().serialize()).build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_ADDRESS, recipient.getAddress().serialize()).build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -221,7 +221,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
if (!Util.equals(profileAvatar, recipient.getProfileAvatar())) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RetrieveProfileAvatarJob(context, recipient, profileAvatar));
+ .add(new RetrieveProfileAvatarJob(recipient, profileAvatar));
}
}
@@ -234,4 +234,18 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
return Optional.absent();
}
+
+ public static final class Factory implements Job.Factory {
+
+ private final Application application;
+
+ public Factory(Application application) {
+ this.application = application;
+ }
+
+ @Override
+ public @NonNull RetrieveProfileJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RetrieveProfileJob(parameters, Recipient.from(application, Address.fromSerialized(data.getString(KEY_ADDRESS)), true));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java b/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java
index 9592b08a6e..3a0270f806 100644
--- a/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java
@@ -5,55 +5,55 @@ import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
@SuppressWarnings("WeakerAccess")
-public class RotateCertificateJob extends ContextJob implements InjectableType {
+public class RotateCertificateJob extends BaseJob implements InjectableType {
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "RotateCertificateJob";
private static final String TAG = RotateCertificateJob.class.getSimpleName();
- @Inject transient SignalServiceAccountManager accountManager;
-
- public RotateCertificateJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
+ @Inject SignalServiceAccountManager accountManager;
public RotateCertificateJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId("__ROTATE_SENDER_CERTIFICATE__")
- .withNetworkRequirement()
- .create());
+ this(new Job.Parameters.Builder()
+ .setQueue("__ROTATE_SENDER_CERTIFICATE__")
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build());
+ setContext(context);
}
- @NonNull
- @Override
- protected Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ private RotateCertificateJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
+ }
+ @Override
+ public String getFactoryKey() {
+ return KEY;
}
@Override
public void onAdded() {}
-
@Override
public void onRun() throws IOException {
synchronized (RotateCertificateJob.class) {
@@ -71,4 +71,11 @@ public class RotateCertificateJob extends ContextJob implements InjectableType {
public void onCanceled() {
Log.w(TAG, "Failed to rotate sender certificate!");
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull RotateCertificateJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RotateCertificateJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java b/src/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java
index 895f9475a2..3124ad4d29 100644
--- a/src/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RotateProfileKeyJob.java
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -8,8 +7,9 @@ import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
@@ -22,33 +22,33 @@ import java.io.IOException;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RotateProfileKeyJob extends BaseJob implements InjectableType {
-public class RotateProfileKeyJob extends ContextJob implements InjectableType {
+ public static String KEY = "RotateProfileKeyJob";
@Inject SignalServiceAccountManager accountManager;
- public RotateProfileKeyJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RotateProfileKeyJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("__ROTATE_PROFILE_KEY__")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(25)
+ .setMaxInstances(1)
+ .build());
}
- public RotateProfileKeyJob(Context context) {
- super(context, new JobParameters.Builder()
- .withGroupId("__ROTATE_PROFILE_KEY__")
- .withDuplicatesIgnored(true)
- .withNetworkRequirement()
- .create());
- }
-
- @NonNull
- @Override
- protected Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ private RotateProfileKeyJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
+ }
+
+ @Override
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -60,11 +60,11 @@ public class RotateProfileKeyJob extends ContextJob implements InjectableType {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RefreshAttributesJob(context));
+ .add(new RefreshAttributesJob());
}
@Override
- protected void onCanceled() {
+ public void onCanceled() {
}
@@ -86,4 +86,11 @@ public class RotateProfileKeyJob extends ContextJob implements InjectableType {
}
return null;
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull RotateProfileKeyJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RotateProfileKeyJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java b/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java
index 9db70110af..9f1ccdb0fe 100644
--- a/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java
@@ -1,16 +1,15 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.PreKeyUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.IdentityKeyPair;
@@ -20,33 +19,33 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class RotateSignedPreKeyJob extends BaseJob implements InjectableType {
-public class RotateSignedPreKeyJob extends ContextJob implements InjectableType {
+ public static final String KEY = "RotateSignedPreKeyJob";
private static final String TAG = RotateSignedPreKeyJob.class.getSimpleName();
- @Inject transient SignalServiceAccountManager accountManager;
+ @Inject SignalServiceAccountManager accountManager;
- public RotateSignedPreKeyJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public RotateSignedPreKeyJob() {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(5)
+ .build());
}
- public RotateSignedPreKeyJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .withRetryCount(5)
- .create());
+ private RotateSignedPreKeyJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -64,7 +63,7 @@ public class RotateSignedPreKeyJob extends ContextJob implements InjectableType
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new CleanPreKeysJob(context));
+ .add(new CleanPreKeysJob());
}
@Override
@@ -76,4 +75,11 @@ public class RotateSignedPreKeyJob extends ContextJob implements InjectableType
public void onCanceled() {
TextSecurePreferences.setSignedPreKeyFailureCount(context, TextSecurePreferences.getSignedPreKeyFailureCount(context) + 1);
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull RotateSignedPreKeyJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new RotateSignedPreKeyJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java
index c4a418342a..0a0711f5b2 100644
--- a/src/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SendDeliveryReceiptJob.java
@@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
@@ -19,15 +19,13 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.IOException;
import java.util.Collections;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class SendDeliveryReceiptJob extends BaseJob implements InjectableType {
-public class SendDeliveryReceiptJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "SendDeliveryReceiptJob";
private static final String KEY_ADDRESS = "address";
private static final String KEY_MESSAGE_ID = "message_id";
@@ -42,37 +40,40 @@ public class SendDeliveryReceiptJob extends ContextJob implements InjectableType
private long messageId;
private long timestamp;
- public SendDeliveryReceiptJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public SendDeliveryReceiptJob(@NonNull Address address, long messageId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ address,
+ messageId,
+ System.currentTimeMillis());
}
- public SendDeliveryReceiptJob(Context context, Address address, long messageId) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .create());
+ private SendDeliveryReceiptJob(@NonNull Job.Parameters parameters,
+ @NonNull Address address,
+ long messageId,
+ long timestamp)
+ {
+ super(parameters);
this.address = address.serialize();
this.messageId = messageId;
- this.timestamp = System.currentTimeMillis();
+ this.timestamp = timestamp;
}
@Override
- public void onAdded() {}
-
- @NonNull
- @Override
- protected Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putString(KEY_ADDRESS, address)
- .putLong(KEY_MESSAGE_ID, messageId)
- .putLong(KEY_TIMESTAMP, timestamp)
- .build();
+ public @NonNull Data serialize() {
+ return new Data.Builder().putString(KEY_ADDRESS, address)
+ .putLong(KEY_MESSAGE_ID, messageId)
+ .putLong(KEY_TIMESTAMP, timestamp)
+ .build();
}
@Override
- protected void initialize(@NonNull SafeData data) {
- this.address = data.getString(KEY_ADDRESS);
- this.messageId = data.getLong(KEY_MESSAGE_ID);
- this.timestamp = data.getLong(KEY_TIMESTAMP);
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -98,4 +99,13 @@ public class SendDeliveryReceiptJob extends ContextJob implements InjectableType
Log.w(TAG, "Failed to send delivery receipt to: " + address);
}
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull SendDeliveryReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new SendDeliveryReceiptJob(parameters,
+ Address.fromSerialized(data.getString(KEY_ADDRESS)),
+ data.getLong(KEY_MESSAGE_ID),
+ data.getLong(KEY_TIMESTAMP));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SendJob.java b/src/org/thoughtcrime/securesms/jobs/SendJob.java
index b29f41b0d6..b6d989c89d 100644
--- a/src/org/thoughtcrime/securesms/jobs/SendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SendJob.java
@@ -1,17 +1,15 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.thoughtcrime.securesms.BuildConfig;
-import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.thoughtcrime.securesms.attachments.Attachment;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.JobLogger;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MediaConstraints;
import org.thoughtcrime.securesms.mms.MediaStream;
@@ -24,19 +22,13 @@ import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
-import androidx.work.WorkerParameters;
-
-public abstract class SendJob extends ContextJob {
+public abstract class SendJob extends BaseJob {
@SuppressWarnings("unused")
private final static String TAG = SendJob.class.getSimpleName();
- public SendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
- public SendJob(Context context, JobParameters parameters) {
- super(context, parameters);
+ public SendJob(Job.Parameters parameters) {
+ super(parameters);
}
@Override
@@ -93,7 +85,7 @@ public abstract class SendJob extends ContextJob {
}
protected void log(@NonNull String tag, @NonNull String message) {
- Log.i(tag, "[" + getId().toString() + "] " + message + logSuffix());
+ Log.i(tag, JobLogger.format(this, message));
}
protected void warn(@NonNull String tag, @NonNull String message) {
@@ -105,6 +97,6 @@ public abstract class SendJob extends ContextJob {
}
protected void warn(@NonNull String tag, @NonNull String message, @Nullable Throwable t) {
- Log.w(tag, "[" + getId().toString() + "] " + message + logSuffix(), t);
+ Log.w(tag, JobLogger.format(this, message), t);
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java
index dbea519867..d7ea76b4d8 100644
--- a/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SendReadReceiptJob.java
@@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -21,15 +21,13 @@ import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class SendReadReceiptJob extends BaseJob implements InjectableType {
-public class SendReadReceiptJob extends ContextJob implements InjectableType {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "SendReadReceiptJob";
private static final String TAG = SendReadReceiptJob.class.getSimpleName();
@@ -37,49 +35,51 @@ public class SendReadReceiptJob extends ContextJob implements InjectableType {
private static final String KEY_MESSAGE_IDS = "message_ids";
private static final String KEY_TIMESTAMP = "timestamp";
- @Inject transient SignalServiceMessageSender messageSender;
+ @Inject SignalServiceMessageSender messageSender;
private String address;
private List messageIds;
private long timestamp;
- public SendReadReceiptJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public SendReadReceiptJob(Address address, List messageIds) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(NetworkConstraint.KEY)
+ .setLifespan(TimeUnit.DAYS.toMillis(1))
+ .setMaxAttempts(Parameters.UNLIMITED)
+ .build(),
+ address,
+ messageIds,
+ System.currentTimeMillis());
}
- public SendReadReceiptJob(Context context, Address address, List messageIds) {
- super(context, JobParameters.newBuilder()
- .withNetworkRequirement()
- .create());
+ private SendReadReceiptJob(@NonNull Job.Parameters parameters,
+ @NonNull Address address,
+ @NonNull List messageIds,
+ long timestamp)
+ {
+ super(parameters);
this.address = address.serialize();
this.messageIds = messageIds;
- this.timestamp = System.currentTimeMillis();
+ this.timestamp = timestamp;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- address = data.getString(KEY_ADDRESS);
- timestamp = data.getLong(KEY_TIMESTAMP);
-
- long[] ids = data.getLongArray(KEY_MESSAGE_IDS);
- messageIds = new ArrayList<>(ids.length);
- for (long id : ids) {
- messageIds.add(id);
- }
- }
-
- @Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
+ public @NonNull Data serialize() {
long[] ids = new long[messageIds.size()];
for (int i = 0; i < ids.length; i++) {
ids[i] = messageIds.get(i);
}
- return dataBuilder.putString(KEY_ADDRESS, address)
- .putLongArray(KEY_MESSAGE_IDS, ids)
- .putLong(KEY_TIMESTAMP, timestamp)
- .build();
+ return new Data.Builder().putString(KEY_ADDRESS, address)
+ .putLongArray(KEY_MESSAGE_IDS, ids)
+ .putLong(KEY_TIMESTAMP, timestamp)
+ .build();
+ }
+
+ @Override
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -104,4 +104,20 @@ public class SendReadReceiptJob extends ContextJob implements InjectableType {
public void onCanceled() {
Log.w(TAG, "Failed to send read receipts to: " + address);
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull SendReadReceiptJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ Address address = Address.fromSerialized(data.getString(KEY_ADDRESS));
+ long timestamp = data.getLong(KEY_TIMESTAMP);
+ long[] ids = data.getLongArray(KEY_MESSAGE_IDS);
+ List messageIds = new ArrayList<>(ids.length);
+
+ for (long id : ids) {
+ messageIds.add(id);
+ }
+
+ return new SendReadReceiptJob(parameters, address, messageIds, timestamp);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java b/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java
index 21b79bf379..47dbd6a770 100644
--- a/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/ServiceOutageDetectionJob.java
@@ -1,13 +1,13 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -15,10 +15,9 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class ServiceOutageDetectionJob extends BaseJob {
-public class ServiceOutageDetectionJob extends ContextJob {
+ public static final String KEY = "ServiceOutageDetectionJob";
private static final String TAG = ServiceOutageDetectionJob.class.getSimpleName();
@@ -26,26 +25,27 @@ public class ServiceOutageDetectionJob extends ContextJob {
private static final String IP_FAILURE = "127.0.0.2";
private static final long CHECK_TIME = 1000 * 60;
- public ServiceOutageDetectionJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public ServiceOutageDetectionJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("ServiceOutageDetectionJob")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(5)
+ .setMaxInstances(1)
+ .build());
}
- public ServiceOutageDetectionJob(Context context) {
- super(context, new JobParameters.Builder()
- .withGroupId(ServiceOutageDetectionJob.class.getSimpleName())
- .withDuplicatesIgnored(true)
- .withNetworkRequirement()
- .withRetryCount(5)
- .create());
+ private ServiceOutageDetectionJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -92,4 +92,11 @@ public class ServiceOutageDetectionJob extends ContextJob {
TextSecurePreferences.setLastOutageCheckTime(context, System.currentTimeMillis());
EventBus.getDefault().post(new ReminderUpdateEvent());
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull ServiceOutageDetectionJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new ServiceOutageDetectionJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
index 79513f8727..fceeaae38e 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsReceiveJob.java
@@ -1,17 +1,17 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.telephony.SmsMessage;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
import org.thoughtcrime.securesms.database.SmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
@@ -23,12 +23,9 @@ import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class SmsReceiveJob extends BaseJob {
-public class SmsReceiveJob extends ContextJob {
-
- private static final long serialVersionUID = 1L;
+ public static final String KEY = "SmsReceiveJob";
private static final String TAG = SmsReceiveJob.class.getSimpleName();
@@ -39,44 +36,37 @@ public class SmsReceiveJob extends ContextJob {
private int subscriptionId;
- public SmsReceiveJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public SmsReceiveJob(@Nullable Object[] pdus, int subscriptionId) {
+ this(new Job.Parameters.Builder()
+ .addConstraint(SqlCipherMigrationConstraint.KEY)
+ .setMaxAttempts(25)
+ .build(),
+ pdus,
+ subscriptionId);
}
- public SmsReceiveJob(@NonNull Context context, @Nullable Object[] pdus, int subscriptionId) {
- super(context, JobParameters.newBuilder()
- .withSqlCipherRequirement()
- .create());
+ private SmsReceiveJob(@NonNull Job.Parameters parameters, @Nullable Object[] pdus, int subscriptionId) {
+ super(parameters);
this.pdus = pdus;
this.subscriptionId = subscriptionId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- String[] encoded = data.getStringArray(KEY_PDUS);
- pdus = new Object[encoded.length];
- try {
- for (int i = 0; i < encoded.length; i++) {
- pdus[i] = Base64.decode(encoded[i]);
- }
- } catch (IOException e) {
- throw new AssertionError(e);
- }
-
- subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
- }
-
- @Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
+ public @NonNull Data serialize() {
String[] encoded = new String[pdus.length];
for (int i = 0; i < pdus.length; i++) {
encoded[i] = Base64.encodeBytes((byte[]) pdus[i]);
}
- return dataBuilder.putStringArray(KEY_PDUS, encoded)
- .putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
- .build();
+ return new Data.Builder().putStringArray(KEY_PDUS, encoded)
+ .putInt(KEY_SUBSCRIPTION_ID, subscriptionId)
+ .build();
+ }
+
+ @Override
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -155,6 +145,24 @@ public class SmsReceiveJob extends ContextJob {
}
private class MigrationPendingException extends Exception {
+ }
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull SmsReceiveJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ try {
+ int subscriptionId = data.getInt(KEY_SUBSCRIPTION_ID);
+ String[] encoded = data.getStringArray(KEY_PDUS);
+ Object[] pdus = new Object[encoded.length];
+
+ for (int i = 0; i < encoded.length; i++) {
+ pdus[i] = Base64.decode(encoded[i]);
+ }
+
+ return new SmsReceiveJob(parameters, pdus, subscriptionId);
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
}
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
index 90fa3dbd12..0e49d60aa3 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
@@ -9,12 +9,11 @@ import android.support.annotation.NonNull;
import android.telephony.PhoneNumberUtils;
import android.telephony.SmsManager;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
-import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
-import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirement;
-import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
@@ -22,20 +21,16 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
-import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.NumberUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import java.util.ArrayList;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
-
public class SmsSendJob extends SendJob {
- private static final long serialVersionUID = -5118520036244759718L;
+ public static final String KEY = "SmsSendJob";
+
private static final String TAG = SmsSendJob.class.getSimpleName();
private static final int MAX_ATTEMPTS = 15;
private static final String KEY_MESSAGE_ID = "message_id";
@@ -44,44 +39,35 @@ public class SmsSendJob extends SendJob {
private long messageId;
private int runAttempt;
- public SmsSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
- }
-
public SmsSendJob(Context context, long messageId, String name) {
this(context, messageId, name, 0);
}
public SmsSendJob(Context context, long messageId, String name, int runAttempt) {
- super(context, constructParameters(name));
+ this(constructParameters(context, name), messageId, runAttempt);
+ }
+
+ private SmsSendJob(@NonNull Job.Parameters parameters, long messageId, int runAttempt) {
+ super(parameters);
+
this.messageId = messageId;
this.runAttempt = runAttempt;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- runAttempt = data.getInt(KEY_RUN_ATTEMPT);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putInt(KEY_RUN_ATTEMPT, runAttempt)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putInt(KEY_RUN_ATTEMPT, runAttempt)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
- public void onAdded() {
- }
-
- @Override
- public void onSend() throws NoSuchMessageException, RequirementNotMetException, TooManyRetriesException {
- if (!requirementsMet()) {
- warn(TAG, "No service. Retrying.");
- throw new RequirementNotMetException();
- }
-
+ public void onSend() throws NoSuchMessageException, TooManyRetriesException {
if (runAttempt >= MAX_ATTEMPTS) {
warn(TAG, "Hit the retry limit. Failing.");
throw new TooManyRetriesException();
@@ -124,14 +110,6 @@ public class SmsSendJob extends SendJob {
}
}
- private boolean requirementsMet() {
- if (TextSecurePreferences.isWifiSmsEnabled(context)) {
- return new NetworkOrServiceRequirement(context).isPresent();
- } else {
- return new ServiceRequirement(context).isPresent();
- }
- }
-
private void deliver(SmsMessageRecord message)
throws UndeliverableMessageException
{
@@ -223,7 +201,7 @@ public class SmsSendJob extends SendJob {
pending.putExtra("type", type);
pending.putExtra("message_id", messageId);
- pending.putExtra("run_attempt", Math.max(runAttempt, getRunAttemptCount()));
+ pending.putExtra("run_attempt", Math.max(runAttempt, getRunAttempt()));
pending.putExtra("upgraded", upgraded);
pending.putExtra("push", push);
@@ -248,15 +226,22 @@ public class SmsSendJob extends SendJob {
}
}
- private static JobParameters constructParameters(String name) {
- JobParameters.Builder builder = JobParameters.newBuilder()
- .withRetryCount(MAX_ATTEMPTS)
- .withGroupId(name);
- return builder.create();
+ private static Job.Parameters constructParameters(@NonNull Context context, String name) {
+ String constraint = TextSecurePreferences.isWifiSmsEnabled(context) ? NetworkOrCellServiceConstraint.KEY
+ : CellServiceConstraint.KEY;
+ return new Job.Parameters.Builder()
+ .setMaxAttempts(MAX_ATTEMPTS)
+ .setQueue(name)
+ .addConstraint(constraint)
+ .build();
}
private static class TooManyRetriesException extends Exception { }
- private static class RequirementNotMetException extends Exception { }
-
+ public static class Factory implements Job.Factory {
+ @Override
+ public @NonNull SmsSendJob create(@NonNull Parameters parameters, @NonNull org.thoughtcrime.securesms.jobmanager.Data data) {
+ return new SmsSendJob(parameters, data.getLong(KEY_MESSAGE_ID), data.getInt(KEY_RUN_ATTEMPT));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
index ba654cf692..fa765b7c90 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSentJob.java
@@ -1,30 +1,26 @@
package org.thoughtcrime.securesms.jobs;
import android.app.Activity;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.telephony.SmsManager;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.notifications.MessageNotifier;
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class SmsSentJob extends BaseJob {
-public class SmsSentJob extends ContextJob {
+ public static final String KEY = "SmsSentJob";
- private static final long serialVersionUID = -2624694558755317560L;
- private static final String TAG = SmsSentJob.class.getSimpleName();
+ private static final String TAG = SmsSentJob.class.getSimpleName();
private static final String KEY_MESSAGE_ID = "message_id";
private static final String KEY_ACTION = "action";
@@ -36,13 +32,16 @@ public class SmsSentJob extends ContextJob {
private int result;
private int runAttempt;
- public SmsSentJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public SmsSentJob(long messageId, String action, int result, int runAttempt) {
+ this(new Job.Parameters.Builder().build(),
+ messageId,
+ action,
+ result,
+ runAttempt);
}
- public SmsSentJob(Context context, long messageId, String action, int result, int runAttempt) {
- super(context, JobParameters.newBuilder()
- .create());
+ private SmsSentJob(@NonNull Job.Parameters parameters, long messageId, String action, int result, int runAttempt) {
+ super(parameters);
this.messageId = messageId;
this.action = action;
@@ -51,20 +50,17 @@ public class SmsSentJob extends ContextJob {
}
@Override
- protected void initialize(@NonNull SafeData data) {
- messageId = data.getLong(KEY_MESSAGE_ID);
- action = data.getString(KEY_ACTION);
- result = data.getInt(KEY_RESULT);
- runAttempt = data.getInt(KEY_RUN_ATTEMPT);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_MESSAGE_ID, messageId)
+ .putString(KEY_ACTION, action)
+ .putInt(KEY_RESULT, result)
+ .putInt(KEY_RUN_ATTEMPT, runAttempt)
+ .build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_MESSAGE_ID, messageId)
- .putString(KEY_ACTION, action)
- .putInt(KEY_RESULT, result)
- .putInt(KEY_RUN_ATTEMPT, runAttempt)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -88,7 +84,6 @@ public class SmsSentJob extends ContextJob {
@Override
public void onCanceled() {
-
}
private void handleDeliveredResult(long messageId, int result) {
@@ -108,8 +103,8 @@ public class SmsSentJob extends ContextJob {
case SmsManager.RESULT_ERROR_RADIO_OFF:
Log.w(TAG, "Service connectivity problem, requeuing...");
ApplicationContext.getInstance(context)
- .getJobManager()
- .add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getAddress().serialize(), runAttempt + 1));
+ .getJobManager()
+ .add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getAddress().serialize(), runAttempt + 1));
break;
default:
database.markAsSentFailed(messageId);
@@ -119,4 +114,15 @@ public class SmsSentJob extends ContextJob {
Log.w(TAG, e);
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull SmsSentJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new SmsSentJob(parameters,
+ data.getLong(KEY_MESSAGE_ID),
+ data.getString(KEY_ACTION),
+ data.getInt(KEY_RESULT),
+ data.getInt(KEY_RUN_ATTEMPT));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java b/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java
index 6cc4b3e807..818cbac632 100644
--- a/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/TrimThreadJob.java
@@ -16,19 +16,17 @@
*/
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class TrimThreadJob extends BaseJob {
-public class TrimThreadJob extends ContextJob {
+ public static final String KEY = "TrimThreadJob";
private static final String TAG = TrimThreadJob.class.getSimpleName();
@@ -36,24 +34,23 @@ public class TrimThreadJob extends ContextJob {
private long threadId;
- public TrimThreadJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public TrimThreadJob(long threadId) {
+ this(new Job.Parameters.Builder().setQueue("TrimThreadJob").build(), threadId);
}
- public TrimThreadJob(Context context, long threadId) {
- super(context, JobParameters.newBuilder().withGroupId(TrimThreadJob.class.getSimpleName()).create());
- this.context = context;
+ private TrimThreadJob(@NonNull Job.Parameters parameters, long threadId) {
+ super(parameters);
this.threadId = threadId;
}
@Override
- protected void initialize(@NonNull SafeData data) {
- threadId = data.getLong(KEY_THREAD_ID);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_THREAD_ID, threadId).build();
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_THREAD_ID, threadId).build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -76,4 +73,11 @@ public class TrimThreadJob extends ContextJob {
public void onCanceled() {
Log.w(TAG, "Canceling trim attempt: " + threadId);
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull TrimThreadJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new TrimThreadJob(parameters, data.getLong(KEY_THREAD_ID));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java b/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java
index 34c242a561..926fde25ef 100644
--- a/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/TypingSendJob.java
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.jobs;
-import android.content.Context;
import android.support.annotation.NonNull;
import com.annimon.stream.Stream;
@@ -8,8 +7,8 @@ import com.annimon.stream.Stream;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.GroupUtil;
@@ -23,13 +22,13 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
+public class TypingSendJob extends BaseJob implements InjectableType {
-public class TypingSendJob extends ContextJob implements InjectableType {
+ public static final String KEY = "TypingSendJob";
private static final String TAG = TypingSendJob.class.getSimpleName();
@@ -41,32 +40,34 @@ public class TypingSendJob extends ContextJob implements InjectableType {
@Inject SignalServiceMessageSender messageSender;
- public TypingSendJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public TypingSendJob(long threadId, boolean typing) {
+ this(new Job.Parameters.Builder()
+ .setQueue("TYPING_" + threadId)
+ .setMaxAttempts(1)
+ .setLifespan(TimeUnit.SECONDS.toMillis(5))
+ .build(),
+ threadId,
+ typing);
}
- public TypingSendJob(Context context, long threadId, boolean typing) {
- super(context, JobParameters.newBuilder()
- .withGroupId("TYPING_" + threadId)
- .withRetryCount(1)
- .create());
+ private TypingSendJob(@NonNull Job.Parameters parameters, long threadId, boolean typing) {
+ super(parameters);
this.threadId = threadId;
this.typing = typing;
}
+
@Override
- protected void initialize(@NonNull SafeData data) {
- this.threadId = data.getLong(KEY_THREAD_ID);
- this.typing = data.getBoolean(KEY_TYPING);
+ public @NonNull Data serialize() {
+ return new Data.Builder().putLong(KEY_THREAD_ID, threadId)
+ .putBoolean(KEY_TYPING, typing)
+ .build();
}
- @NonNull
@Override
- protected Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.putLong(KEY_THREAD_ID, threadId)
- .putBoolean(KEY_TYPING, typing)
- .build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -99,11 +100,18 @@ public class TypingSendJob extends ContextJob implements InjectableType {
}
@Override
- protected void onCanceled() {
+ public void onCanceled() {
}
@Override
protected boolean onShouldRetry(Exception exception) {
return false;
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull TypingSendJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new TypingSendJob(parameters, data.getLong(KEY_THREAD_ID), data.getBoolean(KEY_TYPING));
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java b/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
index 2e07392f1f..e7d3561c80 100644
--- a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
@@ -8,17 +8,17 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import org.thoughtcrime.securesms.jobmanager.SafeData;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.Job;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.thoughtcrime.securesms.BuildConfig;
-import org.thoughtcrime.securesms.jobmanager.JobParameters;
import org.thoughtcrime.securesms.service.UpdateApkReadyListener;
import org.thoughtcrime.securesms.util.FileUtils;
import org.thoughtcrime.securesms.util.Hex;
@@ -29,35 +29,36 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
-import androidx.work.Data;
-import androidx.work.WorkerParameters;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
-public class UpdateApkJob extends ContextJob {
+public class UpdateApkJob extends BaseJob {
+
+ public static final String KEY = "UpdateApkJob";
private static final String TAG = UpdateApkJob.class.getSimpleName();
- public UpdateApkJob(@NonNull Context context, @NonNull WorkerParameters workerParameters) {
- super(context, workerParameters);
+ public UpdateApkJob() {
+ this(new Job.Parameters.Builder()
+ .setQueue("UpdateApkJob")
+ .addConstraint(NetworkConstraint.KEY)
+ .setMaxAttempts(2)
+ .build());
}
- public UpdateApkJob(Context context) {
- super(context, JobParameters.newBuilder()
- .withGroupId(UpdateApkJob.class.getSimpleName())
- .withNetworkRequirement()
- .withRetryCount(2)
- .create());
+ private UpdateApkJob(@NonNull Job.Parameters parameters) {
+ super(parameters);
}
@Override
- protected void initialize(@NonNull SafeData data) {
+ public @NonNull Data serialize() {
+ return Data.EMPTY;
}
@Override
- protected @NonNull Data serialize(@NonNull Data.Builder dataBuilder) {
- return dataBuilder.build();
+ public @NonNull String getFactoryKey() {
+ return KEY;
}
@Override
@@ -260,4 +261,11 @@ public class UpdateApkJob extends ContextJob {
return downloadId;
}
}
+
+ public static final class Factory implements Job.Factory {
+ @Override
+ public @NonNull UpdateApkJob create(@NonNull Parameters parameters, @NonNull Data data) {
+ return new UpdateApkJob(parameters);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java
deleted file mode 100644
index b33f424614..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirement.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-import android.content.Context;
-
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.SimpleRequirement;
-import org.thoughtcrime.securesms.service.KeyCachingService;
-
-public class MasterSecretRequirement extends SimpleRequirement implements ContextDependent {
-
- private transient Context context;
-
- public MasterSecretRequirement(Context context) {
- this.context = context;
- }
-
- @Override
- public boolean isPresent() {
- return KeyCachingService.getMasterSecret(context) != null;
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java
deleted file mode 100644
index db036ff968..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/MasterSecretRequirementProvider.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener;
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider;
-import org.thoughtcrime.securesms.service.KeyCachingService;
-
-public class MasterSecretRequirementProvider implements RequirementProvider {
-
- private final BroadcastReceiver newKeyReceiver;
-
- private RequirementListener listener;
-
- public MasterSecretRequirementProvider(Context context) {
- this.newKeyReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (listener != null) {
- listener.onRequirementStatusChanged();
- }
- }
- };
-
- IntentFilter filter = new IntentFilter(KeyCachingService.NEW_KEY_EVENT);
- context.registerReceiver(newKeyReceiver, filter, KeyCachingService.KEY_PERMISSION, null);
- }
-
- @Override
- public void setListener(RequirementListener listener) {
- this.listener = listener;
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java
deleted file mode 100644
index 5dcf686b51..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/NetworkOrServiceRequirement.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-import android.content.Context;
-
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.SimpleRequirement;
-
-public class NetworkOrServiceRequirement extends SimpleRequirement implements ContextDependent {
-
- private transient Context context;
-
- public NetworkOrServiceRequirement(Context context) {
- this.context = context;
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context;
- }
-
- @Override
- public boolean isPresent() {
- NetworkRequirement networkRequirement = new NetworkRequirement(context);
- ServiceRequirement serviceRequirement = new ServiceRequirement(context);
-
- return networkRequirement.isPresent() || serviceRequirement.isPresent();
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java
deleted file mode 100644
index 49a0368c55..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirement.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-import android.content.Context;
-
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.SimpleRequirement;
-import org.thoughtcrime.securesms.sms.TelephonyServiceState;
-
-public class ServiceRequirement extends SimpleRequirement implements ContextDependent {
-
- private static final String TAG = ServiceRequirement.class.getSimpleName();
-
- private transient Context context;
-
- public ServiceRequirement(Context context) {
- this.context = context;
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context;
- }
-
- @Override
- public boolean isPresent() {
- TelephonyServiceState telephonyServiceState = new TelephonyServiceState();
- return telephonyServiceState.isConnected(context);
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java
deleted file mode 100644
index 4b7ccd08a5..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/ServiceRequirementProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-import android.content.Context;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
-
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener;
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class ServiceRequirementProvider implements RequirementProvider {
-
- private final TelephonyManager telephonyManager;
- private final ServiceStateListener serviceStateListener;
- private final AtomicBoolean listeningForServiceState;
-
- private RequirementListener requirementListener;
-
- public ServiceRequirementProvider(Context context) {
- this.telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- this.serviceStateListener = new ServiceStateListener();
- this.listeningForServiceState = new AtomicBoolean(false);
- }
-
- @Override
- public void setListener(RequirementListener requirementListener) {
- this.requirementListener = requirementListener;
- }
-
- public void start() {
- if (listeningForServiceState.compareAndSet(false, true)) {
- this.telephonyManager.listen(serviceStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
- }
- }
-
- private void handleInService() {
- if (listeningForServiceState.compareAndSet(true, false)) {
- this.telephonyManager.listen(serviceStateListener, PhoneStateListener.LISTEN_NONE);
- }
-
- if (requirementListener != null) {
- requirementListener.onRequirementStatusChanged();
- }
- }
-
- private class ServiceStateListener extends PhoneStateListener {
- @Override
- public void onServiceStateChanged(ServiceState serviceState) {
- if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
- handleInService();
- }
- }
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java
deleted file mode 100644
index 76dd67b663..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirement.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-
-import org.thoughtcrime.securesms.jobmanager.dependencies.ContextDependent;
-import org.thoughtcrime.securesms.jobmanager.requirements.Requirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.SimpleRequirement;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
-
-public class SqlCipherMigrationRequirement extends SimpleRequirement implements ContextDependent {
-
- @SuppressWarnings("unused")
- private static final String TAG = SqlCipherMigrationRequirement.class.getSimpleName();
-
- private transient Context context;
-
- public SqlCipherMigrationRequirement(@NonNull Context context) {
- this.context = context;
- }
-
- @Override
- public void setContext(Context context) {
- this.context = context;
- }
-
- @Override
- public boolean isPresent() {
- return !TextSecurePreferences.getNeedsSqlCipherMigration(context);
- }
-}
diff --git a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java b/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java
deleted file mode 100644
index 2ce574f515..0000000000
--- a/src/org/thoughtcrime/securesms/jobs/requirements/SqlCipherMigrationRequirementProvider.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.thoughtcrime.securesms.jobs.requirements;
-
-
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener;
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementProvider;
-
-public class SqlCipherMigrationRequirementProvider implements RequirementProvider {
-
- private RequirementListener listener;
-
- public SqlCipherMigrationRequirementProvider() {
- EventBus.getDefault().register(this);
- }
-
- @Override
- public void setListener(RequirementListener listener) {
- this.listener = listener;
- }
-
- @Subscribe(threadMode = ThreadMode.MAIN)
- public void onEvent(SqlCipherNeedsMigrationEvent event) {
- if (listener != null) listener.onRequirementStatusChanged();
- }
-
- public static class SqlCipherNeedsMigrationEvent {
-
- }
-}
diff --git a/src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java b/src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java
index 23d49c48bd..77bc2da90c 100644
--- a/src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java
+++ b/src/org/thoughtcrime/securesms/logsubmit/SubmitLogFragment.java
@@ -51,7 +51,6 @@ import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import org.thoughtcrime.securesms.ApplicationContext;
-import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
import org.thoughtcrime.securesms.logging.Log;
@@ -93,6 +92,7 @@ public class SubmitLogFragment extends Fragment {
private static final String API_ENDPOINT = "https://debuglogs.org";
private static final String HEADER_SYSINFO = "========== SYSINFO ========";
+ private static final String HEADER_JOBS = "=========== JOBS =========";
private static final String HEADER_LOGCAT = "========== LOGCAT ========";
private static final String HEADER_LOGGER = "========== LOGGER ========";
@@ -373,6 +373,8 @@ public class SubmitLogFragment extends Fragment {
return HEADER_SYSINFO + "\n\n" +
buildDescription(context) + "\n\n\n" +
+ HEADER_JOBS + "\n\n" +
+ scrubber.scrub(ApplicationContext.getInstance(context).getJobManager().getDebugInfo()) + "\n\n" +
HEADER_LOGCAT + "\n\n" +
scrubbedLogcat + "\n\n\n" +
HEADER_LOGGER + "\n\n" +
@@ -487,7 +489,7 @@ public class SubmitLogFragment extends Fragment {
final PackageManager pm = context.getPackageManager();
final StringBuilder builder = new StringBuilder();
-
+ builder.append("Time : ").append(System.currentTimeMillis()).append('\n');
builder.append("Device : ")
.append(Build.MANUFACTURER).append(" ")
.append(Build.MODEL).append(" (")
diff --git a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
index 7182921790..670fe42ce5 100644
--- a/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
+++ b/src/org/thoughtcrime/securesms/notifications/MarkReadReceiver.java
@@ -77,7 +77,7 @@ public class MarkReadReceiver extends BroadcastReceiver {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MultiDeviceReadUpdateJob(context, syncMessageIds));
+ .add(new MultiDeviceReadUpdateJob(syncMessageIds));
Map> addressMap = Stream.of(markedReadMessages)
.map(MarkedMessageInfo::getSyncMessageId)
@@ -88,7 +88,7 @@ public class MarkReadReceiver extends BroadcastReceiver {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new SendReadReceiptJob(context, address, timestamps));
+ .add(new SendReadReceiptJob(address, timestamps));
}
}
diff --git a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java
index 90eea15b4d..aa85a68d9a 100644
--- a/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java
+++ b/src/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java
@@ -4,13 +4,11 @@ import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
-import android.view.View;
import android.widget.Toast;
import org.thoughtcrime.securesms.ApplicationContext;
@@ -22,7 +20,6 @@ import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob;
-import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob;
import org.thoughtcrime.securesms.jobs.RefreshAttributesJob;
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
import org.thoughtcrime.securesms.service.KeyCachingService;
@@ -187,8 +184,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean enabled = (boolean)newValue;
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new MultiDeviceConfigurationUpdateJob(getContext(),
- enabled,
+ .add(new MultiDeviceConfigurationUpdateJob(enabled,
TextSecurePreferences.isTypingIndicatorsEnabled(requireContext()),
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()),
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
@@ -203,8 +199,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean enabled = (boolean)newValue;
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new MultiDeviceConfigurationUpdateJob(getContext(),
- TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
+ .add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
enabled,
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()),
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
@@ -223,8 +218,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean enabled = (boolean)newValue;
ApplicationContext.getInstance(requireContext())
.getJobManager()
- .add(new MultiDeviceConfigurationUpdateJob(requireContext(),
- TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
+ .add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(requireContext()),
TextSecurePreferences.isTypingIndicatorsEnabled(requireContext()),
TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(requireContext()),
enabled));
@@ -327,8 +321,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean enabled = (boolean) newValue;
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new MultiDeviceConfigurationUpdateJob(getContext(),
- TextSecurePreferences.isReadReceiptsEnabled(getContext()),
+ .add(new MultiDeviceConfigurationUpdateJob(TextSecurePreferences.isReadReceiptsEnabled(getContext()),
TextSecurePreferences.isTypingIndicatorsEnabled(getContext()),
enabled,
TextSecurePreferences.isLinkPreviewsEnabled(getContext())));
@@ -342,7 +335,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
public boolean onPreferenceChange(Preference preference, Object o) {
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new RefreshAttributesJob(getContext()));
+ .add(new RefreshAttributesJob());
return true;
}
}
diff --git a/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java
index 3b950703b5..05d4999a4d 100644
--- a/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java
+++ b/src/org/thoughtcrime/securesms/preferences/ChatsPreferenceFragment.java
@@ -163,7 +163,7 @@ public class ChatsPreferenceFragment extends ListSummaryPreferenceFragment {
Log.i(TAG, "Queing backup...");
ApplicationContext.getInstance(getContext())
.getJobManager()
- .add(new LocalBackupJob(getContext()));
+ .add(new LocalBackupJob());
})
.withPermanentDenialDialog(getString(R.string.ChatsPreferenceFragment_signal_requires_external_storage_permission_in_order_to_create_backups))
.execute();
diff --git a/src/org/thoughtcrime/securesms/service/BootReceiver.java b/src/org/thoughtcrime/securesms/service/BootReceiver.java
index e94765b44c..7435a6acee 100644
--- a/src/org/thoughtcrime/securesms/service/BootReceiver.java
+++ b/src/org/thoughtcrime/securesms/service/BootReceiver.java
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
diff --git a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java b/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java
index d31aff40df..8abacdca4d 100644
--- a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java
+++ b/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java
@@ -24,7 +24,7 @@ public class DirectoryRefreshListener extends PersistentAlarmManagerListener {
if (scheduledTime != 0 && TextSecurePreferences.isPushRegistered(context)) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new DirectoryRefreshJob(context, true));
+ .add(new DirectoryRefreshJob(true));
}
long newTime = System.currentTimeMillis() + INTERVAL;
diff --git a/src/org/thoughtcrime/securesms/service/IncomingMessageObserver.java b/src/org/thoughtcrime/securesms/service/IncomingMessageObserver.java
index dacbc49e6b..c0d7ac95aa 100644
--- a/src/org/thoughtcrime/securesms/service/IncomingMessageObserver.java
+++ b/src/org/thoughtcrime/securesms/service/IncomingMessageObserver.java
@@ -12,14 +12,14 @@ import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
+import org.thoughtcrime.securesms.jobmanager.ConstraintObserver;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
+import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.InjectableType;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement;
-import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirementProvider;
-import org.thoughtcrime.securesms.jobmanager.requirements.RequirementListener;
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
@@ -33,7 +33,7 @@ import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
-public class IncomingMessageObserver implements InjectableType, RequirementListener {
+public class IncomingMessageObserver implements InjectableType, ConstraintObserver.Notifier {
private static final String TAG = IncomingMessageObserver.class.getSimpleName();
@@ -43,8 +43,8 @@ public class IncomingMessageObserver implements InjectableType, RequirementListe
private static SignalServiceMessagePipe pipe = null;
private static SignalServiceMessagePipe unidentifiedPipe = null;
- private final Context context;
- private final NetworkRequirement networkRequirement;
+ private final Context context;
+ private final NetworkConstraint networkConstraint;
private boolean appVisible;
@@ -55,9 +55,9 @@ public class IncomingMessageObserver implements InjectableType, RequirementListe
ApplicationContext.getInstance(context).injectDependencies(this);
this.context = context;
- this.networkRequirement = new NetworkRequirement(context);
+ this.networkConstraint = new NetworkConstraint.Factory(ApplicationContext.getInstance(context)).create();
- new NetworkRequirementProvider(context).setListener(this);
+ new NetworkConstraintObserver(ApplicationContext.getInstance(context)).register(this);
new MessageRetrievalThread().start();
if (TextSecurePreferences.isFcmDisabled(context)) {
@@ -78,7 +78,7 @@ public class IncomingMessageObserver implements InjectableType, RequirementListe
}
@Override
- public void onRequirementStatusChanged() {
+ public void onConstraintMet(@NonNull String reason) {
synchronized (this) {
notifyAll();
}
@@ -98,12 +98,12 @@ public class IncomingMessageObserver implements InjectableType, RequirementListe
boolean isGcmDisabled = TextSecurePreferences.isFcmDisabled(context);
Log.d(TAG, String.format("Network requirement: %s, app visible: %s, gcm disabled: %b",
- networkRequirement.isPresent(), appVisible, isGcmDisabled));
+ networkConstraint.isMet(), appVisible, isGcmDisabled));
return TextSecurePreferences.isPushRegistered(context) &&
TextSecurePreferences.isWebsocketRegistered(context) &&
(appVisible || isGcmDisabled) &&
- networkRequirement.isPresent() &&
+ networkConstraint.isMet() &&
!networkAccess.isCensored(context);
}
diff --git a/src/org/thoughtcrime/securesms/service/LocalBackupListener.java b/src/org/thoughtcrime/securesms/service/LocalBackupListener.java
index d60dad3498..57ae5de31e 100644
--- a/src/org/thoughtcrime/securesms/service/LocalBackupListener.java
+++ b/src/org/thoughtcrime/securesms/service/LocalBackupListener.java
@@ -22,7 +22,7 @@ public class LocalBackupListener extends PersistentAlarmManagerListener {
@Override
protected long onAlarm(Context context, long scheduledTime) {
if (TextSecurePreferences.isBackupEnabled(context)) {
- ApplicationContext.getInstance(context).getJobManager().add(new LocalBackupJob(context));
+ ApplicationContext.getInstance(context).getJobManager().add(new LocalBackupJob());
}
long nextTime = System.currentTimeMillis() + INTERVAL;
diff --git a/src/org/thoughtcrime/securesms/service/MmsListener.java b/src/org/thoughtcrime/securesms/service/MmsListener.java
index 09d9797cb5..b7d3d93383 100644
--- a/src/org/thoughtcrime/securesms/service/MmsListener.java
+++ b/src/org/thoughtcrime/securesms/service/MmsListener.java
@@ -19,13 +19,11 @@ package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import android.provider.Telephony;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.MmsReceiveJob;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
public class MmsListener extends BroadcastReceiver {
@@ -58,7 +56,7 @@ public class MmsListener extends BroadcastReceiver {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new MmsReceiveJob(context, intent.getByteArrayExtra("data"), subscriptionId));
+ .add(new MmsReceiveJob(intent.getByteArrayExtra("data"), subscriptionId));
abortBroadcast();
}
diff --git a/src/org/thoughtcrime/securesms/service/RotateSignedPreKeyListener.java b/src/org/thoughtcrime/securesms/service/RotateSignedPreKeyListener.java
index 0eee795d62..06ed207f27 100644
--- a/src/org/thoughtcrime/securesms/service/RotateSignedPreKeyListener.java
+++ b/src/org/thoughtcrime/securesms/service/RotateSignedPreKeyListener.java
@@ -24,7 +24,7 @@ public class RotateSignedPreKeyListener extends PersistentAlarmManagerListener {
if (scheduledTime != 0 && TextSecurePreferences.isPushRegistered(context)) {
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new RotateSignedPreKeyJob(context));
+ .add(new RotateSignedPreKeyJob());
}
long nextTime = System.currentTimeMillis() + INTERVAL;
diff --git a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java b/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java
index 09047f2617..00854e0f87 100644
--- a/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java
+++ b/src/org/thoughtcrime/securesms/service/SmsDeliveryListener.java
@@ -4,11 +4,12 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
+
+import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.database.SmsDatabase;
-import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.SmsSentJob;
public class SmsDeliveryListener extends BroadcastReceiver {
@@ -20,15 +21,15 @@ public class SmsDeliveryListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
- long messageId = intent.getLongExtra("message_id", -1);
- int runAttempt = intent.getIntExtra("run_attempt", 0);
+ JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
+ long messageId = intent.getLongExtra("message_id", -1);
+ int runAttempt = intent.getIntExtra("run_attempt", 0);
switch (intent.getAction()) {
case SENT_SMS_ACTION:
int result = getResultCode();
- jobManager.add(new SmsSentJob(context, messageId, SENT_SMS_ACTION, result, runAttempt));
+ jobManager.add(new SmsSentJob(messageId, SENT_SMS_ACTION, result, runAttempt));
break;
case DELIVERED_SMS_ACTION:
byte[] pdu = intent.getByteArrayExtra("pdu");
@@ -59,7 +60,7 @@ public class SmsDeliveryListener extends BroadcastReceiver {
else if (status >> 24 == 3) status = SmsDatabase.Status.STATUS_FAILED;
}
- jobManager.add(new SmsSentJob(context, messageId, DELIVERED_SMS_ACTION, status, runAttempt));
+ jobManager.add(new SmsSentJob(messageId, DELIVERED_SMS_ACTION, status, runAttempt));
break;
default:
Log.w(TAG, "Unknown action: " + intent.getAction());
diff --git a/src/org/thoughtcrime/securesms/service/SmsListener.java b/src/org/thoughtcrime/securesms/service/SmsListener.java
index 67bf62c453..28df7b3bb3 100644
--- a/src/org/thoughtcrime/securesms/service/SmsListener.java
+++ b/src/org/thoughtcrime/securesms/service/SmsListener.java
@@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
import android.provider.Telephony;
import android.telephony.SmsMessage;
@@ -27,7 +26,6 @@ import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.SmsReceiveJob;
-import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
public class SmsListener extends BroadcastReceiver {
@@ -107,7 +105,7 @@ public class SmsListener extends BroadcastReceiver {
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
int subscriptionId = intent.getExtras().getInt("subscription", -1);
- ApplicationContext.getInstance(context).getJobManager().add(new SmsReceiveJob(context, pdus, subscriptionId));
+ ApplicationContext.getInstance(context).getJobManager().add(new SmsReceiveJob(pdus, subscriptionId));
abortBroadcast();
}
diff --git a/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java b/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
index 4d4d7bdbd7..cebf3499fd 100644
--- a/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
+++ b/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java
@@ -31,7 +31,7 @@ public class UpdateApkRefreshListener extends PersistentAlarmManagerListener {
Log.i(TAG, "Queueing APK update job...");
ApplicationContext.getInstance(context)
.getJobManager()
- .add(new UpdateApkJob(context));
+ .add(new UpdateApkJob());
}
long newTime = System.currentTimeMillis() + INTERVAL;
diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java
index c017188fd1..ea0a27bbbc 100644
--- a/src/org/thoughtcrime/securesms/sms/MessageSender.java
+++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java
@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
+import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.ApplicationContext;
@@ -35,7 +36,6 @@ import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
-import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.MmsSendJob;
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
import org.thoughtcrime.securesms.jobs.PushMediaSendJob;
@@ -159,7 +159,7 @@ public class MessageSender {
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
- jobManager.add(new PushTextSendJob(context, messageId, recipient.getAddress()));
+ jobManager.add(new PushTextSendJob(messageId, recipient.getAddress()));
}
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
@@ -179,7 +179,7 @@ public class MessageSender {
private static void sendMms(Context context, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
- jobManager.add(new MmsSendJob(context, messageId));
+ jobManager.add(new MmsSendJob(messageId));
}
private static boolean isPushTextSend(Context context, Recipient recipient, boolean keyExchange) {
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index c8a015446e..cd769178e4 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -11,11 +11,12 @@ import android.support.annotation.ArrayRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
+
+import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver;
import org.thoughtcrime.securesms.logging.Log;
import org.greenrobot.eventbus.EventBus;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirementProvider;
import org.thoughtcrime.securesms.lock.RegistrationLockReminders;
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
import org.whispersystems.libsignal.util.Medium;
@@ -285,7 +286,7 @@ public class TextSecurePreferences {
public static void setNeedsSqlCipherMigration(@NonNull Context context, boolean value) {
setBooleanPreference(context, NEEDS_SQLCIPHER_MIGRATION, value);
- EventBus.getDefault().post(new SqlCipherMigrationRequirementProvider.SqlCipherNeedsMigrationEvent());
+ EventBus.getDefault().post(new SqlCipherMigrationConstraintObserver.SqlCipherNeedsMigrationEvent());
}
public static boolean getNeedsSqlCipherMigration(@NonNull Context context) {
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/jobmanager/impl/JsonDataSerializerTest.java b/test/unitTest/java/org/thoughtcrime/securesms/jobmanager/impl/JsonDataSerializerTest.java
new file mode 100644
index 0000000000..cd2a66e624
--- /dev/null
+++ b/test/unitTest/java/org/thoughtcrime/securesms/jobmanager/impl/JsonDataSerializerTest.java
@@ -0,0 +1,47 @@
+package org.thoughtcrime.securesms.jobmanager.impl;
+
+import org.junit.Test;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.util.Util;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public final class JsonDataSerializerTest {
+
+ private static final float FloatDelta = 0.00001f;
+
+ @Test
+ public void deserialize_dataMatchesExpected() throws IOException {
+ Data data = new JsonDataSerializer().deserialize(Util.readFullyAsString(ClassLoader.getSystemClassLoader().getResourceAsStream("data/data_serialized.json")));
+
+ assertEquals("s1 value", data.getString("s1"));
+ assertEquals("s2 value", data.getString("s2"));
+ assertArrayEquals(new String[]{ "a", "b", "c" }, data.getStringArray("s_array_1"));
+
+ assertEquals(1, data.getInt("i1"));
+ assertEquals(2, data.getInt("i2"));
+ assertEquals(Integer.MAX_VALUE, data.getInt("max"));
+ assertEquals(Integer.MIN_VALUE, data.getInt("min"));
+ assertArrayEquals(new int[]{ 1, 2, 3, Integer.MAX_VALUE, Integer.MIN_VALUE }, data.getIntegerArray("i_array_1"));
+
+ assertEquals(10, data.getLong("l1"));
+ assertEquals(20, data.getLong("l2"));
+ assertEquals(Long.MAX_VALUE, data.getLong("max"));
+ assertEquals(Long.MIN_VALUE, data.getLong("min"));
+ assertArrayEquals(new long[]{ 1, 2, 3, Long.MAX_VALUE, Long.MIN_VALUE }, data.getLongArray("l_array_1"));
+
+ assertEquals(1.2f, data.getFloat("f1"), FloatDelta);
+ assertEquals(3.4f, data.getFloat("f2"), FloatDelta);
+ assertArrayEquals(new float[]{ 5.6f, 7.8f }, data.getFloatArray("f_array_1"), FloatDelta);
+
+ assertEquals(10.2, data.getDouble("d1"), FloatDelta);
+ assertEquals(30.4, data.getDouble("d2"), FloatDelta);
+ assertArrayEquals(new double[]{ 50.6, 70.8 }, data.getDoubleArray("d_array_1"), FloatDelta);
+
+ assertTrue(data.getBoolean("b1"));
+ assertFalse(data.getBoolean("b2"));
+ assertArrayEquals(new boolean[]{ false, true }, data.getBooleanArray("b_array_1"));
+ }
+}
\ No newline at end of file
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java b/test/unitTest/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
new file mode 100644
index 0000000000..7844aa0672
--- /dev/null
+++ b/test/unitTest/java/org/thoughtcrime/securesms/jobs/FastJobStorageTest.java
@@ -0,0 +1,352 @@
+package org.thoughtcrime.securesms.jobs;
+
+import android.support.annotation.NonNull;
+
+import com.annimon.stream.Stream;
+
+import org.junit.Test;
+import org.thoughtcrime.securesms.database.JobDatabase;
+import org.thoughtcrime.securesms.jobmanager.Data;
+import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer;
+import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec;
+import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class FastJobStorageTest {
+
+ private static final JsonDataSerializer serializer = new JsonDataSerializer();
+ private static final String EMPTY_DATA = serializer.serialize(Data.EMPTY);
+
+ @Test
+ public void init_allStoredDataAvailable() {
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
+
+ subject.init();
+
+ DataSet1.assertJobsMatch(subject.getAllJobSpecs());
+ DataSet1.assertConstraintsMatch(subject.getAllConstraintSpecs());
+ DataSet1.assertDependenciesMatch(subject.getAllDependencySpecs());
+ }
+
+ @Test
+ public void insertJobs_writesToDatabase() {
+ JobDatabase database = noopDatabase();
+ FastJobStorage subject = new FastJobStorage(database);
+
+ subject.insertJobs(DataSet1.FULL_SPECS);
+
+ verify(database).insertJobs(DataSet1.FULL_SPECS);
+ }
+
+ @Test
+ public void insertJobs_dataCanBeFound() {
+ FastJobStorage subject = new FastJobStorage(noopDatabase());
+
+ subject.insertJobs(DataSet1.FULL_SPECS);
+
+ DataSet1.assertJobsMatch(subject.getAllJobSpecs());
+ DataSet1.assertConstraintsMatch(subject.getAllConstraintSpecs());
+ DataSet1.assertDependenciesMatch(subject.getAllDependencySpecs());
+ }
+
+ @Test
+ public void insertJobs_individualJobCanBeFound() {
+ FastJobStorage subject = new FastJobStorage(noopDatabase());
+
+ subject.insertJobs(DataSet1.FULL_SPECS);
+
+ assertEquals(DataSet1.JOB_1, subject.getJobSpec(DataSet1.JOB_1.getId()));
+ assertEquals(DataSet1.JOB_2, subject.getJobSpec(DataSet1.JOB_2.getId()));
+ }
+
+ @Test
+ public void updateAllJobsToBePending_writesToDatabase() {
+ JobDatabase database = noopDatabase();
+ FastJobStorage subject = new FastJobStorage(database);
+
+ subject.updateAllJobsToBePending();
+
+ verify(database).updateAllJobsToBePending();
+ }
+
+ @Test
+ public void updateAllJobsToBePending_allArePending() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", null, 1, 1, 1, 1, 1, 1, 1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", null, 1, 1, 1, 1, 1, 1, 1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+
+ subject.init();
+ subject.updateAllJobsToBePending();
+
+ assertFalse(subject.getJobSpec("1").isRunning());
+ assertFalse(subject.getJobSpec("2").isRunning());
+ }
+
+ @Test
+ public void updateJobRunningState_writesToDatabase() {
+ JobDatabase database = noopDatabase();
+ FastJobStorage subject = new FastJobStorage(database);
+
+ subject.updateJobRunningState("1", true);
+
+ verify(database).updateJobRunningState("1", true);
+ }
+
+ @Test
+ public void updateJobRunningState_stateUpdated() {
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
+ subject.init();
+
+ subject.updateJobRunningState(DataSet1.JOB_1.getId(), true);
+ assertTrue(subject.getJobSpec(DataSet1.JOB_1.getId()).isRunning());
+
+ subject.updateJobRunningState(DataSet1.JOB_1.getId(), false);
+ assertFalse(subject.getJobSpec(DataSet1.JOB_1.getId()).isRunning());
+ }
+
+ @Test
+ public void updateJobAfterRetry_writesToDatabase() {
+ JobDatabase database = noopDatabase();
+ FastJobStorage subject = new FastJobStorage(database);
+
+ subject.updateJobAfterRetry("1", true, 1, 10);
+
+ verify(database).updateJobAfterRetry("1", true, 1, 10);
+ }
+
+ @Test
+ public void updateJobAfterRetry_stateUpdated() {
+ FullSpec fullSpec = new FullSpec(new JobSpec("1", "f1", null, 0, 0, 0, 3, 30000, -1, -1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
+
+ subject.init();
+ subject.updateJobAfterRetry("1", false, 1, 10);
+
+ JobSpec job = subject.getJobSpec("1");
+
+ assertNotNull(job);
+ assertFalse(job.isRunning());
+ assertEquals(1, job.getRunAttempt());
+ assertEquals(10, job.getNextRunAttemptTime());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenEarlierItemInQueueInRunning() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+ subject.init();
+
+ assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(1).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenAllJobsAreRunning() {
+ FullSpec fullSpec = new FullSpec(new JobSpec("1", "f1", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
+ subject.init();
+
+ assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenNextRunTimeIsAfterCurrentTime() {
+ FullSpec fullSpec = new FullSpec(new JobSpec("1", "f1", "q", 0, 10, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
+ subject.init();
+
+ assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(0).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_noneWhenDependentOnAnotherJob() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.singletonList(new DependencySpec("2", "1")));
+
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+ subject.init();
+
+ assertEquals(0, subject.getPendingJobsWithNoDependenciesInCreatedOrder(0).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_singleEligibleJob() {
+ FullSpec fullSpec = new FullSpec(new JobSpec("1", "f1", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Collections.singletonList(fullSpec)));
+ subject.init();
+
+ assertEquals(1, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_multipleEligibleJobs() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+ subject.init();
+
+ assertEquals(2, subject.getPendingJobsWithNoDependenciesInCreatedOrder(10).size());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_singleEligibleJobInMixedList() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, true),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", null, 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+ subject.init();
+
+ List jobs = subject.getPendingJobsWithNoDependenciesInCreatedOrder(10);
+
+ assertEquals(1, jobs.size());
+ assertEquals("2", jobs.get(0).getId());
+ }
+
+ @Test
+ public void getPendingJobsWithNoDependenciesInCreatedOrder_firstItemInQueue() {
+ FullSpec fullSpec1 = new FullSpec(new JobSpec("1", "f1", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+ FullSpec fullSpec2 = new FullSpec(new JobSpec("2", "f2", "q", 0, 0, 0, 0, 0, -1, -1, EMPTY_DATA, false),
+ Collections.emptyList(),
+ Collections.emptyList());
+
+
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(Arrays.asList(fullSpec1, fullSpec2)));
+ subject.init();
+
+ List jobs = subject.getPendingJobsWithNoDependenciesInCreatedOrder(10);
+
+ assertEquals(1, jobs.size());
+ assertEquals("1", jobs.get(0).getId());
+ }
+
+ @Test
+ public void deleteJobs_writesToDatabase() {
+ JobDatabase database = noopDatabase();
+ FastJobStorage subject = new FastJobStorage(database);
+ List ids = Arrays.asList("1", "2");
+
+ subject.deleteJobs(ids);
+
+ verify(database).deleteJobs(ids);
+ }
+
+ @Test
+ public void deleteJobs_deletesAllRelevantPieces() {
+ FastJobStorage subject = new FastJobStorage(fixedDataDatabase(DataSet1.FULL_SPECS));
+
+ subject.init();
+ subject.deleteJobs(Collections.singletonList("id1"));
+
+ List jobs = subject.getAllJobSpecs();
+ List constraints = subject.getAllConstraintSpecs();
+ List dependencies = subject.getAllDependencySpecs();
+
+ assertEquals(1, jobs.size());
+ assertEquals(DataSet1.JOB_2, jobs.get(0));
+ assertEquals(1, constraints.size());
+ assertEquals(DataSet1.CONSTRAINT_2, constraints.get(0));
+ assertEquals(0, dependencies.size());
+ }
+
+
+ private JobDatabase noopDatabase() {
+ JobDatabase database = mock(JobDatabase.class);
+
+ when(database.getAllJobSpecs()).thenReturn(Collections.emptyList());
+ when(database.getAllConstraintSpecs()).thenReturn(Collections.emptyList());
+ when(database.getAllDependencySpecs()).thenReturn(Collections.emptyList());
+
+ return database;
+ }
+
+ private JobDatabase fixedDataDatabase(List fullSpecs) {
+ JobDatabase database = mock(JobDatabase.class);
+
+ when(database.getAllJobSpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getJobSpec).toList());
+ when(database.getAllConstraintSpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getConstraintSpecs).flatMap(Stream::of).toList());
+ when(database.getAllDependencySpecs()).thenReturn(Stream.of(fullSpecs).map(FullSpec::getDependencySpecs).flatMap(Stream::of).toList());
+
+ return database;
+ }
+
+ private static final class DataSet1 {
+ static final JobSpec JOB_1 = new JobSpec("id1", "f1", "q1", 1, 2, 3, 4, 5, 6, 7, EMPTY_DATA, false);
+ static final JobSpec JOB_2 = new JobSpec("id2", "f2", "q2", 1, 2, 3, 4, 5, 6, 7, EMPTY_DATA, false);
+ static final ConstraintSpec CONSTRAINT_1 = new ConstraintSpec("id1", "f1");
+ static final ConstraintSpec CONSTRAINT_2 = new ConstraintSpec("id2", "f2");
+ static final DependencySpec DEPENDENCY_2 = new DependencySpec("id2", "id1");
+ static final FullSpec FULL_SPEC_1 = new FullSpec(JOB_1, Collections.singletonList(CONSTRAINT_1), Collections.emptyList());
+ static final FullSpec FULL_SPEC_2 = new FullSpec(JOB_2, Collections.singletonList(CONSTRAINT_2), Collections.singletonList(DEPENDENCY_2));
+ static final List FULL_SPECS = Arrays.asList(FULL_SPEC_1, FULL_SPEC_2);
+
+ static void assertJobsMatch(@NonNull List jobs) {
+ assertEquals(jobs.size(), 2);
+ assertTrue(jobs.contains(DataSet1.JOB_1));
+ assertTrue(jobs.contains(DataSet1.JOB_1));
+ }
+
+ static void assertConstraintsMatch(@NonNull List constraints) {
+ assertEquals(constraints.size(), 2);
+ assertTrue(constraints.contains(DataSet1.CONSTRAINT_1));
+ assertTrue(constraints.contains(DataSet1.CONSTRAINT_2));
+ }
+
+ static void assertDependenciesMatch(@NonNull List dependencies) {
+ assertEquals(dependencies.size(), 1);
+ assertTrue(dependencies.contains(DataSet1.DEPENDENCY_2));
+ }
+ }
+}
diff --git a/test/unitTest/java/org/thoughtcrime/securesms/testutil/DirectExecutor.java b/test/unitTest/java/org/thoughtcrime/securesms/testutil/DirectExecutor.java
new file mode 100644
index 0000000000..b602ba25ba
--- /dev/null
+++ b/test/unitTest/java/org/thoughtcrime/securesms/testutil/DirectExecutor.java
@@ -0,0 +1,16 @@
+package org.thoughtcrime.securesms.testutil;
+
+import android.support.annotation.NonNull;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Executor that runs runnables on the same thread {@link #execute(Runnable)} is invoked on.
+ * Only intended to be used for tests.
+ */
+public class DirectExecutor implements Executor {
+ @Override
+ public void execute(@NonNull Runnable runnable) {
+ runnable.run();
+ }
+}
diff --git a/test/unitTest/resources/data/data_serialized.json b/test/unitTest/resources/data/data_serialized.json
new file mode 100644
index 0000000000..7f8d235937
--- /dev/null
+++ b/test/unitTest/resources/data/data_serialized.json
@@ -0,0 +1,73 @@
+{
+ "strings": {
+ "s1": "s1 value",
+ "s2": "s2 value"
+ },
+ "stringArrays": {
+ "s_array_1": [
+ "a",
+ "b",
+ "c"
+ ]
+ },
+ "integers": {
+ "i1": 1,
+ "i2": 2,
+ "max": 2147483647,
+ "min": -2147483648
+ },
+ "integerArrays": {
+ "i_array_1": [
+ 1,
+ 2,
+ 3,
+ 2147483647,
+ -2147483648
+ ]
+ },
+ "longs": {
+ "l1": 10,
+ "l2": 20,
+ "max": 9223372036854775807,
+ "min": -9223372036854775808
+ },
+ "longArrays": {
+ "l_array_1": [
+ 1,
+ 2,
+ 3,
+ 9223372036854775807,
+ -9223372036854775808
+ ]
+ },
+ "floats": {
+ "f1": 1.2,
+ "f2": 3.4
+ },
+ "floatArrays": {
+ "f_array_1": [
+ 5.6,
+ 7.8
+ ]
+ },
+ "doubles": {
+ "d1": 10.2,
+ "d2": 30.4
+ },
+ "doubleArrays": {
+ "d_array_1": [
+ 50.6,
+ 70.8
+ ]
+ },
+ "booleans": {
+ "b1": true,
+ "b2": false
+ },
+ "booleanArrays": {
+ "b_array_1": [
+ false,
+ true
+ ]
+ }
+}
\ No newline at end of file