Added transparency-metadata display.
This feature enables 'App Details' to support MBAs with metadata file and display in an offline UI. This change includes a new fragment and user view that sources data from within any MBAs apk file that contains application-metadata.xml. Test: make -j64 RunSettingsRoboTests , AVD manual test Change-Id: If7822100a90f5fb8d33ce5d85958391fc33ecbee Bug: 244215932
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.applications.appinfo;
|
||||
|
||||
import static com.android.settings.applications.mobilebundledapps.MobileBundledAppDetailsActivity.ACTION_TRANSPARENCY_METADATA;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -41,11 +43,14 @@ import android.os.UserManager;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.applications.mobilebundledapps.ApplicationMetadataUtils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -53,7 +58,8 @@ import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class AppInstallerInfoPreferenceControllerTest {
|
||||
|
||||
private static final String TEST_PACKAGE_NAME = "Package1";
|
||||
private static final String TEST_CONTEXT_KEY = "test_key";
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
@@ -67,11 +73,17 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
@Mock
|
||||
private Preference mPreference;
|
||||
|
||||
@Mock
|
||||
private ApplicationMetadataUtils mApplicationMetadataUtils;
|
||||
|
||||
@Captor
|
||||
ArgumentCaptor<Intent> mIntentArgumentCaptor;
|
||||
|
||||
private Context mContext;
|
||||
private AppInstallerInfoPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() throws PackageManager.NameNotFoundException {
|
||||
public void setup() throws PackageManager.NameNotFoundException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
@@ -81,9 +93,13 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
when(mInstallSourceInfo.getInstallingPackageName()).thenReturn(installerPackage);
|
||||
when(mPackageManager.getApplicationInfo(eq(installerPackage), anyInt()))
|
||||
.thenReturn(mAppInfo);
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, "test_key");
|
||||
mController.setPackageName("Package1");
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, TEST_CONTEXT_KEY);
|
||||
mController.setParentFragment(mFragment);
|
||||
mController.setPackageName(TEST_PACKAGE_NAME);
|
||||
when(mApplicationMetadataUtils.packageContainsXmlFile(mPackageManager, TEST_PACKAGE_NAME))
|
||||
.thenReturn(false);
|
||||
mController.setMbaWithMetadataStatus(mApplicationMetadataUtils, TEST_PACKAGE_NAME);
|
||||
mController.setEnableMbaFlag(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,8 +111,42 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noAppLabel_shouldReturnDisabled() {
|
||||
public void getAvailabilityStatus_noAppLabel_andNotMbaWithMetadata_shouldReturnDisabled()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
when(mUserManager.isManagedProfile()).thenReturn(false);
|
||||
mockMainlineModule(TEST_PACKAGE_NAME, false /* isMainlineModule */);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noAppLabel_andHaveMbaFile_shouldReturnAvailable()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, TEST_CONTEXT_KEY);
|
||||
mController.setPackageName(TEST_PACKAGE_NAME);
|
||||
mController.setParentFragment(mFragment);
|
||||
when(mApplicationMetadataUtils.packageContainsXmlFile(mPackageManager, TEST_PACKAGE_NAME))
|
||||
.thenReturn(true);
|
||||
mController.setMbaWithMetadataStatus(mApplicationMetadataUtils, TEST_PACKAGE_NAME);
|
||||
mockMainlineModule(TEST_PACKAGE_NAME, false /* isMainlineModule */);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_noAppLabel_andMbaFeatureFlagDisabled_shouldReturnDisabled()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
mController.setEnableMbaFlag(false);
|
||||
when(mUserManager.isManagedProfile()).thenReturn(false);
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, TEST_CONTEXT_KEY);
|
||||
mController.setPackageName(TEST_PACKAGE_NAME);
|
||||
mController.setParentFragment(mFragment);
|
||||
when(mApplicationMetadataUtils.packageContainsXmlFile(mPackageManager, TEST_PACKAGE_NAME))
|
||||
.thenReturn(true);
|
||||
mController.setMbaWithMetadataStatus(mApplicationMetadataUtils, TEST_PACKAGE_NAME);
|
||||
mockMainlineModule(TEST_PACKAGE_NAME, false /* isMainlineModule */);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
|
||||
@@ -105,13 +155,12 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
@Test
|
||||
public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable()
|
||||
throws PackageManager.NameNotFoundException {
|
||||
final String packageName = "Package1";
|
||||
when(mUserManager.isManagedProfile()).thenReturn(false);
|
||||
when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label1");
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, "test_key");
|
||||
mController.setPackageName(packageName);
|
||||
mController = new AppInstallerInfoPreferenceController(mContext, TEST_CONTEXT_KEY);
|
||||
mController.setPackageName(TEST_PACKAGE_NAME);
|
||||
mController.setParentFragment(mFragment);
|
||||
mockMainlineModule(packageName, false /* isMainlineModule */);
|
||||
mockMainlineModule(TEST_PACKAGE_NAME, false /* isMainlineModule */);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
@@ -129,7 +178,7 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_noAppStoreLink_shouldDisablePreference() {
|
||||
public void updateState_noAppStoreLink_andNotMbaWithMetadata_shouldDisablePreference() {
|
||||
final PackageInfo packageInfo = mock(PackageInfo.class);
|
||||
packageInfo.applicationInfo = mAppInfo;
|
||||
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
|
||||
@@ -139,6 +188,39 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
@Test
|
||||
public void updateState_noAppStoreLink_andMbaFeatureFlagDisabled_shouldDisablePreference() {
|
||||
mController.setEnableMbaFlag(false);
|
||||
when(mApplicationMetadataUtils.packageContainsXmlFile(mPackageManager, TEST_PACKAGE_NAME))
|
||||
.thenReturn(true);
|
||||
mController.setMbaWithMetadataStatus(mApplicationMetadataUtils, TEST_PACKAGE_NAME);
|
||||
final PackageInfo packageInfo = mock(PackageInfo.class);
|
||||
packageInfo.applicationInfo = mAppInfo;
|
||||
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
|
||||
when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(null);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_noAppStoreLink_andMbaWithMetadata_shouldSetPreferenceIntent() {
|
||||
when(mApplicationMetadataUtils.packageContainsXmlFile(mPackageManager, TEST_PACKAGE_NAME))
|
||||
.thenReturn(true);
|
||||
mController.setMbaWithMetadataStatus(mApplicationMetadataUtils, TEST_PACKAGE_NAME);
|
||||
final PackageInfo packageInfo = mock(PackageInfo.class);
|
||||
packageInfo.applicationInfo = mAppInfo;
|
||||
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
|
||||
when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(null);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference, never()).setEnabled(false);
|
||||
verify(mPreference).setIntent(mIntentArgumentCaptor.capture());
|
||||
assertThat(mIntentArgumentCaptor.getValue().getAction())
|
||||
.isEqualTo(ACTION_TRANSPARENCY_METADATA);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_hasAppStoreLink_shouldSetPreferenceIntent() {
|
||||
@@ -154,7 +236,9 @@ public class AppInstallerInfoPreferenceControllerTest {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference, never()).setEnabled(false);
|
||||
verify(mPreference).setIntent(any(Intent.class));
|
||||
verify(mPreference).setIntent(mIntentArgumentCaptor.capture());
|
||||
assertThat(mIntentArgumentCaptor.getValue().getAction())
|
||||
.isEqualTo(Intent.ACTION_SHOW_APP_INFO);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.applications.mobilebundledapps;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.google.common.io.CharSource;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ApplicationMetadataUtilsTest {
|
||||
private static final String TEST_PACKAGE_NAME = "test";
|
||||
private static final String TEST_SOURCE_DIR = "sourcedir";
|
||||
|
||||
private static final String TEST_XML_SCHEMA = "<transparency-info>\n"
|
||||
+ " <template/>\n"
|
||||
+ " <contains-ads/>\n"
|
||||
+ " <developers>\n"
|
||||
+ " <developer name=\"Example ODM\" relationship=\"ODM\" email=\"odm@example.com\""
|
||||
+ " \n"
|
||||
+ " website=\"http://odm.example.com\" country=\"US\"/>\n"
|
||||
+ " <developer name=\"Example carrier\" relationship=\"CARRIER\" "
|
||||
+ "email=\"carrier@example.com\" \n"
|
||||
+ " country=\"US\"/>\n"
|
||||
+ " </developers>\n"
|
||||
+ " <contact url=\"http://example.com/contact-us\" email=\"contact@example.com\"/>\n"
|
||||
+ " <privacy-policy url=\"https://www.example.com/privacy-policy.html\"/>\n"
|
||||
+ " <description>This application provides the user with news "
|
||||
+ "headlines</description>\n"
|
||||
+ " <category name=\"News and magazines\"/>\n"
|
||||
+ "</transparency-info>";
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
private Document mDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
.parse(CharSource.wrap(TEST_XML_SCHEMA).asByteSource(StandardCharsets.UTF_8)
|
||||
.openStream());
|
||||
|
||||
|
||||
public ApplicationMetadataUtilsTest()
|
||||
throws IOException, ParserConfigurationException, SAXException {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup()
|
||||
throws PackageManager.NameNotFoundException, IOException, ParserConfigurationException,
|
||||
SAXException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
final ApplicationInfo appInfo = new ApplicationInfo();
|
||||
appInfo.sourceDir = TEST_SOURCE_DIR;
|
||||
when(mPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME),
|
||||
any(PackageManager.ApplicationInfoFlags.class))).thenReturn(appInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDefaultInstance_alwaysReturnSameInstance() {
|
||||
final ApplicationMetadataUtils firstInstance =
|
||||
ApplicationMetadataUtils.getDefaultInstance();
|
||||
|
||||
assertThat(firstInstance).isEqualTo(ApplicationMetadataUtils.getDefaultInstance());
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void createInstance_bubblesUpException() throws PackageManager.NameNotFoundException {
|
||||
final String testErrorMsg = "test";
|
||||
when(mPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME),
|
||||
any(PackageManager.ApplicationInfoFlags.class)))
|
||||
.thenThrow(new Exception(testErrorMsg));
|
||||
|
||||
ApplicationMetadataUtils.newInstance(mPackageManager, TEST_PACKAGE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldGetters_toReturnNull_whenEmptyOrError() {
|
||||
final ApplicationMetadataUtils appUtils = new ApplicationMetadataUtils();
|
||||
assertThat(appUtils.getContainsAds()).isEqualTo(false);
|
||||
assertThat(appUtils.getCategoryName()).isNull();
|
||||
assertThat(appUtils.getPrivacyPolicyUrl()).isNull();
|
||||
assertThat(appUtils.getDescription()).isNull();
|
||||
assertThat(appUtils.getDevelopers()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldGetters_toReturnCorrectValues_whenExists() {
|
||||
final ApplicationMetadataUtils appUtils = new ApplicationMetadataUtils();
|
||||
appUtils.setXmlDoc(mDocument);
|
||||
assertThat(appUtils.getContainsAds()).isEqualTo(true);
|
||||
assertThat(appUtils.getCategoryName()).isEqualTo("News and magazines");
|
||||
assertThat(appUtils.getPrivacyPolicyUrl())
|
||||
.isEqualTo("https://www.example.com/privacy-policy.html");
|
||||
assertThat(appUtils.getDescription())
|
||||
.isEqualTo("This application provides the user with news headlines");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDevelopers_returnsCorrectValues() {
|
||||
final ApplicationMetadataUtils appUtils = new ApplicationMetadataUtils();
|
||||
appUtils.setXmlDoc(mDocument);
|
||||
final List<ApplicationMetadataUtils.MbaDeveloper> developers = appUtils.getDevelopers();
|
||||
|
||||
assertThat(developers.size()).isEqualTo(2);
|
||||
assertThat(developers.get(0).country).isEqualTo("US");
|
||||
assertThat(developers.get(0).email).isEqualTo("odm@example.com");
|
||||
assertThat(developers.get(0).name).isEqualTo("Example ODM");
|
||||
assertThat(developers.get(1).relationship).isEqualTo("CARRIER");
|
||||
assertThat(developers.get(1).country).isEqualTo("US");
|
||||
assertThat(developers.get(1).email).isEqualTo("carrier@example.com");
|
||||
assertThat(developers.get(1).name).isEqualTo("Example carrier");
|
||||
assertThat(developers.get(1).relationship).isEqualTo("CARRIER");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user