Merge "Revert "Add a new logger for StatsLog""
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e93e56d..e86917c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -678,7 +678,7 @@
<!-- check box to allow data usage when roaming [CHAR LIMIT=41] -->
<string name="allow_data_usage_title">Allow data usage when roaming</string>
<!-- mobile network settings screen, setting check box title -->
- <string name="roaming">Data roaming</string>
+ <string name="roaming">Roaming</string>
<!-- mobile network settings screen, setting option summary text when check box is selected -->
<string name="roaming_enable">Connect to data services when roaming</string>
<!-- mobile network settings screen, setting option summary text when check box is clear -->
@@ -9964,6 +9964,13 @@
<!-- UI debug setting: ANGLE enabled app has been set [CHAR LIMIT=NONE] -->
<string name="angle_enabled_app_set">ANGLE enabled application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
+ <!-- UI debug setting: select an app to use updated graphics driver [CHAR LIMIT=100] -->
+ <string name="updated_gfx_driver_dev_opt_in_app">Select app to use updated graphics driver</string>
+ <!-- UI debug setting: no app selected to use updated GPU driver [CHAR LIMIT=100] -->
+ <string name="updated_gfx_driver_dev_opt_in_app_not_set">No selected app to use updated graphics driver</string>
+ <!-- UI debug setting: app selected to use updated graphics driver [CHAR LIMIT=NONE] -->
+ <string name="updated_gfx_driver_dev_opt_in_app_set">Opt in application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
+
<!-- Slices Strings -->
<!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
@@ -10243,6 +10250,8 @@
<string name="mobile_data_usage_title">App data usage</string>
<!-- Summary to show the current network mode is invalid. [CHAR LIMIT=NONE]-->
<string name="mobile_network_mode_error">Invalid Network Mode <xliff:g id="networkModeId" example="0">%1$d</xliff:g>. Ignore.</string>
+ <!-- Title for Apn settings in mobile network settings [CHAR LIMIT=60] -->
+ <string name="mobile_network_apn_title">Access Point Names</string>
<!-- Available networks screen, summary when button disallowed due to permanent automatic mode [CHAR LIMIT=NONE] -->
<string name="manual_mode_disallowed_summary">Unavailable when connected to <xliff:g id="carrier" example="verizon">%1$s</xliff:g></string>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 49018f8..a35ad1b 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -422,6 +422,10 @@
<Preference android:key="angle_enabled_app"
android:title="@string/angle_enabled_app" />
+ <Preference android:key="updated_gfx_driver_dev_opt_in_app"
+ android:summary="@string/updated_gfx_driver_dev_opt_in_app_summary"
+ android:title="@string/updated_gfx_driver_dev_opt_in_app" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
deleted file mode 100644
index cf56595..0000000
--- a/res/xml/gsm_umts_options.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2008 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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <!--We want separate APN setting from reset of settings because-->
- <!--we want user to change it with caution.-->
- <PreferenceCategory
- android:key="category_gsm_apn_key"
- android:layout="@layout/preference_category_no_label">
-
- <com.android.settingslib.RestrictedPreference
- android:key="button_gsm_apn_key"
- android:title="@string/apn_settings"
- android:persistent="false" />
- </PreferenceCategory>
-
- <PreferenceScreen
- android:key="carrier_settings_key"
- android:title="@string/carrier_settings_title">
- <!-- b/114749736, create a preference controller to build intent -->
- </PreferenceScreen>
-
-</PreferenceScreen>
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 0478664..cc914ad 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -138,7 +138,7 @@
<com.android.settingslib.RestrictedPreference
android:key="telephony_apn_key"
android:persistent="false"
- android:title="@string/apn_settings"
+ android:title="@string/mobile_network_apn_title"
settings:allowDividerAbove="true"
settings:controller="com.android.settings.network.telephony.ApnPreferenceController"/>
diff --git a/src/com/android/settings/accounts/AccountFeatureProvider.java b/src/com/android/settings/accounts/AccountFeatureProvider.java
index 9829ca6..fd65095 100644
--- a/src/com/android/settings/accounts/AccountFeatureProvider.java
+++ b/src/com/android/settings/accounts/AccountFeatureProvider.java
@@ -18,8 +18,10 @@
import android.accounts.Account;
import android.content.Context;
+import android.content.Intent;
public interface AccountFeatureProvider {
String getAccountType();
Account[] getAccounts(Context context);
+ Intent getAccountSettingsDeeplinkIntent();
}
diff --git a/src/com/android/settings/accounts/AccountFeatureProviderImpl.java b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java
index 90b581b..2e0f432 100644
--- a/src/com/android/settings/accounts/AccountFeatureProviderImpl.java
+++ b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java
@@ -2,6 +2,7 @@
import android.accounts.Account;
import android.content.Context;
+import android.content.Intent;
public class AccountFeatureProviderImpl implements AccountFeatureProvider {
@Override
@@ -13,4 +14,9 @@
public Account[] getAccounts(Context context) {
return new Account[0];
}
+
+ @Override
+ public Intent getAccountSettingsDeeplinkIntent() {
+ return null;
+ }
}
diff --git a/src/com/android/settings/accounts/AvatarViewMixin.java b/src/com/android/settings/accounts/AvatarViewMixin.java
index 6dcf312..78750b1 100644
--- a/src/com/android/settings/accounts/AvatarViewMixin.java
+++ b/src/com/android/settings/accounts/AvatarViewMixin.java
@@ -17,18 +17,30 @@
package com.android.settings.accounts;
import android.accounts.Account;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
import android.util.Log;
import android.widget.ImageView;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.OnLifecycleEvent;
import com.android.settings.R;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.List;
/**
* Avatar related work to the onStart method of registered observable classes
@@ -37,12 +49,39 @@
public class AvatarViewMixin implements LifecycleObserver {
private static final String TAG = "AvatarViewMixin";
+ @VisibleForTesting
+ static final Intent INTENT_GET_ACCOUNT_DATA =
+ new Intent("android.content.action.SETTINGS_ACCOUNT_DATA");
+
+ private static final String METHOD_GET_ACCOUNT_AVATAR = "getAccountAvatar";
+ private static final String KEY_AVATAR_BITMAP = "account_avatar";
+ private static final int REQUEST_CODE = 1013;
+
private final Context mContext;
private final ImageView mAvatarView;
+ private final MutableLiveData<Bitmap> mAvatarImage;
- public AvatarViewMixin(Context context, ImageView avatarView) {
- mContext = context.getApplicationContext();
+ public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
+ mContext = activity.getApplicationContext();
mAvatarView = avatarView;
+ mAvatarView.setOnClickListener(v -> {
+ if (hasAccount()) {
+ //TODO(b/117509285) launch the new page of the MeCard
+ } else {
+ final Intent intent = FeatureFactory.getFactory(mContext)
+ .getAccountFeatureProvider()
+ .getAccountSettingsDeeplinkIntent();
+
+ if (intent != null) {
+ activity.startActivityForResult(intent, REQUEST_CODE);
+ }
+ }
+ });
+
+ mAvatarImage = new MutableLiveData<>();
+ mAvatarImage.observe(activity, bitmap -> {
+ avatarView.setImageBitmap(bitmap);
+ });
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
@@ -52,7 +91,7 @@
return;
}
if (hasAccount()) {
- //TODO(b/117509285): To migrate account icon on search bar
+ loadAvatar();
} else {
mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp);
}
@@ -64,4 +103,34 @@
mContext).getAccountFeatureProvider().getAccounts(mContext);
return (accounts != null) && (accounts.length > 0);
}
+
+ private void loadAvatar() {
+ final String authority = queryProviderAuthority();
+ if (TextUtils.isEmpty(authority)) {
+ return;
+ }
+
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .build();
+ final Bundle bundle = mContext.getContentResolver().call(uri,
+ METHOD_GET_ACCOUNT_AVATAR, null /* arg */, null /* extras */);
+ final Bitmap bitmap = bundle.getParcelable(KEY_AVATAR_BITMAP);
+ mAvatarImage.postValue(bitmap);
+ });
+ }
+
+ @VisibleForTesting
+ String queryProviderAuthority() {
+ final List<ResolveInfo> providers =
+ mContext.getPackageManager().queryIntentContentProviders(INTENT_GET_ACCOUNT_DATA,
+ PackageManager.MATCH_SYSTEM_ONLY);
+ if (providers.size() == 1) {
+ return providers.get(0).providerInfo.authority;
+ } else {
+ Log.w(TAG, "The size of the provider is " + providers.size());
+ return null;
+ }
+ }
}
diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
index 6e3ec93..3532a15 100644
--- a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
+++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
@@ -27,4 +27,6 @@
int REQUEST_MOCK_LOCATION_APP = 2;
int REQUEST_CODE_ANGLE_ENABLED_APP = 3;
+
+ int REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP = 4;
}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 5663d1e..0fcf6aa 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -406,6 +406,7 @@
controllers.add(new WaitForDebuggerPreferenceController(context));
controllers.add(new EnableGpuDebugLayersPreferenceController(context));
controllers.add(new AngleEnabledAppPreferenceController(context, fragment));
+ controllers.add(new UpdatedGfxDriverDevOptInPreferenceController(context, fragment));
controllers.add(new VerifyAppsOverUsbPreferenceController(context));
controllers.add(new LogdSizePreferenceController(context));
controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle));
diff --git a/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceController.java b/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceController.java
new file mode 100644
index 0000000..ad2131e
--- /dev/null
+++ b/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceController.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2018 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.development;
+
+import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
+ .REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+// TODO(b/119221883): Need to override isAvailable() to return false when updatable graphics driver is not supported.
+public class UpdatedGfxDriverDevOptInPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements PreferenceControllerMixin, OnActivityResultListener {
+
+ private static final String UPDATED_GFX_DRIVER_DEV_OPT_IN_APP_KEY =
+ "updated_gfx_driver_dev_opt_in_app";
+
+ private final DevelopmentSettingsDashboardFragment mFragment;
+ private final PackageManager mPackageManager;
+
+ public UpdatedGfxDriverDevOptInPreferenceController(Context context,
+ DevelopmentSettingsDashboardFragment fragment) {
+ super(context);
+ mFragment = fragment;
+ mPackageManager = mContext.getPackageManager();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return UPDATED_GFX_DRIVER_DEV_OPT_IN_APP_KEY;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (UPDATED_GFX_DRIVER_DEV_OPT_IN_APP_KEY.equals(preference.getKey())) {
+ // pass it on to settings
+ final Intent intent = getActivityStartIntent();
+ mFragment.startActivityForResult(intent,
+ REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ updatePreferenceSummary();
+ }
+
+ @Override
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode != REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP
+ || resultCode != Activity.RESULT_OK) {
+ return false;
+ }
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP, data.getAction());
+ updatePreferenceSummary();
+ return true;
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.updated_gfx_driver_dev_opt_in_app_not_set));
+ }
+
+ @VisibleForTesting
+ Intent getActivityStartIntent() {
+ Intent intent = new Intent(mContext, AppPicker.class);
+ intent.putExtra(AppPicker.EXTRA_NON_SYSTEM, true /* value */);
+ return intent;
+ }
+
+ private void updatePreferenceSummary() {
+ final String updatedGfxDriverDevOptInApp = Settings.Global.getString(
+ mContext.getContentResolver(), Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+ if (updatedGfxDriverDevOptInApp != null && !updatedGfxDriverDevOptInApp.isEmpty()) {
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.updated_gfx_driver_dev_opt_in_app_set,
+ getAppLabel(updatedGfxDriverDevOptInApp)));
+ } else {
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.updated_gfx_driver_dev_opt_in_app_not_set));
+ }
+ }
+
+ private String getAppLabel(String applicationPackageName) {
+ try {
+ final ApplicationInfo ai = mPackageManager.getApplicationInfo(applicationPackageName,
+ PackageManager.GET_DISABLED_COMPONENTS);
+ final CharSequence lab = mPackageManager.getApplicationLabel(ai);
+ return lab != null ? lab.toString() : applicationPackageName;
+ } catch (PackageManager.NameNotFoundException e) {
+ return applicationPackageName;
+ }
+ }
+}
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 7f04bde..14a918e 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -264,6 +264,10 @@
return false;
}
+ protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
+ return ChooseLockGeneric.InternalActivity.class;
+ }
+
protected void addHeaderView() {
if (mForFingerprint) {
setHeaderView(R.layout.choose_lock_generic_fingerprint_header);
@@ -291,7 +295,7 @@
return true;
} else if (KEY_SKIP_FINGERPRINT.equals(key) || KEY_SKIP_FACE.equals(key)) {
Intent chooseLockGenericIntent = new Intent(getActivity(),
- ChooseLockGeneric.InternalActivity.class);
+ getInternalActivityClass());
chooseLockGenericIntent.setAction(getIntent().getAction());
// Forward the target user id to ChooseLockGeneric.
chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 700cc2d..7600104 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -27,6 +27,7 @@
import android.view.ViewGroup;
import android.widget.LinearLayout;
+import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView;
@@ -135,6 +136,11 @@
return true;
}
+ @Override
+ protected Class<? extends ChooseLockGeneric.InternalActivity> getInternalActivityClass() {
+ return SetupChooseLockGeneric.InternalActivity.class;
+ }
+
/***
* Disables preferences that are less secure than required quality and shows only secure
* screen lock options here.
@@ -207,4 +213,25 @@
return intent;
}
}
+
+ public static class InternalActivity extends ChooseLockGeneric.InternalActivity {
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ return InternalSetupChooseLockGenericFragment.class.getName().equals(fragmentName);
+ }
+
+ @Override
+ /* package */ Class<? extends Fragment> getFragmentClass() {
+ return InternalSetupChooseLockGenericFragment.class;
+ }
+
+ public static class InternalSetupChooseLockGenericFragment
+ extends ChooseLockGenericFragment {
+ @Override
+ protected boolean canRunBeforeDeviceProvisioned() {
+ return true;
+ }
+ }
+ }
+
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index f9301a2..479ffee 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -58,6 +58,7 @@
com.android.settings.notification.ZenModeEventRuleSettings
com.android.settings.notification.ZenModeScheduleRuleSettings
com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment
+com.android.settings.password.SetupChooseLockGeneric$InternalActivity$InternalSetupChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
com.android.settings.print.PrintJobSettingsFragment
com.android.settings.print.PrintServiceSettingsFragment
diff --git a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
index b3d929c..039d2e2 100644
--- a/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AvatarViewMixinTest.java
@@ -24,6 +24,10 @@
import android.accounts.Account;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
import android.widget.ImageView;
import com.android.settings.homepage.SettingsHomepageActivity;
@@ -39,38 +43,45 @@
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowPackageManager;
@RunWith(SettingsRobolectricTestRunner.class)
public class AvatarViewMixinTest {
private static final String DUMMY_ACCOUNT = "test@domain.com";
private static final String DUMMY_DOMAIN = "domain.com";
+ private static final String DUMMY_AUTHORITY = "authority.domain.com";
private Context mContext;
private ImageView mImageView;
+ private ActivityController mController;
+ private SettingsHomepageActivity mActivity;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mImageView = new ImageView(mContext);
+ mController = Robolectric.buildActivity(SettingsHomepageActivity.class).create();
+ mActivity = (SettingsHomepageActivity) mController.get();
}
@Test
public void hasAccount_useDefaultAccountData_returnFalse() {
- final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mActivity, mImageView);
assertThat(avatarViewMixin.hasAccount()).isFalse();
}
@Test
@Config(shadows = ShadowAccountFeatureProviderImpl.class)
public void hasAccount_useShadowAccountData_returnTrue() {
- final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mActivity, mImageView);
assertThat(avatarViewMixin.hasAccount()).isTrue();
}
@Test
public void onStart_configDisabled_doNothing() {
- final AvatarViewMixin mixin = spy(new AvatarViewMixin(mContext, mImageView));
+ final AvatarViewMixin mixin = spy(new AvatarViewMixin(mActivity, mImageView));
mixin.onStart();
verify(mixin, never()).hasAccount();
@@ -79,19 +90,45 @@
@Test
@Config(qualifiers = "mcc999")
public void onStart_useMockAvatarViewMixin_shouldBeExecuted() {
- final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mContext, mImageView));
+ final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mActivity, mImageView));
- final ActivityController controller = Robolectric.buildActivity(
- SettingsHomepageActivity.class).create();
- final SettingsHomepageActivity settingsHomepageActivity =
- (SettingsHomepageActivity) controller.get();
- settingsHomepageActivity.getLifecycle().addObserver(mockAvatar);
- controller.start();
+ mActivity.getLifecycle().addObserver(mockAvatar);
+ mController.start();
verify(mockAvatar).hasAccount();
}
- @Implements(AccountFeatureProviderImpl.class)
+ @Test
+ public void queryProviderAuthority_useShadowPackagteManager_returnNull() {
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mActivity, mImageView);
+
+ assertThat(avatarViewMixin.queryProviderAuthority()).isNull();
+ }
+
+ @Test
+ public void queryProviderAuthority_useNewShadowPackagteManager_returnAuthority() {
+ final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mActivity, mImageView);
+ ShadowPackageManager shadowPackageManager = Shadow.extract(mContext.getPackageManager());
+ final PackageInfo accountProvider = new PackageInfo();
+ accountProvider.packageName = "test.pkg";
+ accountProvider.applicationInfo = new ApplicationInfo();
+ accountProvider.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+ accountProvider.applicationInfo.packageName = accountProvider.packageName;
+ accountProvider.providers = new ProviderInfo[1];
+ accountProvider.providers[0] = new ProviderInfo();
+ accountProvider.providers[0].authority = DUMMY_AUTHORITY;
+ accountProvider.providers[0].packageName = accountProvider.packageName;
+ accountProvider.providers[0].name = "test.class";
+ accountProvider.providers[0].applicationInfo = accountProvider.applicationInfo;
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.providerInfo = accountProvider.providers[0];
+ shadowPackageManager.addResolveInfoForIntent(AvatarViewMixin.INTENT_GET_ACCOUNT_DATA,
+ resolveInfo);
+ assertThat(avatarViewMixin.queryProviderAuthority()).isEqualTo(DUMMY_AUTHORITY);
+ }
+
+ @Implements(value = AccountFeatureProviderImpl.class)
public static class ShadowAccountFeatureProviderImpl {
@Implementation
diff --git a/tests/robotests/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceControllerTest.java
new file mode 100644
index 0000000..3071912
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/UpdatedGfxDriverDevOptInPreferenceControllerTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018 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.development;
+
+import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class UpdatedGfxDriverDevOptInPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private DevelopmentSettingsDashboardFragment mFragment;
+
+ private Context mContext;
+ private Preference mPreference;
+ private UpdatedGfxDriverDevOptInPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new UpdatedGfxDriverDevOptInPreferenceController(mContext, mFragment));
+ mPreference = new Preference(mContext);
+ mPreference.setKey(mController.getPreferenceKey());
+
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_preferenceClicked_launchActivity() {
+ final Intent activityStartIntent = new Intent(mContext, AppPicker.class);
+ final String preferenceKey = mController.getPreferenceKey();
+ doReturn(activityStartIntent).when(mController).getActivityStartIntent();
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mFragment).startActivityForResult(activityStartIntent,
+ REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+ }
+
+ @Test
+ public void updateState_foobarAppSelected_shouldUpdateSummaryWithUpdatedDriverDevOptInAppLabel() {
+ final String selectedApp = "foobar";
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putString(contentResolver,
+ Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP, selectedApp);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo(mContext.getString(R.string.updated_gfx_driver_dev_opt_in_app_set, selectedApp));
+ }
+
+ @Test
+ public void updateState_noAppSelected_shouldUpdateSummaryWithNoAppSelected() {
+ final String selectedApp = null;
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putString(contentResolver,
+ Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP, selectedApp);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary()).isEqualTo(mContext.getString(R.string.updated_gfx_driver_dev_opt_in_app_not_set));
+ }
+
+ @Test
+ public void onActivityResult_foobarAppSelected_shouldUpdateSummaryWithUpdatedDriverDevOptInLabel() {
+ Intent activityResultIntent = new Intent(mContext, AppPicker.class);
+ final String appLabel = "foobar";
+ activityResultIntent.setAction(appLabel);
+ final boolean result = mController
+ .onActivityResult(REQUEST_CODE_UPDATED_GFX_DRIVER_DEV_OPT_IN_APP, Activity.RESULT_OK,
+ activityResultIntent);
+
+ assertThat(result).isTrue();
+ assertThat(mPreference.getSummary()).isEqualTo(mContext.getString(R.string.updated_gfx_driver_dev_opt_in_app_set, appLabel));
+ }
+
+ @Test
+ public void onActivityResult_badRequestCode_shouldReturnFalse() {
+ assertThat(mController.onActivityResult(
+ -1 /* requestCode */, -1 /* resultCode */, null /* intent */)).isFalse();
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.getSummary()).isEqualTo(mContext.getString(R.string.updated_gfx_driver_dev_opt_in_app_not_set));
+ }
+}
diff --git a/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java b/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java
new file mode 100644
index 0000000..ce3d08f
--- /dev/null
+++ b/tests/unit/src/com/android/settings/password/SetupChooseLockGenericTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 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.password;
+
+import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import android.support.test.runner.lifecycle.Stage;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiSelector;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collection;
+
+/**
+ * Tests for {@link SetupChooseLockGenericTest}
+ *
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SetupChooseLockGenericTest {
+
+ private UiDevice mDevice;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mContext = getInstrumentation().getTargetContext();
+ Settings.Global.putInt(
+ mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
+ }
+
+ @After
+ public void tearDown() {
+ Settings.Global.putInt(
+ mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
+ }
+
+ @Test
+ public void clickSkipFigerprintPreference_deviceNotProvisioned_shouldBeAbleToProceed()
+ throws Throwable {
+ final Intent newPasswordIntent =
+ new Intent(getTargetContext(), SetupChooseLockGeneric.class)
+ .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true)
+ .setAction(ACTION_SET_NEW_PASSWORD)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+ getInstrumentation().getContext().startActivity(newPasswordIntent);
+ mDevice.waitForIdle();
+ mDevice.findObject(new UiSelector().textContains("Continue without ")).click();
+
+ final Activity activity = getCurrentActivity();
+ assertThat(activity).isInstanceOf(SetupChooseLockGeneric.InternalActivity.class);
+ }
+
+ private Activity getCurrentActivity() throws Throwable {
+ getInstrumentation().waitForIdleSync();
+ final Activity[] activity = new Activity[1];
+ getInstrumentation().runOnMainSync(() -> {
+ Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance()
+ .getActivitiesInStage(Stage.RESUMED);
+ activity[0] = activities.iterator().next();
+ });
+ return activity[0];
+ }
+
+}