From 9083e002d4e14473187b433b0aae6ad109cc9e82 Mon Sep 17 00:00:00 2001
From: Alex Karezin <alexkarezin@gmail.com>
Date: Tue, 26 Sep 2023 03:01:48 -0400
Subject: [PATCH 1/3] docs: remove dead link and add link to repository map in
 README.md (#1712)

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 49dde2a165..be3497cba7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 [![Coverage Status](https://coveralls.io/repos/github/Microsoft/AppCenter-SDK-Android/badge.svg?branch=develop)](https://coveralls.io/github/Microsoft/AppCenter-SDK-Android?branch=develop)
 [![GitHub Release](https://img.shields.io/github/release/microsoft/appcenter-sdk-android.svg)](https://github.com/microsoft/appcenter-sdk-android/releases/latest)
-[![Bintray](https://api.bintray.com/packages/vsappcenter/appcenter/appcenter/images/download.svg)](https://bintray.com/vsappcenter/appcenter)
 [![license](https://img.shields.io/badge/license-MIT%20License-00AAAA.svg)](https://github.com/microsoft/appcenter-sdk-android/blob/master/license.txt)
+[![Project Map](https://img.shields.io/badge/SourceSpy-Project_Map-blue.svg)](https://sourcespy.com/github/microsoftappcentersdkandroid/)
 
 # Visual Studio App Center SDK for Android
 

From e662738cacf6e73ab1840772e1e6ecbd9ed4619d Mon Sep 17 00:00:00 2001
From: MikhailSuendukov <110986399+MikhailSuendukov@users.noreply.github.com>
Date: Thu, 30 Nov 2023 12:47:12 +0100
Subject: [PATCH 2/3] Adopt target SDK 34 (#1713)

Co-authored-by: JiglioNero <smouk.chayz@gmail.com>
Co-authored-by: Dima <v-dmkira@microsoft.com>
---
 CHANGELOG.md                                  |  5 +++
 .../activities/SettingsActivity.java          |  3 +-
 .../session/InstallStatusReceiver.java        | 16 +++++++-
 .../session/SessionReleaseInstaller.java      |  7 +++-
 .../session/InstallStatusReceiverTest.java    |  9 +++++
 .../session/SessionReleaseInstallerTest.java  | 38 +++++++++++++++++--
 6 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cdcb4b655b..d23e635751 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 
 ## Version 5.0.3 (In development)
 
+### App Center Distribute
+
+* **[Fix]** Add RECEIVER_EXPORTED flag for install receiver.
+* **[Fix]** Add FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT flag for broadcast pending intent.
+
 ## Version 5.0.2
 
 ### AppCenter
diff --git a/apps/sasquatch/src/main/java/com/microsoft/appcenter/sasquatch/activities/SettingsActivity.java b/apps/sasquatch/src/main/java/com/microsoft/appcenter/sasquatch/activities/SettingsActivity.java
index 6c2f1dfae9..7d5cfe6d9f 100644
--- a/apps/sasquatch/src/main/java/com/microsoft/appcenter/sasquatch/activities/SettingsActivity.java
+++ b/apps/sasquatch/src/main/java/com/microsoft/appcenter/sasquatch/activities/SettingsActivity.java
@@ -13,6 +13,7 @@
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.FileObserver;
 import android.preference.CheckBoxPreference;
@@ -738,7 +739,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
             if (requestCode == FILE_ATTACHMENT_DIALOG_ID) {
                 Uri fileAttachment = resultCode == RESULT_OK && data != null ? data.getData() : null;
                 if (fileAttachment != null) {
-                    getActivity().getContentResolver().takePersistableUriPermission(fileAttachment, data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    getActivity().getContentResolver().takePersistableUriPermission(fileAttachment, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 }
                 MainActivity.setFileAttachment(fileAttachment);
                 Preference preference = getPreferenceManager().findPreference(getString(R.string.appcenter_crashes_file_attachment_key));
diff --git a/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiver.java b/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiver.java
index a91aad3ab9..84db739f17 100644
--- a/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiver.java
+++ b/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiver.java
@@ -7,6 +7,7 @@
 
 import static com.microsoft.appcenter.distribute.DistributeConstants.LOG_TAG;
 
+import android.annotation.SuppressLint;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -32,6 +33,15 @@ class InstallStatusReceiver extends BroadcastReceiver {
     @VisibleForTesting
     static final String INSTALL_STATUS_ACTION = "com.microsoft.appcenter.action.INSTALL_STATUS";
 
+    /**
+     * Raw value of PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT.
+     * https://developer.android.com/reference/android/app/PendingIntent#FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
+     * This flag will appear only in Android target SDK 34.
+     */
+    @VisibleForTesting
+    private static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT_VALUE = 16777216;
+
+
     static IntentFilter getInstallerReceiverFilter() {
         IntentFilter installerReceiverFilter = new IntentFilter();
         installerReceiverFilter.addAction(INSTALL_STATUS_ACTION);
@@ -49,8 +59,12 @@ static IntentSender getInstallStatusIntentSender(Context context, int requestCod
         int broadcastFlags = 0;
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
             broadcastFlags = PendingIntent.FLAG_MUTABLE;
+            if (Build.VERSION.SDK_INT >= 34) {
+                broadcastFlags |= FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT_VALUE;
+            }
         }
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(
+        // Suppress the warning as the flag PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT is unavailable on Android SDK < 34.
+        @SuppressLint("WrongConstant") PendingIntent pendingIntent = PendingIntent.getBroadcast(
                 context,
                 requestCode,
                 new Intent(INSTALL_STATUS_ACTION),
diff --git a/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstaller.java b/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstaller.java
index c855c63b7a..1e40d2b4de 100644
--- a/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstaller.java
+++ b/sdk/appcenter-distribute/src/main/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstaller.java
@@ -14,6 +14,7 @@
 import android.content.IntentSender;
 import android.content.pm.PackageInstaller;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 
@@ -233,7 +234,11 @@ private synchronized void registerListeners() {
         if (mInstallStatusReceiver == null) {
             AppCenterLog.debug(LOG_TAG, "Register receiver for installing a new release.");
             mInstallStatusReceiver = new InstallStatusReceiver(this);
-            mContext.registerReceiver(mInstallStatusReceiver, InstallStatusReceiver.getInstallerReceiverFilter());
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+                mContext.registerReceiver(mInstallStatusReceiver, InstallStatusReceiver.getInstallerReceiverFilter(), Context.RECEIVER_EXPORTED);
+            } else {
+                mContext.registerReceiver(mInstallStatusReceiver, InstallStatusReceiver.getInstallerReceiverFilter());
+            }
         }
         if (mSessionCallback == null) {
             PackageInstaller packageInstaller = getPackageInstaller();
diff --git a/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiverTest.java b/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiverTest.java
index cf461e8cae..c7ead5c866 100644
--- a/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiverTest.java
+++ b/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/InstallStatusReceiverTest.java
@@ -53,6 +53,7 @@
 public class InstallStatusReceiverTest {
 
     private static final int SESSION_ID = 42;
+    private static final int FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT_VALUE = 16777216;
 
     @Rule
     public PowerMockRule mRule = new PowerMockRule();
@@ -216,6 +217,14 @@ public void installerReceiverFilter() throws Exception {
         verify(filter).addAction(INSTALL_STATUS_ACTION);
     }
 
+    @Test
+    public void createIntentSenderOnAndroid34() {
+
+        /* Mock SDK_INT to 34 target SDK. */
+        Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", 34);
+        createIntentSender(PendingIntent.FLAG_MUTABLE | FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT_VALUE);
+    }
+
     @Test
     public void createIntentSenderOnAndroidS() {
 
diff --git a/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstallerTest.java b/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstallerTest.java
index 4a98e311b6..ec9fd594a7 100644
--- a/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstallerTest.java
+++ b/sdk/appcenter-distribute/src/test/java/com/microsoft/appcenter/distribute/install/session/SessionReleaseInstallerTest.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 
@@ -41,12 +42,14 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
 import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
 
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -58,7 +61,7 @@
         InstallStatusReceiver.class,
         PackageInstallerListener.class,
         ReleaseInstallerActivity.class,
-        SessionReleaseInstaller.class
+        SessionReleaseInstaller.class,
 })
 public class SessionReleaseInstallerTest {
 
@@ -153,7 +156,9 @@ public Boolean answer(InvocationOnMock invocation) {
     }
 
     @Test
-    public void installSuccess() throws IOException {
+    public void installSuccessForSV2() throws IOException {
+        Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S_V2);
+
         Uri uri = mock(Uri.class);
         mInstaller.install(uri);
 
@@ -177,6 +182,33 @@ public void installSuccess() throws IOException {
         verify(mPackageInstaller).abandonSession(eq(SESSION_ID));
     }
 
+    @Test
+    public void installSuccessForTiramisu() throws IOException {
+        Whitebox.setInternalState(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
+
+        Uri uri = mock(Uri.class);
+        mInstaller.install(uri);
+
+        /* Verify that all required things called. */
+        verify(mHandler).post(any(Runnable.class));
+        verify(mContext).registerReceiver(eq(mInstallStatusReceiver), any(), anyInt());
+        verify(mPackageInstaller).registerSessionCallback(eq(mPackageInstallerListener));
+        verify(mInputStream).close();
+        verify(mOutputStream).close();
+        verify(mSession).commit(any(IntentSender.class));
+        verify(mSession, never()).abandon();
+        verify(mSession).close();
+        verifyNoInteractions(mListener);
+
+        /* Try to star install second time. It's valid case if something goes wrong with previous try. */
+        mInstaller.install(uri);
+
+        /* Cancel previous session and re-use callbacks. */
+        verify(mContext).registerReceiver(eq(mInstallStatusReceiver), any(), anyInt());
+        verify(mPackageInstaller).registerSessionCallback(eq(mPackageInstallerListener));
+        verify(mPackageInstaller).abandonSession(eq(SESSION_ID));
+    }
+
     @Test
     public void throwIOExceptionWhenTryToOpenWriteSession() throws IOException {
 
@@ -246,7 +278,7 @@ public void clear() {
         mInstaller.install(uri);
 
         /* Registering callbacks. */
-        verify(mContext).registerReceiver(eq(mInstallStatusReceiver), any());
+        verify(mContext).registerReceiver(eq(mInstallStatusReceiver), any(), anyInt());
         verify(mPackageInstaller).registerSessionCallback(eq(mPackageInstallerListener));
 
         /* Clear after start should clear registered callbacks and abandon the session. */

From 94e17ea745b7363f820cb39127b5dc9e965ec37e Mon Sep 17 00:00:00 2001
From: MikhailSuendukov <110986399+MikhailSuendukov@users.noreply.github.com>
Date: Wed, 6 Dec 2023 17:20:24 +0100
Subject: [PATCH 3/3] Bump versions (#1717)

---
 CHANGELOG.md    | 9 ++++++++-
 versions.gradle | 4 ++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d23e635751..5acad340c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,12 +1,19 @@
 # App Center SDK for Android Change Log
 
-## Version 5.0.3 (In development)
+## Version 5.0.4
 
 ### App Center Distribute
 
 * **[Fix]** Add RECEIVER_EXPORTED flag for install receiver.
 * **[Fix]** Add FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT flag for broadcast pending intent.
 
+## Version 5.0.3
+
+### AppCenter
+
+* **[Internal]** Add `dataResidencyRegion` option.
+
+
 ## Version 5.0.2
 
 ### AppCenter
diff --git a/versions.gradle b/versions.gradle
index f8f00f8976..006914d962 100644
--- a/versions.gradle
+++ b/versions.gradle
@@ -6,8 +6,8 @@
 // Version constants
 
 ext {
-    versionCode = 72
-    versionName = '5.0.3'
+    versionCode = 73
+    versionName = '5.0.4'
     minSdkVersion = 21
     compileSdkVersion = 33
     targetSdkVersion = 33