Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 5.0.3 #1708

Merged
merged 3 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# App Center SDK for Android Change Log

## Version 5.0.2 (In development)
## Version 5.0.3 (In development)

## Version 5.0.2

### AppCenter

Expand Down
6 changes: 3 additions & 3 deletions apps/sasquatch/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
flavorDimensions "dependency", "distribute"

defaultConfig {
versionCode 300
versionName "5.0.1"
versionCode 302
versionName "5.0.3"
externalNativeBuild {
ndkBuild {
arguments "NDK_APPLICATION_MK=Application.mk", "V=1"
Expand Down Expand Up @@ -100,7 +100,7 @@ dependencies {
projectDependencyImplementation project(':sdk:appcenter-analytics')
projectDependencyImplementation project(':sdk:appcenter-crashes')

def appCenterSdkVersion = "5.0.1"
def appCenterSdkVersion = "5.0.2"
mavenCentralDependencyImplementation "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}"
mavenCentralDependencyImplementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ static void startAppCenter(Application application, String startTypeString) {
AppCenter.setCountryCode(countryCode);
}

// TODO: uncomment this code after release sdk to maven
// /* Set data residency region. */
// String dataResidencyRegion = MainActivity.sSharedPreferences.getString(application.getString(R.string.data_residency_region_key), null);
// if (dataResidencyRegion != null) {
// AppCenter.setDataResidencyRegion(dataResidencyRegion);
// }

/* Set the track explicitly only if we set it in settings, to test the initial public by default at first launch. */
int savedTrack = sSharedPreferences.getInt(application.getString(R.string.appcenter_distribute_track_state_key), 0);
if (savedTrack != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,34 @@ public void onClick(DialogInterface dialog, int which) {
return true;
}
});
initClickableSetting(R.string.data_residency_region_key, MainActivity.sSharedPreferences.getString(getActivity().getString(R.string.data_residency_region_key), null), new Preference.OnPreferenceClickListener() {

@Override
public boolean onPreferenceClick(final Preference preference) {
final EditText input = new EditText(getActivity());
input.setInputType(InputType.TYPE_CLASS_TEXT);
input.setHint(R.string.data_residency_region_title);
input.setText(MainActivity.sSharedPreferences.getString(getActivity().getString(R.string.data_residency_region_key), null));
input.setSelection(input.getText().length());
new AlertDialog.Builder(getActivity()).setTitle(R.string.data_residency_region_title).setView(input)
.setPositiveButton(R.string.save, new DialogInterface.OnClickListener() {

@SuppressLint("CommitPrefEdits")
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.sSharedPreferences
.edit()
.putString(getActivity().getString(R.string.data_residency_region_key), input.getText().toString())
.apply();
preference.setSummary(input.getText());
Toast.makeText(getActivity(), getActivity().getString(R.string.data_residency_region_save_message), Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton(R.string.cancel, null)
.create().show();
return true;
}
});
initClickableSetting(R.string.storage_size_key, Formatter.formatFileSize(getActivity(), MainActivity.sSharedPreferences.getLong(MAX_STORAGE_SIZE_KEY, DEFAULT_MAX_STORAGE_SIZE)), new Preference.OnPreferenceClickListener() {

@Override
Expand Down
4 changes: 4 additions & 0 deletions apps/sasquatch/src/main/res/values/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
<string name="country_code_title" tools:ignore="MissingTranslation">Country Code</string>
<string name="country_code_save_message" tools:ignore="MissingTranslation">Country code value will be applied after the application restart.</string>

<string name="data_residency_region_key" tools:ignore="MissingTranslation">data_residency_region</string>
<string name="data_residency_region_title" tools:ignore="MissingTranslation">Data residency region</string>
<string name="data_residency_region_save_message" tools:ignore="MissingTranslation">Data residency region value will be applied after the application restart.</string>

<string name="storage_file_size_key" tools:ignore="MissingTranslation">storage_file_size_key</string>
<string name="storage_file_size_title" tools:ignore="MissingTranslation">Storage File Size</string>

Expand Down
5 changes: 5 additions & 0 deletions apps/sasquatch/src/main/res/xml/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
<Preference
android:key="@string/country_code_key"
android:title="@string/country_code_title" />
<EditTextPreference
android:key="@string/data_residency_region_key"
android:selectAllOnFocus="false"
android:singleLine="false"
android:title="@string/data_residency_region_title" />
<Preference
android:key="@string/storage_size_key"
android:title="@string/storage_size_title" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

package com.microsoft.appcenter.crashes.utils;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import androidx.test.platform.app.InstrumentationRegistry;

import com.microsoft.appcenter.Constants;
Expand All @@ -19,12 +25,6 @@
import java.io.File;
import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

@SuppressWarnings("unused")
public class ErrorLogHelperAndroidTest {

Expand Down Expand Up @@ -170,4 +170,19 @@ public void parseDevice() {
assertNotNull(device4);
assertNull(userId4);
}

@Test
public void parseDataResidencyRegion() {
String mockDataResidencyRegion = "mockRegion";
String mockContextInformation = "{\"dataResidencyRegion\":\"" + mockDataResidencyRegion + "\"}";
String result = ErrorLogHelper.parseDataResidencyRegion(mockContextInformation);
assertEquals(mockDataResidencyRegion, result);
}

@Test()
public void parseDataResidencyRegionIncorrectJson() {
String invalidJson = "invalidJson";
String result = ErrorLogHelper.parseDataResidencyRegion(invalidJson);
assertNull(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import androidx.annotation.WorkerThread;

import com.microsoft.appcenter.AbstractAppCenterService;
import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.Constants;
import com.microsoft.appcenter.Flags;
import com.microsoft.appcenter.channel.Channel;
Expand Down Expand Up @@ -639,6 +640,8 @@ private synchronized UUID queueException(@NonNull final ExceptionModelBuilder ex
final String userId = UserIdContext.getInstance().getUserId();
final UUID errorId = UUID.randomUUID();
final Map<String, String> validatedProperties = ErrorLogHelper.validateProperties(properties, "HandledError");
final String dataResidencyRegion = AppCenter.getDataResidencyRegion();

post(new Runnable() {

@Override
Expand All @@ -648,11 +651,17 @@ public void run() {
HandledErrorLog errorLog = new HandledErrorLog();
errorLog.setId(errorId);
errorLog.setUserId(userId);
errorLog.setDataResidencyRegion(dataResidencyRegion);
errorLog.setException(exceptionModelBuilder.buildExceptionModel());
errorLog.setProperties(validatedProperties);
mChannel.enqueue(errorLog, ERROR_GROUP, Flags.DEFAULTS);

/* Then attachments if any. */
if (attachments != null) {
for (ErrorAttachmentLog attachment : attachments) {
attachment.setDataResidencyRegion(dataResidencyRegion);
}
}
sendErrorAttachment(errorId, attachments);
}
});
Expand Down Expand Up @@ -780,6 +789,7 @@ private void processSingleMinidump(File minidumpFile, File minidumpFolder) {
errorLog.setProcessName("");
try {
String savedUserId = ErrorLogHelper.getStoredUserInfo(minidumpFolder);
String dataResidencyRegion = ErrorLogHelper.getStoredDataResidencyRegion(minidumpFolder);
Device savedDeviceInfo = ErrorLogHelper.getStoredDeviceInfo(minidumpFolder);
if (savedDeviceInfo == null) {

Expand All @@ -792,6 +802,7 @@ private void processSingleMinidump(File minidumpFile, File minidumpFolder) {
}
errorLog.setDevice(savedDeviceInfo);
errorLog.setUserId(savedUserId);
errorLog.setDataResidencyRegion(dataResidencyRegion);
saveErrorLogFiles(new NativeException(), errorLog);
if (!minidumpFile.renameTo(dest)) {
throw new IOException("Failed to move file");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.Constants;
import com.microsoft.appcenter.crashes.Crashes;
import com.microsoft.appcenter.crashes.ingestion.models.Exception;
Expand Down Expand Up @@ -144,6 +145,11 @@ public class ErrorLogHelper {
@VisibleForTesting
static String DEVICE_INFO_KEY = "DEVICE_INFO";

/**
* Key for data residency region.
*/
private static final String DATA_RESIDENCY_REGION_KEY = "dataResidencyRegion";

/**
* Key for saving userId to JSON.
*/
Expand All @@ -168,6 +174,9 @@ public static ManagedErrorLog createErrorLog(@NonNull Context context, @NonNull
/* Set user identifier. */
errorLog.setUserId(UserIdContext.getInstance().getUserId());

/* Set data residency region. */
errorLog.setDataResidencyRegion(AppCenter.getDataResidencyRegion());

/* Snapshot device properties. */
try {
errorLog.setDevice(DeviceInfoHelper.getDeviceInfo(context));
Expand Down Expand Up @@ -287,6 +296,7 @@ public static synchronized File getNewMinidumpSubfolderWithContextData(Context c
try {
Device deviceInfo = DeviceInfoHelper.getDeviceInfo(context);
String userIdContext = UserIdContext.getInstance().getUserId();
String dataResidencyRegion = AppCenter.getDataResidencyRegion();
deviceInfo.setWrapperSdkName(WRAPPER_SDK_NAME_NDK);

/* To JSON. */
Expand All @@ -296,6 +306,7 @@ public static synchronized File getNewMinidumpSubfolderWithContextData(Context c
writer.endObject();
String deviceInfoString = writer.toString();
JSONObject jsonObject = new JSONObject();
jsonObject.put(DATA_RESIDENCY_REGION_KEY, dataResidencyRegion);
jsonObject.put(DEVICE_INFO_KEY, deviceInfoString);
jsonObject.put(USER_ID_KEY, userIdContext);

Expand Down Expand Up @@ -371,6 +382,21 @@ public static String getStoredUserInfo(File logFolder) {
return parseUserId(userInformationString);
}

/**
* Get data residency region.
*
* @param logFolder folder where to look for stored data residency region.
* @return a data residency region or null.
*/
@Nullable
public static String getStoredDataResidencyRegion(File logFolder) {
String context = getContextInformation(logFolder);
if (context == null) {
return null;
}
return parseDataResidencyRegion(context);
}

/**
* Get data about userId and deviceInfo in JSON format.
* @param logFolder - path to folder where placed file with data about userId and deviceId.
Expand Down Expand Up @@ -439,6 +465,24 @@ static Device parseDevice(String contextInformation) {
return null;
}

/**
* Look for 'dataResidencyRegion' data in file inside the minidump folder and parse it.
* @param contextInformation - data with information about userId.
* @return dataResidencyRegion or null.
*/
@VisibleForTesting
static String parseDataResidencyRegion(String contextInformation) {
try {
JSONObject jsonObject = new JSONObject(contextInformation);
if (jsonObject.has(DATA_RESIDENCY_REGION_KEY)) {
return jsonObject.getString(DATA_RESIDENCY_REGION_KEY);
}
} catch (JSONException e) {
AppCenterLog.error(Crashes.LOG_TAG, "Failed to deserialize data residency region.", e);
}
return null;
}

/**
* Remove the minidump sub-folders from previous sessions in the 'minidump/new' folder.
* Minidumps from these folders should already be moved to the 'minidump/pending' folder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -428,26 +428,30 @@ public void getStoredDeviceInfo() throws IOException {
}

@Test
public void getStoredDeviceInfoAndUserIdNull() {
public void getStoredMinidumpFileContentNull() {
File minidumpFolder = mock(File.class);
when(minidumpFolder.listFiles(any(FilenameFilter.class))).thenReturn(null);
Device storedDeviceInfo = ErrorLogHelper.getStoredDeviceInfo(minidumpFolder);
String storedUserId = ErrorLogHelper.getStoredUserInfo(minidumpFolder);
String dataResidencyRegion = ErrorLogHelper.getStoredDataResidencyRegion(minidumpFolder);
assertNull(storedDeviceInfo);
assertNull(storedUserId);
assertNull(dataResidencyRegion);
}

@Test
public void getStoredDeviceInfoAndUserIdEmpty() throws IOException {
public void getStoredMinidumpFileContentEmpty() throws IOException {
File minidumpFolder = mTemporaryFolder.newFolder("minidump");
Device storedDeviceInfo = ErrorLogHelper.getStoredDeviceInfo(minidumpFolder);
String storedUserId = ErrorLogHelper.getStoredUserInfo(minidumpFolder);
String dataResidencyRegion = ErrorLogHelper.getStoredDataResidencyRegion(minidumpFolder);
assertNull(storedDeviceInfo);
assertNull(storedUserId);
assertNull(dataResidencyRegion);
}

@Test
public void getStoredDeviceInfoAndUserInfoCannotRead() throws IOException {
public void getStoredMinidumpFileContentCannotRead() throws IOException {
File minidumpFolder = mTemporaryFolder.newFolder("minidump");
File deviceInfoFile = new File(minidumpFolder, ErrorLogHelper.DEVICE_INFO_FILE);
assertTrue(deviceInfoFile.createNewFile());
Expand All @@ -457,6 +461,8 @@ public void getStoredDeviceInfoAndUserInfoCannotRead() throws IOException {
assertNull(storedDeviceInfo);
String userInfo = ErrorLogHelper.getStoredUserInfo(minidumpFolder);
assertNull(userInfo);
String dataResidencyRegion = ErrorLogHelper.getStoredDataResidencyRegion(minidumpFolder);
assertNull(dataResidencyRegion);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import android.os.HandlerThread;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.annotation.WorkerThread;
import android.util.Log;
Expand Down Expand Up @@ -236,6 +237,11 @@ public class AppCenter {
*/
private Boolean mAllowedNetworkRequests;

/**
* Country code or any other string to identify residency region..
*/
private @Nullable String mDataResidencyRegion;

/**
* Get unique instance.
*
Expand Down Expand Up @@ -308,6 +314,25 @@ public static void setCountryCode(String countryCode) {
DeviceInfoHelper.setCountryCode(countryCode);
}

/**
* Set the country code or any other string to identify residency region.
*
* @param dataResidencyRegion residency region code.
*/
public static void setDataResidencyRegion(@Nullable String dataResidencyRegion) {
getInstance().mDataResidencyRegion = dataResidencyRegion;
}

/**
* Set the country code or any other string to identify residency region.
*
* @return dataResidencyRegion residency region code if defined.
*/
@Nullable
public static String getDataResidencyRegion() {
return getInstance().mDataResidencyRegion;
}

/**
* Get the current version of App Center SDK.
*
Expand Down
Loading