Skip to content

Commit

Permalink
Merge pull request #1718 from microsoft/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
MikhailSuendukov authored Dec 6, 2023
2 parents d406e11 + 94e17ea commit 9075240
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 10 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
# 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

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -58,7 +61,7 @@
InstallStatusReceiver.class,
PackageInstallerListener.class,
ReleaseInstallerActivity.class,
SessionReleaseInstaller.class
SessionReleaseInstaller.class,
})
public class SessionReleaseInstallerTest {

Expand Down Expand Up @@ -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);

Expand All @@ -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 {

Expand Down Expand Up @@ -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. */
Expand Down
4 changes: 2 additions & 2 deletions versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 9075240

Please sign in to comment.