Merge "Check MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED" into main
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
deleted file mode 100644
index 8f59f0e..0000000
--- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2019 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.network.telephony;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.telephony.data.ApnSetting;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.network.MobileDataContentObserver;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-/**
- * Preference controller for "MMS messages"
- */
-public class MmsMessagePreferenceController extends TelephonyTogglePreferenceController implements
-        LifecycleObserver, OnStart, OnStop {
-    private TelephonyManager mTelephonyManager;
-    private MobileDataContentObserver mMobileDataContentObserver;
-    private PreferenceScreen mScreen;
-    private Preference mPreference;
-
-    public MmsMessagePreferenceController(Context context, String key) {
-        super(context, key);
-        mMobileDataContentObserver = new MobileDataContentObserver(
-                new Handler(Looper.getMainLooper()));
-        mMobileDataContentObserver.setOnMobileDataChangedListener(() -> refreshPreference());
-    }
-
-    @Override
-    public int getAvailabilityStatus(int subId) {
-        final TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class)
-                .createForSubscriptionId(subId);
-        return (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
-                && !telephonyManager.isDataEnabled()
-                && telephonyManager.isApnMetered(ApnSetting.TYPE_MMS))
-                ? AVAILABLE
-                : CONDITIONALLY_UNAVAILABLE;
-    }
-
-    @Override
-    public void onStart() {
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            mMobileDataContentObserver.register(mContext, mSubId);
-            updateState(mPreference);
-        }
-    }
-
-    @Override
-    public void onStop() {
-        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            mMobileDataContentObserver.unRegister(mContext);
-        }
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mScreen = screen;
-        mPreference = screen.findPreference(getPreferenceKey());
-    }
-
-
-    public void init(int subId) {
-        mSubId = subId;
-        mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
-                .createForSubscriptionId(mSubId);
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        if (mTelephonyManager == null) {
-            return false;
-        }
-        mTelephonyManager.setMobileDataPolicyEnabled(
-                TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, isChecked);
-        return true;
-    }
-
-
-    @Override
-    public boolean isChecked() {
-        return mTelephonyManager != null && mTelephonyManager.isDataEnabledForApn(
-                ApnSetting.TYPE_MMS);
-    }
-
-    private void refreshPreference() {
-        if (mScreen != null) {
-            super.displayPreference(mScreen);
-        }
-    }
-}
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt
new file mode 100644
index 0000000..23a9738
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2023 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.network.telephony
+
+import android.content.Context
+import android.os.Handler
+import android.os.Looper
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.telephony.data.ApnSetting
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.preference.PreferenceScreen
+import com.android.settings.network.MobileDataContentObserver
+
+/**
+ * Preference controller for "MMS messages"
+ */
+class MmsMessagePreferenceController(context: Context, key: String) :
+    TelephonyTogglePreferenceController(context, key), DefaultLifecycleObserver {
+
+    private lateinit var telephonyManager: TelephonyManager
+
+    private var preferenceScreen: PreferenceScreen? = null
+
+    private val mobileDataContentObserver =
+        MobileDataContentObserver(Handler(Looper.getMainLooper())).apply {
+            setOnMobileDataChangedListener {
+                preferenceScreen?.let { super.displayPreference(it) }
+            }
+        }
+
+    fun init(subId: Int) {
+        mSubId = subId
+        telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
+            .createForSubscriptionId(subId)
+    }
+
+    override fun getAvailabilityStatus(subId: Int) =
+        if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID &&
+            !telephonyManager.isDataEnabled &&
+            telephonyManager.isApnMetered(ApnSetting.TYPE_MMS)
+        ) AVAILABLE else CONDITIONALLY_UNAVAILABLE
+
+    override fun onStart(owner: LifecycleOwner) {
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mobileDataContentObserver.register(mContext, mSubId)
+        }
+    }
+
+    override fun onStop(owner: LifecycleOwner) {
+        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            mobileDataContentObserver.unRegister(mContext)
+        }
+    }
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preferenceScreen = screen
+    }
+
+    override fun isChecked(): Boolean = telephonyManager.isMobileDataPolicyEnabled(
+        TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED
+    )
+
+    override fun setChecked(isChecked: Boolean): Boolean {
+        telephonyManager.setMobileDataPolicyEnabled(
+            TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED,
+            isChecked,
+        )
+        return true
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.kt
new file mode 100644
index 0000000..33a8575
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2023 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.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
+import android.telephony.TelephonyManager
+import android.telephony.data.ApnSetting
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.core.BasePreferenceController.AVAILABLE
+import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.verify
+
+@RunWith(AndroidJUnit4::class)
+class MmsMessagePreferenceControllerTest {
+    private val mockTelephonyManager: TelephonyManager = mock<TelephonyManager> {
+        on { createForSubscriptionId(any()) } doReturn mock
+    }
+
+    private var context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+    }
+
+    private val controller = MmsMessagePreferenceController(context, KEY).apply {
+        init(SUB_ID)
+    }
+
+    @Test
+    fun getAvailabilityStatus_invalidSubscription_returnUnavailable() {
+        controller.init(INVALID_SUBSCRIPTION_ID)
+
+        val availabilityStatus = controller.getAvailabilityStatus(INVALID_SUBSCRIPTION_ID)
+
+        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
+    }
+
+    @Test
+    fun getAvailabilityStatus_mobileDataOn_returnUnavailable() {
+        mockTelephonyManager.stub {
+            on { isDataEnabled } doReturn true
+        }
+
+        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
+
+        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
+    }
+
+    @Test
+    fun getAvailabilityStatus_meteredOff_returnUnavailable() {
+        mockTelephonyManager.stub {
+            on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn false
+        }
+
+        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
+
+        assertThat(availabilityStatus).isEqualTo(CONDITIONALLY_UNAVAILABLE)
+    }
+
+    @Test
+    fun getAvailabilityStatus_mobileDataOffWithValidSubId_returnAvailable() {
+        mockTelephonyManager.stub {
+            on { isDataEnabled } doReturn false
+            on { isApnMetered(ApnSetting.TYPE_MMS) } doReturn true
+        }
+
+        val availabilityStatus = controller.getAvailabilityStatus(SUB_ID)
+
+        assertThat(availabilityStatus).isEqualTo(AVAILABLE)
+    }
+
+    @Test
+    fun isChecked_whenMmsNotAlwaysAllowed_returnFalse() {
+        mockTelephonyManager.stub {
+            on {
+                isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED)
+            } doReturn false
+        }
+
+        val isChecked = controller.isChecked()
+
+        assertThat(isChecked).isFalse()
+    }
+
+    @Test
+    fun isChecked_whenMmsAlwaysAllowed_returnTrue() {
+        mockTelephonyManager.stub {
+            on {
+                isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED)
+            } doReturn true
+        }
+
+        val isChecked = controller.isChecked()
+
+        assertThat(isChecked).isTrue()
+    }
+
+    @Test
+    fun setChecked_setTrue_setDataIntoSubscriptionManager() {
+        controller.setChecked(true)
+
+        verify(mockTelephonyManager).setMobileDataPolicyEnabled(
+            TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, true
+        )
+    }
+
+    @Test
+    fun setChecked_setFalse_setDataIntoSubscriptionManager() {
+        controller.setChecked(false)
+
+        verify(mockTelephonyManager).setMobileDataPolicyEnabled(
+            TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false
+        )
+    }
+
+    private companion object {
+        const val KEY = "mms_message"
+        const val SUB_ID = 2
+    }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.java
deleted file mode 100644
index 127cdfd..0000000
--- a/tests/unit/src/com/android/settings/network/telephony/MmsMessagePreferenceControllerTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2020 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.network.telephony;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.telephony.data.ApnSetting;
-
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class MmsMessagePreferenceControllerTest {
-    private static final int SUB_ID = 2;
-
-    @Mock
-    private TelephonyManager mTelephonyManager;
-    @Mock
-    private SubscriptionManager mSubscriptionManager;
-
-    private MmsMessagePreferenceController mController;
-    private SwitchPreference mPreference;
-    private Context mContext;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
-        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
-        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
-        when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
-
-        mPreference = spy(new SwitchPreference(mContext));
-        mController = new MmsMessagePreferenceController(mContext, "mms_message");
-        mController.init(SUB_ID);
-        mPreference.setKey(mController.getPreferenceKey());
-    }
-
-    @Test
-    public void getAvailabilityStatus_invalidSubscription_returnUnavailable() {
-        mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_mobileDataOn_returnUnavailable() {
-        when(mTelephonyManager.isDataEnabled()).thenReturn(true);
-
-        assertThat(mController.getAvailabilityStatus(SUB_ID)).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_meteredOff_returnUnavailable() {
-        when(mTelephonyManager.isApnMetered(ApnSetting.TYPE_MMS)).thenReturn(false);
-
-        assertThat(mController.getAvailabilityStatus(SUB_ID)).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_mobileDataOffWithValidSubId_returnAvailable() {
-        mController.init(SUB_ID);
-        when(mTelephonyManager.isDataEnabled()).thenReturn(false);
-        when(mTelephonyManager.isApnMetered(ApnSetting.TYPE_MMS)).thenReturn(true);
-
-        assertThat(mController.getAvailabilityStatus(SUB_ID)).isEqualTo(AVAILABLE);
-    }
-
-    @Test
-    public void isChecked_returnDataFromTelephonyManager() {
-        when(mTelephonyManager.isDataEnabledForApn(ApnSetting.TYPE_MMS)).thenReturn(false);
-        assertThat(mController.isChecked()).isFalse();
-
-        when(mTelephonyManager.isDataEnabledForApn(ApnSetting.TYPE_MMS)).thenReturn(true);
-        assertThat(mController.isChecked()).isTrue();
-    }
-
-    @Test
-    public void setChecked_setDataIntoSubscriptionManager() {
-        mController.setChecked(true);
-        verify(mTelephonyManager).setMobileDataPolicyEnabled(
-                TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, true);
-
-        mController.setChecked(false);
-        verify(mTelephonyManager).setMobileDataPolicyEnabled(
-                TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false);
-    }
-
-    @Test
-    public void onStart_updatePreferenceUiState() {
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-        PreferenceManager preferenceManager = new PreferenceManager(mContext);
-        PreferenceScreen preferenceScreen = preferenceManager.createPreferenceScreen(mContext);
-        preferenceScreen.addPreference(mPreference);
-        mController.displayPreference(preferenceScreen);
-
-        mController.onStart();
-
-        // First is preference initialization, and second is in onStart();
-        verify(mPreference, times(2)).setChecked(anyBoolean());
-    }
-}