use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class CommonTestHelper method createAccountAndSync.
/**
* Create an account and a dedicated session
*
* @param context the context
* @param userName the account username
* @param password the password
* @param sessionTestParams parameters for the test
*/
private MXSession createAccountAndSync(Context context, String userName, String password, SessionTestParams sessionTestParams) throws InterruptedException {
final HomeServerConnectionConfig hs = createHomeServerConfig(null);
final LoginRestClient loginRestClient = new LoginRestClient(hs);
final Map<String, Object> params = new HashMap<>();
final RegistrationParams registrationParams = new RegistrationParams();
CountDownLatch lock = new CountDownLatch(1);
// get the registration session id
loginRestClient.register(registrationParams, new TestApiCallback<Credentials>(lock, false) {
@Override
public void onMatrixError(MatrixError e) {
// detect if a parameter is expected
RegistrationFlowResponse registrationFlowResponse = null;
// when a response is not completed the server returns an error message
if ((null != e.mStatus) && (e.mStatus == 401)) {
try {
registrationFlowResponse = JsonUtils.toRegistrationFlowResponse(e.mErrorBodyAsString);
} catch (Exception castExcept) {
}
}
// check if the server response can be casted
if (null != registrationFlowResponse) {
params.put("session", registrationFlowResponse.session);
}
super.onMatrixError(e);
}
});
await(lock);
final String session = (String) params.get("session");
Assert.assertNotNull(session);
registrationParams.username = userName;
registrationParams.password = password;
AuthParams authParams = new AuthParams(LoginRestClient.LOGIN_FLOW_TYPE_DUMMY);
authParams.session = session;
registrationParams.auth = authParams;
lock = new CountDownLatch(1);
loginRestClient.register(registrationParams, new TestApiCallback<Credentials>(lock) {
@Override
public void onSuccess(Credentials credentials) {
params.put("credentials", credentials);
super.onSuccess(credentials);
}
});
await(lock);
Credentials credentials = (Credentials) params.get("credentials");
Assert.assertNotNull(credentials);
hs.setCredentials(credentials);
IMXStore store = new MXFileStore(hs, false, context);
MXDataHandler dataHandler = new MXDataHandler(store, credentials);
dataHandler.setLazyLoadingEnabled(sessionTestParams.getWithLazyLoading());
MXSession mxSession = new MXSession.Builder(hs, dataHandler, context).withLegacyCryptoStore(sessionTestParams.getWithLegacyCryptoStore()).build();
if (sessionTestParams.getWithCryptoEnabled()) {
mxSession.enableCryptoWhenStarting();
}
if (sessionTestParams.getWithInitialSync()) {
syncSession(mxSession, sessionTestParams.getWithCryptoEnabled());
}
return mxSession;
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class EventsThread method startSync.
/**
* Start the events sync
*/
@SuppressLint("NewApi")
private void startSync() {
int serverTimeout;
mPaused = false;
if (isInitialSyncDone()) {
resumeInitialSync();
serverTimeout = 0;
} else {
// Start with initial sync
executeInitialSync();
serverTimeout = mNextServerTimeoutms;
}
Log.d(LOG_TAG, "Starting event stream from token " + mCurrentToken);
// sanity check
if (null != mNetworkConnectivityReceiver) {
mNetworkConnectivityReceiver.addEventListener(mNetworkListener);
//
mbIsConnected = mNetworkConnectivityReceiver.isConnected();
mIsNetworkSuspended = !mbIsConnected;
}
while (!mKilling) {
// test if a delay between two syncs
if ((!mPaused && !mIsNetworkSuspended) && (0 != mRequestDelayMs)) {
Log.d(LOG_TAG, "startSync : start a delay timer ");
Intent intent = new Intent(mContext, SyncDelayReceiver.class);
intent.putExtra(SyncDelayReceiver.EXTRA_INSTANCE_ID, toString());
mPendingDelayedIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long futureInMillis = SystemClock.elapsedRealtime() + mRequestDelayMs;
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) && mPowerManager.isIgnoringBatteryOptimizations(mContext.getPackageName())) {
mAlarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, mPendingDelayedIntent);
} else {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, mPendingDelayedIntent);
}
}
if (mPaused || mIsNetworkSuspended || (null != mPendingDelayedIntent)) {
if (null != mPendingDelayedIntent) {
Log.d(LOG_TAG, "Event stream is paused because there is a timer delay.");
} else if (mIsNetworkSuspended) {
Log.d(LOG_TAG, "Event stream is paused because there is no available network.");
} else {
Log.d(LOG_TAG, "Event stream is paused. Waiting.");
}
try {
Log.d(LOG_TAG, "startSync : wait ...");
synchronized (mSyncObject) {
mSyncObject.wait();
}
if (null != mPendingDelayedIntent) {
Log.d(LOG_TAG, "startSync : cancel mSyncDelayTimer");
mAlarmManager.cancel(mPendingDelayedIntent);
mPendingDelayedIntent.cancel();
mPendingDelayedIntent = null;
}
Log.d(LOG_TAG, "Event stream woken from pause.");
// perform a catchup asap
serverTimeout = 0;
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Unexpected interruption while paused: " + e.getMessage(), e);
}
}
// the service could have been killed while being paused.
if (!mKilling) {
long incrementalSyncStartTime = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(1);
Log.d(LOG_TAG, "Get events from token " + mCurrentToken + " with filterOrFilterId " + mFilterOrFilterId);
final int fServerTimeout = serverTimeout;
mNextServerTimeoutms = mDefaultServerTimeoutms;
mEventsRestClient.syncFromToken(mCurrentToken, serverTimeout, DEFAULT_CLIENT_TIMEOUT_MS, mIsOnline ? null : "offline", mFilterOrFilterId, new SimpleApiCallback<SyncResponse>(mFailureCallback) {
@Override
public void onSuccess(SyncResponse syncResponse) {
if (!mKilling) {
// we get no to_device messages back.
if (0 == fServerTimeout) {
if (hasDevicesChanged(syncResponse)) {
if (mIsCatchingUp) {
Log.d(LOG_TAG, "Some devices have changed but do not set mNextServerTimeoutms to 0 to avoid infinite loops");
} else {
Log.d(LOG_TAG, "mNextServerTimeoutms is set to 0 because of hasDevicesChanged " + syncResponse.deviceLists.changed);
mNextServerTimeoutms = 0;
}
}
}
// to loop again
if (mIsCatchingUp && (0 != mNextServerTimeoutms)) {
// the catchup triggers sync requests until there are some useful events
int eventCounts = 0;
if (null != syncResponse.rooms) {
RoomsSyncResponse roomsSyncResponse = syncResponse.rooms;
if (null != roomsSyncResponse.join) {
eventCounts += roomsSyncResponse.join.size();
}
if (null != roomsSyncResponse.invite) {
eventCounts += roomsSyncResponse.invite.size();
}
}
// stop any catch up
mIsCatchingUp = false;
mPaused = (0 == mRequestDelayMs);
Log.d(LOG_TAG, "Got " + eventCounts + " useful events while catching up : mPaused is set to " + mPaused);
}
Log.d(LOG_TAG, "Got event response");
mListener.onSyncResponse(syncResponse, mCurrentToken, (0 == mNextServerTimeoutms));
mCurrentToken = syncResponse.nextBatch;
Log.d(LOG_TAG, "mCurrentToken is now set to " + mCurrentToken);
}
// unblock the events thread
latch.countDown();
}
private void onError(String description) {
boolean isConnected;
Log.d(LOG_TAG, "Got an error while polling events " + description);
synchronized (mSyncObject) {
isConnected = mbIsConnected;
}
// detected if the device is connected before trying again
if (isConnected) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
public void run() {
latch.countDown();
}
}, RETRY_WAIT_TIME_MS);
} else {
// no network -> wait that a network connection comes back.
mIsNetworkSuspended = true;
latch.countDown();
}
}
@Override
public void onNetworkError(Exception e) {
onError(e.getLocalizedMessage());
}
@Override
public void onMatrixError(MatrixError e) {
if (MatrixError.isConfigurationErrorCode(e.errcode)) {
mListener.onConfigurationError(e.errcode);
} else {
mListener.onSyncError(e);
onError(e.getLocalizedMessage());
}
}
@Override
public void onUnexpectedError(Exception e) {
onError(e.getLocalizedMessage());
}
});
// block until the sync callback is invoked.
try {
latch.await();
} catch (InterruptedException e) {
Log.e(LOG_TAG, "Interrupted whilst polling message", e);
} catch (Exception e) {
// reported by GA
// The thread might have been killed.
Log.e(LOG_TAG, "latch.await() failed " + e.getMessage(), e);
}
long incrementalSyncEndTime = System.currentTimeMillis();
long incrementalSyncDuration = incrementalSyncEndTime - incrementalSyncStartTime;
if (mMetricsListener != null) {
mMetricsListener.onIncrementalSyncFinished(incrementalSyncDuration);
}
}
serverTimeout = mNextServerTimeoutms;
}
if (null != mNetworkConnectivityReceiver) {
mNetworkConnectivityReceiver.removeEventListener(mNetworkListener);
}
Log.d(LOG_TAG, "Event stream terminating.");
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MXMegolmDecryption method shareKeysWithDevice.
@Override
public void shareKeysWithDevice(final IncomingRoomKeyRequest request) {
// sanity checks
if ((null == request) || (null == request.mRequestBody)) {
return;
}
final String userId = request.mUserId;
mCrypto.getDeviceList().downloadKeys(Arrays.asList(userId), false, new ApiCallback<MXUsersDevicesMap<MXDeviceInfo>>() {
@Override
public void onSuccess(MXUsersDevicesMap<MXDeviceInfo> devicesMap) {
final String deviceId = request.mDeviceId;
final MXDeviceInfo deviceInfo = mCrypto.mCryptoStore.getUserDevice(deviceId, userId);
if (null != deviceInfo) {
final RoomKeyRequestBody body = request.mRequestBody;
Map<String, List<MXDeviceInfo>> devicesByUser = new HashMap<>();
devicesByUser.put(userId, new ArrayList<>(Arrays.asList(deviceInfo)));
mCrypto.ensureOlmSessionsForDevices(devicesByUser, new ApiCallback<MXUsersDevicesMap<MXOlmSessionResult>>() {
@Override
public void onSuccess(MXUsersDevicesMap<MXOlmSessionResult> map) {
MXOlmSessionResult olmSessionResult = map.getObject(deviceId, userId);
if ((null == olmSessionResult) || (null == olmSessionResult.mSessionId)) {
// so just skip it.
return;
}
Log.d(LOG_TAG, "## shareKeysWithDevice() : sharing keys for session " + body.senderKey + "|" + body.sessionId + " with device " + userId + ":" + deviceId);
MXOlmInboundGroupSession2 inboundGroupSession = mCrypto.getOlmDevice().getInboundGroupSession(body.sessionId, body.senderKey, body.roomId);
Map<String, Object> payloadJson = new HashMap<>();
payloadJson.put("type", CryptoEvent.EVENT_TYPE_FORWARDED_ROOM_KEY);
payloadJson.put("content", inboundGroupSession.exportKeys());
EncryptedMessage encodedPayload = mCrypto.encryptMessage(payloadJson, Arrays.asList(deviceInfo));
MXUsersDevicesMap<Object> sendToDeviceMap = new MXUsersDevicesMap<>();
sendToDeviceMap.setObject(encodedPayload, userId, deviceId);
Log.d(LOG_TAG, "## shareKeysWithDevice() : sending to " + userId + ":" + deviceId);
mCrypto.getCryptoRestClient().sendToDevice(CryptoEvent.EVENT_TYPE_MESSAGE_ENCRYPTED, sendToDeviceMap, new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
Log.d(LOG_TAG, "## shareKeysWithDevice() : sent to " + userId + ":" + deviceId);
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage(), e);
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage());
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : sendToDevice " + userId + ":" + deviceId + " failed " + e.getMessage(), e);
}
});
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage(), e);
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage());
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " failed " + e.getMessage(), e);
}
});
} else {
Log.e(LOG_TAG, "## shareKeysWithDevice() : ensureOlmSessionsForDevices " + userId + ":" + deviceId + " not found");
}
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : downloadKeys " + userId + " failed " + e.getMessage(), e);
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : downloadKeys " + userId + " failed " + e.getMessage());
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareKeysWithDevice() : downloadKeys " + userId + " failed " + e.getMessage(), e);
}
});
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MXMegolmEncryption method shareUserDevicesKey.
/**
* Share the device keys of a an user
*
* @param session the session info
* @param devicesByUser the devices map
* @param callback the asynchronous callback
*/
private void shareUserDevicesKey(final MXOutboundSessionInfo session, final Map<String, List<MXDeviceInfo>> devicesByUser, final ApiCallback<Void> callback) {
final String sessionKey = mCrypto.getOlmDevice().getSessionKey(session.mSessionId);
final int chainIndex = mCrypto.getOlmDevice().getMessageIndex(session.mSessionId);
Map<String, Object> submap = new HashMap<>();
submap.put("algorithm", CryptoConstantsKt.MXCRYPTO_ALGORITHM_MEGOLM);
submap.put("room_id", mRoomId);
submap.put("session_id", session.mSessionId);
submap.put("session_key", sessionKey);
submap.put("chain_index", chainIndex);
final Map<String, Object> payload = new HashMap<>();
payload.put("type", CryptoEvent.EVENT_TYPE_ROOM_KEY);
payload.put("content", submap);
final long t0 = System.currentTimeMillis();
Log.d(LOG_TAG, "## shareUserDevicesKey() : starts");
mCrypto.ensureOlmSessionsForDevices(devicesByUser, new ApiCallback<MXUsersDevicesMap<MXOlmSessionResult>>() {
@Override
public void onSuccess(final MXUsersDevicesMap<MXOlmSessionResult> results) {
mCrypto.getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "## shareUserDevicesKey() : ensureOlmSessionsForDevices succeeds after " + (System.currentTimeMillis() - t0) + " ms");
MXUsersDevicesMap<Object> contentMap = new MXUsersDevicesMap<>();
boolean haveTargets = false;
List<String> userIds = results.getUserIds();
for (String userId : userIds) {
List<MXDeviceInfo> devicesToShareWith = devicesByUser.get(userId);
for (MXDeviceInfo deviceInfo : devicesToShareWith) {
String deviceID = deviceInfo.deviceId;
MXOlmSessionResult sessionResult = results.getObject(deviceID, userId);
if ((null == sessionResult) || (null == sessionResult.mSessionId)) {
// so just skip it.
continue;
}
Log.d(LOG_TAG, "## shareUserDevicesKey() : Sharing keys with device " + userId + ":" + deviceID);
// noinspection ArraysAsListWithZeroOrOneArgument,ArraysAsListWithZeroOrOneArgument
contentMap.setObject(mCrypto.encryptMessage(payload, Arrays.asList(sessionResult.mDevice)), userId, deviceID);
haveTargets = true;
}
}
if (haveTargets && !mCrypto.hasBeenReleased()) {
final long t0 = System.currentTimeMillis();
Log.d(LOG_TAG, "## shareUserDevicesKey() : has target");
mCrypto.getCryptoRestClient().sendToDevice(CryptoEvent.EVENT_TYPE_MESSAGE_ENCRYPTED, contentMap, new ApiCallback<Void>() {
@Override
public void onSuccess(Void info) {
mCrypto.getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "## shareUserDevicesKey() : sendToDevice succeeds after " + (System.currentTimeMillis() - t0) + " ms");
// for dead devices on every message.
for (String userId : devicesByUser.keySet()) {
List<MXDeviceInfo> devicesToShareWith = devicesByUser.get(userId);
for (MXDeviceInfo deviceInfo : devicesToShareWith) {
session.mSharedWithDevices.setObject(chainIndex, userId, deviceInfo.deviceId);
}
}
mCrypto.getUIHandler().post(new Runnable() {
@Override
public void run() {
if (null != callback) {
callback.onSuccess(null);
}
}
});
}
});
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : sendToDevice onNetworkError " + e.getMessage(), e);
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : sendToDevice onMatrixError " + e.getMessage());
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : sendToDevice onUnexpectedError " + e.getMessage(), e);
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
} else {
Log.d(LOG_TAG, "## shareUserDevicesKey() : no need to sharekey");
if (null != callback) {
mCrypto.getUIHandler().post(new Runnable() {
@Override
public void run() {
callback.onSuccess(null);
}
});
}
}
}
});
}
@Override
public void onNetworkError(Exception e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : ensureOlmSessionsForDevices failed " + e.getMessage(), e);
if (null != callback) {
callback.onNetworkError(e);
}
}
@Override
public void onMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : ensureOlmSessionsForDevices failed " + e.getMessage());
if (null != callback) {
callback.onMatrixError(e);
}
}
@Override
public void onUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## shareUserDevicesKey() : ensureOlmSessionsForDevices failed " + e.getMessage(), e);
if (null != callback) {
callback.onUnexpectedError(e);
}
}
});
}
use of org.matrix.androidsdk.core.model.MatrixError in project matrix-android-sdk by matrix-org.
the class MXMegolmEncryption method encryptEventContent.
@Override
public void encryptEventContent(final JsonElement eventContent, final String eventType, final List<String> userIds, final ApiCallback<JsonElement> callback) {
// Queue the encryption request
// It will be processed when everything is set up
MXQueuedEncryption queuedEncryption = new MXQueuedEncryption();
queuedEncryption.mEventContent = eventContent;
queuedEncryption.mEventType = eventType;
queuedEncryption.mApiCallback = callback;
synchronized (mPendingEncryptions) {
mPendingEncryptions.add(queuedEncryption);
}
final long t0 = System.currentTimeMillis();
Log.d(LOG_TAG, "## encryptEventContent () starts");
getDevicesInRoom(userIds, new ApiCallback<MXUsersDevicesMap<MXDeviceInfo>>() {
/**
* A network error has been received while encrypting
* @param e the exception
*/
private void dispatchNetworkError(Exception e) {
Log.e(LOG_TAG, "## encryptEventContent() : onNetworkError " + e.getMessage(), e);
List<MXQueuedEncryption> queuedEncryptions = getPendingEncryptions();
for (MXQueuedEncryption queuedEncryption : queuedEncryptions) {
queuedEncryption.mApiCallback.onNetworkError(e);
}
synchronized (mPendingEncryptions) {
mPendingEncryptions.removeAll(queuedEncryptions);
}
}
/**
* A matrix error has been received while encrypting
* @param e the exception
*/
private void dispatchMatrixError(MatrixError e) {
Log.e(LOG_TAG, "## encryptEventContent() : onMatrixError " + e.getMessage());
List<MXQueuedEncryption> queuedEncryptions = getPendingEncryptions();
for (MXQueuedEncryption queuedEncryption : queuedEncryptions) {
queuedEncryption.mApiCallback.onMatrixError(e);
}
synchronized (mPendingEncryptions) {
mPendingEncryptions.removeAll(queuedEncryptions);
}
}
/**
* An unexpected error has been received while encrypting
* @param e the exception
*/
private void dispatchUnexpectedError(Exception e) {
Log.e(LOG_TAG, "## onUnexpectedError() : onMatrixError " + e.getMessage(), e);
List<MXQueuedEncryption> queuedEncryptions = getPendingEncryptions();
for (MXQueuedEncryption queuedEncryption : queuedEncryptions) {
queuedEncryption.mApiCallback.onUnexpectedError(e);
}
synchronized (mPendingEncryptions) {
mPendingEncryptions.removeAll(queuedEncryptions);
}
}
@Override
public void onSuccess(MXUsersDevicesMap<MXDeviceInfo> devicesInRoom) {
ensureOutboundSession(devicesInRoom, new ApiCallback<MXOutboundSessionInfo>() {
@Override
public void onSuccess(final MXOutboundSessionInfo session) {
mCrypto.getEncryptingThreadHandler().post(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "## encryptEventContent () processPendingEncryptions after " + (System.currentTimeMillis() - t0) + "ms");
processPendingEncryptions(session);
}
});
}
@Override
public void onNetworkError(Exception e) {
dispatchNetworkError(e);
}
@Override
public void onMatrixError(MatrixError e) {
dispatchMatrixError(e);
}
@Override
public void onUnexpectedError(Exception e) {
dispatchUnexpectedError(e);
}
});
}
@Override
public void onNetworkError(Exception e) {
dispatchNetworkError(e);
}
@Override
public void onMatrixError(MatrixError e) {
dispatchMatrixError(e);
}
@Override
public void onUnexpectedError(Exception e) {
dispatchUnexpectedError(e);
}
});
}
Aggregations