Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba1ec910 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

New BillingCycleRepository

Migrate BillingCyclePreference to BillingCycleRepository first, will
also migrate DataUsageList in future cl.

Also fix an issue that the BillingCyclePreference initial enable state
not set.

Bug: 290856342
Test: manual - on mobile settings
Test: unit test
Change-Id: Idd171fefbc30763010afb7bfb68543612f7b9b1a
parent 2b21582f
Loading
Loading
Loading
Loading
+0 −107
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.datausage;

import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.util.AttributeSet;

import androidx.preference.Preference;

import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.MobileDataEnabledListener;

/**
 * Preference which displays billing cycle of subscription
 */
public class BillingCyclePreference extends Preference
        implements TemplatePreference, MobileDataEnabledListener.Client {

    private NetworkTemplate mTemplate;
    private NetworkServices mServices;
    private int mSubId;
    private MobileDataEnabledListener mListener;

    /**
     * Preference constructor
     *
     * @param context Context of preference
     * @param arrts The attributes of the XML tag that is inflating the preference
     */
    public BillingCyclePreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        mListener = new MobileDataEnabledListener(context, this);
    }

    @Override
    public void onAttached() {
        super.onAttached();
        mListener.start(mSubId);
    }

    @Override
    public void onDetached() {
        mListener.stop();
        super.onDetached();
    }

    @Override
    public void setTemplate(NetworkTemplate template, int subId,
            NetworkServices services) {
        mTemplate = template;
        mSubId = subId;
        mServices = services;
        setSummary(null);

        setIntent(getIntent());
    }

    private void updateEnabled() {
        try {
            setEnabled(mServices.mNetworkService.isBandwidthControlEnabled()
                    && mServices.mTelephonyManager.createForSubscriptionId(mSubId)
                            .isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
                    && mServices.mUserManager.isAdminUser());
        } catch (RemoteException e) {
            setEnabled(false);
        }
    }

    @Override
    public Intent getIntent() {
        final Bundle args = new Bundle();
        args.putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, mTemplate);
        return new SubSettingLauncher(getContext())
                .setDestination(BillingCycleSettings.class.getName())
                .setArguments(args)
                .setTitleRes(R.string.billing_cycle)
                .setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
                .toIntent();
    }

    /**
     * Implementation of {@code MobileDataEnabledListener.Client}
     */
    public void onMobileDataEnabledChange() {
        updateEnabled();
    }
}
+80 −0
Original line number Diff line number Diff line
/*
 * 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.datausage

import android.app.settings.SettingsEnums
import android.content.Context
import android.content.Intent
import android.net.NetworkTemplate
import android.os.Bundle
import android.util.AttributeSet
import androidx.preference.Preference
import com.android.settings.R
import com.android.settings.core.SubSettingLauncher
import com.android.settings.datausage.TemplatePreference.NetworkServices
import com.android.settings.datausage.lib.BillingCycleRepository
import com.android.settings.network.MobileDataEnabledListener

/**
 * Preference which displays billing cycle of subscription
 *
 * @param context Context of preference
 * @param attrs   The attributes of the XML tag that is inflating the preference
 */
class BillingCyclePreference @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet?,
    private val repository: BillingCycleRepository = BillingCycleRepository(context),
) : Preference(context, attrs), TemplatePreference {
    private lateinit var template: NetworkTemplate
    private var subId = 0

    private val listener = MobileDataEnabledListener(context) {
        updateEnabled()
    }

    override fun setTemplate(template: NetworkTemplate, subId: Int, services: NetworkServices?) {
        this.template = template
        this.subId = subId
        summary = null
        updateEnabled()
    }

    override fun onAttached() {
        super.onAttached()
        listener.start(subId)
    }

    override fun onDetached() {
        listener.stop()
        super.onDetached()
    }

    private fun updateEnabled() {
        isEnabled = repository.isModifiable(subId)
    }

    override fun getIntent(): Intent {
        val args = Bundle().apply {
            putParcelable(DataUsageList.EXTRA_NETWORK_TEMPLATE, template)
        }
        return SubSettingLauncher(context).apply {
            setDestination(BillingCycleSettings::class.java.name)
            setArguments(args)
            setTitleRes(R.string.billing_cycle)
            setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
        }.toIntent()
    }
}
+1 −18
Original line number Diff line number Diff line
@@ -17,20 +17,12 @@
package com.android.settings.datausage;

import android.content.Context;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
import android.os.INetworkManagementService;
import android.os.ServiceManager;
import android.os.UserManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import androidx.preference.PreferenceScreen;

import com.android.settings.core.BasePreferenceController;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.datausage.lib.DataUsageLib;
import com.android.settingslib.NetworkPolicyEditor;

public class BillingCyclePreferenceController extends BasePreferenceController {
    private int mSubscriptionId;
@@ -48,18 +40,9 @@ public class BillingCyclePreferenceController extends BasePreferenceController {
        super.displayPreference(screen);
        BillingCyclePreference preference = screen.findPreference(getPreferenceKey());

        TemplatePreference.NetworkServices services = new TemplatePreference.NetworkServices();
        services.mNetworkService = INetworkManagementService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
        services.mPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
        services.mPolicyEditor = new NetworkPolicyEditor(services.mPolicyManager);
        services.mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
        services.mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
        services.mUserManager = mContext.getSystemService(UserManager.class);

        NetworkTemplate template = DataUsageLib.getMobileTemplate(mContext, mSubscriptionId);

        preference.setTemplate(template, mSubscriptionId, services);
        preference.setTemplate(template, mSubscriptionId, null);
    }

    @Override
+53 −0
Original line number Diff line number Diff line
/*
 * 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.datausage.lib

import android.content.Context
import android.os.INetworkManagementService
import android.os.ServiceManager
import android.telephony.TelephonyManager
import android.util.Log
import com.android.settingslib.spaprivileged.framework.common.userManager

class BillingCycleRepository(
    context: Context,
    private val networkService: INetworkManagementService =
        INetworkManagementService.Stub.asInterface(
            ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)
        ),
) {
    private val userManager = context.userManager
    private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!

    fun isModifiable(subId: Int): Boolean =
        isBandwidthControlEnabled() && userManager.isAdminUser && isDataEnabled(subId)

    fun isBandwidthControlEnabled(): Boolean = try {
        networkService.isBandwidthControlEnabled
    } catch (e: Exception) {
        Log.w(TAG, "problem talking with INetworkManagementService: ", e)
        false
    }

    private fun isDataEnabled(subId: Int): Boolean =
        telephonyManager.createForSubscriptionId(subId)
            .isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)

    companion object {
        private const val TAG = "BillingCycleRepository"
    }
}
+60 −0
Original line number Diff line number Diff line
/*
 * 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.datausage

import android.content.Context
import android.net.NetworkTemplate
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.datausage.lib.BillingCycleRepository
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

@RunWith(AndroidJUnit4::class)
class BillingCyclePreferenceTest {

    private val mockBillingCycleRepository = mock<BillingCycleRepository> {
        on { isModifiable(SUB_ID) } doReturn false
    }

    private val context: Context = ApplicationProvider.getApplicationContext()

    private val preference = BillingCyclePreference(context, null, mockBillingCycleRepository)

    @Test
    fun isEnabled_initialState() {
        val enabled = preference.isEnabled

        assertThat(enabled).isTrue()
    }

    @Test
    fun isEnabled_afterSetTemplate_updated() {
        preference.setTemplate(mock<NetworkTemplate>(), SUB_ID, null)

        val enabled = preference.isEnabled

        assertThat(enabled).isFalse()
    }

    private companion object {
        const val SUB_ID = 1
    }
}
Loading