Get intent for backup settings from backup transport.
This changes BackupSettingsActivity to launch backup settings
from intent provided by BackupTransport#dataManagementIntent() API
instead of the config.xml.
Test: make RunSettingsRoboTests -j40
Change-Id: I0847999459a914e585a626761f3051f1d7a0b591
diff --git a/src/com/android/settings/BackupSettingsActivity.java b/src/com/android/settings/BackupSettingsActivity.java
index a4cc4b7..c0456b2 100644
--- a/src/com/android/settings/BackupSettingsActivity.java
+++ b/src/com/android/settings/BackupSettingsActivity.java
@@ -17,19 +17,13 @@
package com.android.settings;
import android.app.Activity;
-import android.app.backup.BackupManager;
-import android.app.backup.IBackupManager;
-import android.content.Context;
+import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.Log;
-import com.android.settings.R;
-
-import java.net.URISyntaxException;
+import com.android.settings.Settings.PrivacySettingsActivity;
/**
* A trampoline activity used to launch the configured Backup activity.
@@ -42,30 +36,24 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- String backup = getResources().getString(R.string.config_backup_settings_intent);
- if (!TextUtils.isEmpty(backup)) {
- try {
- Intent intent = Intent.parseUri(backup, 0);
- if (intent.resolveActivity(getPackageManager()) != null) {
- // use startActivityForResult to let the activity check the caller signature
- IBackupManager bmgr = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- boolean backupOkay;
- try {
- backupOkay = bmgr.isBackupServiceActive(UserHandle.myUserId());
- } catch (Exception e) {
- // things go wrong talking to the backup system => ignore and
- // pass the default 'false' as the "backup is a thing?" state.
- backupOkay = false;
- }
- intent.putExtra(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE, backupOkay);
- startActivityForResult(intent, -1);
- } else {
- Log.e(TAG, "Backup component not found!");
- }
- } catch (URISyntaxException e) {
- Log.e(TAG, "Invalid backup component URI!", e);
+
+ BackupSettingsHelper backupHelper = new BackupSettingsHelper();
+ if (backupHelper.isIntentProvidedByTransport(getPackageManager())) {
+ Intent intent = backupHelper.getIntentForBackupSettings();
+ if (intent != null) {
+ // use startActivityForResult to let the activity check the caller signature
+ startActivityForResult(intent, -1);
}
+ } else {
+ // This should never happen, because isIntentProvidedByTransport() is called before
+ // starting this activity.
+ Log.e(TAG, "Backup transport has not provided an intent"
+ + " or the component for the intent is not found!");
+ getPackageManager().setComponentEnabledSetting(
+ new ComponentName(getPackageName(), PrivacySettingsActivity.class.getName()),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ startActivityForResult(new Intent(this, PrivacySettingsActivity.class), -1);
}
finish();
}
diff --git a/src/com/android/settings/BackupSettingsHelper.java b/src/com/android/settings/BackupSettingsHelper.java
new file mode 100644
index 0000000..37c0971
--- /dev/null
+++ b/src/com/android/settings/BackupSettingsHelper.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 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
+ */
+
+package com.android.settings;
+
+
+import android.app.backup.BackupManager;
+import android.app.backup.BackupTransport;
+import android.app.backup.IBackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Helper class for {@link BackupSettingsActivity} that interacts with {@link IBackupManager}.
+ */
+public class BackupSettingsHelper {
+ private static final String TAG = "BackupSettingsHelper";
+
+ private IBackupManager mBackupManager = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+
+
+ /**
+ * Gets the intent from Backup transport and adds the extra depending on whether the user has
+ * rights to see backup settings.
+ *
+ * @return Intent to launch Backup settings provided by the Backup transport.
+ */
+ public Intent getIntentForBackupSettings() {
+ Intent intent = getIntentFromBackupTransport();
+ if (intent != null) {
+ intent.putExtra(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE, isBackupServiceActive());
+ }
+ return intent;
+ }
+
+
+ /**
+ * Checks if the transport provided the intent to launch the backup settings and if that
+ * intent resolves to an activity.
+ */
+ public boolean isIntentProvidedByTransport(PackageManager packageManager) {
+ Intent intent = getIntentFromBackupTransport();
+ return intent != null && intent.resolveActivity(packageManager) != null;
+ }
+
+ /**
+ * Gets an intent to launch the backup settings from the current transport using
+ * {@link BackupTransport#dataManagementIntent()} API.
+ *
+ * @return intent provided by transport or null if no intent was provided.
+ */
+ private Intent getIntentFromBackupTransport() {
+ try {
+ Intent intent =
+ mBackupManager.getDataManagementIntent(mBackupManager.getCurrentTransport());
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (intent != null) {
+ Log.d(TAG, "Parsed intent from backup transport: " + intent.toString());
+ } else {
+ Log.d(TAG, "Received a null intent from backup transport");
+ }
+ }
+ return intent;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting data management intent", e);
+ }
+ return null;
+ }
+
+ /** Checks if backup service is enabled for this user. */
+ private boolean isBackupServiceActive() {
+ boolean backupOkay;
+ try {
+ backupOkay = mBackupManager.isBackupServiceActive(UserHandle.myUserId());
+ } catch (Exception e) {
+ // things go wrong talking to the backup system => ignore and
+ // pass the default 'false' as the "backup is a thing?" state.
+ backupOkay = false;
+ }
+ return backupOkay;
+ }
+}
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 13bc048..7fe1167 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -33,6 +33,8 @@
import android.content.res.Configuration;
import android.nfc.NfcAdapter;
import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Build.VERSION;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -969,29 +971,27 @@
}
}
- String backupIntent = getResources().getString(R.string.config_backup_settings_intent);
- boolean useDefaultBackup = TextUtils.isEmpty(backupIntent);
+ // Check if the backup transport has provided an intent to launch the backup settings.
+ BackupSettingsHelper backupHelper = new BackupSettingsHelper();
+ boolean useDefaultBackup = !backupHelper.isIntentProvidedByTransport(getPackageManager());
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "Enabling default backup settings page: " + useDefaultBackup);
+ }
+
setTileEnabled(new ComponentName(packageName,
Settings.PrivacySettingsActivity.class.getName()), useDefaultBackup, isAdmin);
setTileEnabled(new ComponentName(packageName,
"com.android.settings.PrivacyDashboardAlias"),
useDefaultBackup, isAdmin);
- boolean hasBackupActivity = false;
- if (!useDefaultBackup) {
- try {
- Intent intent = Intent.parseUri(backupIntent, 0);
- hasBackupActivity = !getPackageManager().queryIntentActivities(intent, 0).isEmpty();
- } catch (URISyntaxException e) {
- Log.e(LOG_TAG, "Invalid backup intent URI!", e);
- }
- }
-
// Enable/disable BackupSettingsActivity and its alias.
+ if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ Log.v(LOG_TAG, "Enabling transport provided backup settings: " + !useDefaultBackup);
+ }
setTileEnabled(new ComponentName(packageName,
- BackupSettingsActivity.class.getName()), hasBackupActivity, isAdmin);
+ BackupSettingsActivity.class.getName()), !useDefaultBackup, isAdmin);
setTileEnabled(new ComponentName(packageName,
- "com.android.settings.BackupResetDashboardAlias"), hasBackupActivity, isAdmin);
+ "com.android.settings.BackupResetDashboardAlias"), !useDefaultBackup, isAdmin);
setTileEnabled(new ComponentName(packageName,
Settings.EnterprisePrivacySettingsActivity.class.getName()),
diff --git a/tests/robotests/src/com/android/settings/BackupSettingsHelperTest.java b/tests/robotests/src/com/android/settings/BackupSettingsHelperTest.java
new file mode 100644
index 0000000..b14debc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/BackupSettingsHelperTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2017 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
+ */
+
+package com.android.settings;
+
+import android.app.backup.BackupManager;
+import android.app.backup.IBackupManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = {BackupSettingsHelperTest.ShadowBackupManagerStub.class})
+public class BackupSettingsHelperTest {
+
+ private BackupSettingsHelper mBackupSettingsHelper;
+
+ @Mock
+ private static IBackupManager mBackupManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(mBackupManager.getCurrentTransport()).thenReturn("test_transport");
+ mBackupSettingsHelper = new BackupSettingsHelper();
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport() throws Exception {
+ Intent intent = new Intent();
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ verify(mBackupManager).getDataManagementIntent(anyString());
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_WithIntent() throws Exception {
+ Intent intent = mock(Intent.class);
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent).isEqualTo(intent);
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_WithNullIntent() throws Exception {
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(null);
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent).isNull();
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_RemoteException() throws Exception {
+ when(mBackupManager.getDataManagementIntent(anyString())).thenThrow(new RemoteException());
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent).isNull();
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_BackupEnabled() throws Exception {
+ Intent intent = new Intent("test_intent");
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+ when(mBackupManager.isBackupServiceActive(anyInt())).thenReturn(true);
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent.getExtras().get(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE))
+ .isEqualTo(true);
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_BackupDisabled() throws Exception {
+ Intent intent = new Intent("test_intent");
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+ when(mBackupManager.isBackupServiceActive(anyInt())).thenReturn(false);
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent.getExtras().get(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE))
+ .isEqualTo(false);
+ }
+
+ @Test
+ public void testGetIntentFromBackupTransport_BackupStatusException() throws Exception {
+ Intent intent = new Intent("test_intent");
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+ when(mBackupManager.isBackupServiceActive(anyInt())).thenThrow(new RemoteException());
+
+ Intent backupIntent = mBackupSettingsHelper.getIntentForBackupSettings();
+
+ assertThat(backupIntent.getExtras().get(BackupManager.EXTRA_BACKUP_SERVICES_AVAILABLE))
+ .isEqualTo(false);
+ }
+
+ @Test
+ public void testIsIntentProvidedByTransport_WithNullIntent() throws Exception {
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(null);
+
+ PackageManager packageManager = mock(PackageManager.class);
+
+ boolean isIntentProvided = mBackupSettingsHelper.isIntentProvidedByTransport(packageManager);
+
+ assertThat(isIntentProvided).isFalse();
+ }
+
+ @Test
+ public void testIsIntentProvidedByTransport_WithInvalidIntent() throws Exception {
+ Intent intent = mock(Intent.class);
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+
+ PackageManager packageManager = mock(PackageManager.class);
+ when(intent.resolveActivity(packageManager)).thenReturn(null);
+
+ boolean isIntentProvided = mBackupSettingsHelper.isIntentProvidedByTransport(packageManager);
+
+ assertThat(isIntentProvided).isFalse();
+ }
+
+ @Test
+ public void testIsIntentProvidedByTransport_WithIntent() throws Exception {
+ Intent intent = mock(Intent.class);
+
+ when(mBackupManager.getDataManagementIntent(anyString())).thenReturn(intent);
+
+ PackageManager packageManager = mock(PackageManager.class);
+ when(intent.resolveActivity(packageManager)).thenReturn(mock(ComponentName.class));
+
+ boolean isIntentProvided = mBackupSettingsHelper.isIntentProvidedByTransport(packageManager);
+
+ assertThat(isIntentProvided).isTrue();
+ }
+
+ @Implements(IBackupManager.Stub.class)
+ public static class ShadowBackupManagerStub {
+ @Implementation
+ public static IBackupManager asInterface(IBinder iBinder) {
+ return mBackupManager;
+ }
+ }
+}