Loading res/xml/mobile_network_settings.xml +1 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ android:title="@string/network_operator_category" settings:controller="com.android.settings.network.telephony.NetworkPreferenceCategoryController"> <SwitchPreferenceCompat <com.android.settings.spa.preference.ComposePreference android:key="auto_select_key" android:title="@string/select_automatically" settings:controller="com.android.settings.network.telephony.gsm.AutoSelectPreferenceController"/> Loading src/com/android/settings/network/helper/LifecycleCallbackAdapter.javadeleted 100644 → 0 +0 −100 Original line number Diff line number Diff line /* * 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.network.helper; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.LifecycleOwner; import java.util.concurrent.atomic.AtomicReference; /** * A {@link androidx.lifecycle.LifecycleObserver} implementation of adapter over callback. * * Which including: * 1. Request to active callback when Lifecycle.State.STARTED * 2. Request to inactive callback when Lifecycle.State.STOPPED * 3. Close (no further resume) when Lifecycle.State.DESTROYED */ @VisibleForTesting abstract class LifecycleCallbackAdapter implements LifecycleEventObserver, AutoCloseable { private static final String TAG = "LifecycleCallbackAdapter"; private AtomicReference<Lifecycle> mLifecycle = new AtomicReference<Lifecycle>(); /** * Constructor * @param lifecycle {@link Lifecycle} to monitor */ @VisibleForTesting protected LifecycleCallbackAdapter(@NonNull Lifecycle lifecycle) { mLifecycle.set(lifecycle); lifecycle.addObserver(this); } /** * Get {@link Lifecycle} under monitor. * @return {@link Lifecycle}. Return {@code null} when closed. */ @VisibleForTesting public Lifecycle getLifecycle() { return mLifecycle.get(); } /** * Check current callback status. * @return true when callback is active. */ public abstract boolean isCallbackActive(); /** * Change callback status. * @param isActive true to active callback, otherwise inactive. */ public abstract void setCallbackActive(boolean isActive); /** * Implementation of LifecycleEventObserver. */ public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mLifecycle.get() == null) { return; } Lifecycle.State state = event.getTargetState(); boolean expectCallbackActive = state.isAtLeast(Lifecycle.State.STARTED); if (expectCallbackActive != isCallbackActive()) { setCallbackActive(expectCallbackActive); } if (state == Lifecycle.State.DESTROYED) { close(); } } /** * Implementation of AutoCloseable. */ @MainThread public void close() { Lifecycle lifecycle = mLifecycle.getAndSet(null); if (lifecycle != null) { lifecycle.removeObserver(this); } } } src/com/android/settings/network/helper/LifecycleCallbackConverter.javadeleted 100644 → 0 +0 −132 Original line number Diff line number Diff line /* * 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.network.helper; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; /** * A {@link LifecycleCallbackAdapter} which support carrying a result from any threads back to UI * thread through {@link #postResult(T)}. * * A {@link Consumer<T>} would be invoked from UI thread for further processing on the result. * * Note: Result not in STARTED or RESUMED stage will be discarded silently. * This is to align with the criteria set within * {@link LifecycleCallbackAdapter#onStateChanged()}. */ @VisibleForTesting public class LifecycleCallbackConverter<T> extends LifecycleCallbackAdapter { private static final String TAG = "LifecycleCallbackConverter"; private final Thread mUiThread; private final Consumer<T> mResultCallback; /** * A record of number of active status change. * Even numbers (0, 2, 4, 6 ...) are inactive status. * Odd numbers (1, 3, 5, 7 ...) are active status. */ private final AtomicLong mNumberOfActiveStatusChange = new AtomicLong(); /** * Constructor * * @param lifecycle {@link Lifecycle} to monitor * @param resultCallback for further processing the result */ @VisibleForTesting @UiThread public LifecycleCallbackConverter( @NonNull Lifecycle lifecycle, @NonNull Consumer<T> resultCallback) { super(lifecycle); mUiThread = Thread.currentThread(); mResultCallback = resultCallback; } /** * Post a result (from any thread) back to UI thread. * * @param result the object ready to be passed back to {@link Consumer<T>}. */ @AnyThread @VisibleForTesting public void postResult(T result) { /** * Since mNumberOfActiveStatusChange only increase, it is a concept of sequence number. * Carry it when sending data in between different threads allow to verify if the data * has arrived on time. And drop the data when expired. */ long currentNumberOfChange = mNumberOfActiveStatusChange.get(); if (Thread.currentThread() == mUiThread) { dispatchExtResult(currentNumberOfChange, result); // Dispatch directly } else { postResultToUiThread(currentNumberOfChange, result); } } @AnyThread protected void postResultToUiThread(long numberOfStatusChange, T result) { ThreadUtils.postOnMainThread(() -> dispatchExtResult(numberOfStatusChange, result)); } @UiThread protected void dispatchExtResult(long numberOfStatusChange, T result) { /** * For a postResult() sending in between different threads, not only create a latency * but also enqueued into main UI thread for dispatch. * * To align behavior within {@link LifecycleCallbackAdapter#onStateChanged()}, * some checking on both numberOfStatusChange and {@link Lifecycle} status are required. */ if (isActiveStatus(numberOfStatusChange) && (numberOfStatusChange == mNumberOfActiveStatusChange.get()) && getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { mResultCallback.accept(result); } } private static final boolean isActiveStatus(long numberOfStatusChange) { return ((numberOfStatusChange & 1L) != 0L); } /* Implementation of LifecycleCallbackAdapter */ @UiThread public boolean isCallbackActive() { return isActiveStatus(mNumberOfActiveStatusChange.get()); } /* Implementation of LifecycleCallbackAdapter */ @UiThread public void setCallbackActive(boolean updatedActiveStatus) { /** * Make sure only increase when active status got changed. * This is to implement the definition of mNumberOfActiveStatusChange. */ if (isCallbackActive() != updatedActiveStatus) { mNumberOfActiveStatusChange.getAndIncrement(); } } } src/com/android/settings/network/helper/LifecycleCallbackIntentReceiver.javadeleted 100644 → 0 +0 −104 Original line number Diff line number Diff line /* * 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.network.helper; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import java.util.function.Consumer; /** * A {@link BroadcastReceiver} for {@link Intent}. * * This is {@link BroadcastReceiver} supported by {@link LifecycleCallbackConverter}, * and only register when state is either START or RESUME. */ @VisibleForTesting public class LifecycleCallbackIntentReceiver extends LifecycleCallbackConverter<Intent> { private static final String TAG = "LifecycleCallbackIntentReceiver"; @VisibleForTesting protected final BroadcastReceiver mReceiver; private final Runnable mRegisterCallback; private final Runnable mUnRegisterCallback; /** * Constructor * @param lifecycle {@link Lifecycle} to monitor * @param context for this BroadcastReceiver * @param filter the IntentFilter for BroadcastReceiver * @param broadcastPermission for permission when listening * @param scheduler for running in background thread * @param resultCallback for the Intent from BroadcastReceiver */ @VisibleForTesting public LifecycleCallbackIntentReceiver(@NonNull Lifecycle lifecycle, @NonNull Context context, @NonNull IntentFilter filter, String broadcastPermission, Handler scheduler, @NonNull Consumer<Intent> resultCallback) { super(lifecycle, resultCallback); // BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { if (isInitialStickyBroadcast()) { return; } final String action = intent.getAction(); if ((action == null) || (action.length() <= 0)) { return; } postResult(intent); } }; // Register operation mRegisterCallback = () -> { Intent initIntent = context.registerReceiver(mReceiver, filter, broadcastPermission, scheduler); if (initIntent != null) { postResult(initIntent); } }; // Un-Register operation mUnRegisterCallback = () -> { context.unregisterReceiver(mReceiver); }; } @Override public void setCallbackActive(boolean isActive) { super.setCallbackActive(isActive); Runnable op = (isActive) ? mRegisterCallback : mUnRegisterCallback; op.run(); } @Override public void close() { super.close(); if (isCallbackActive()) { setCallbackActive(false); } } } src/com/android/settings/network/helper/LifecycleCallbackTelephonyAdapter.javadeleted 100644 → 0 +0 −72 Original line number Diff line number Diff line /* * 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.network.helper; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * A {@link LifecycleCallbackConverter} for supporting the register/unregister work for * {@link TelephonyCallback}. */ @VisibleForTesting public class LifecycleCallbackTelephonyAdapter<T> extends LifecycleCallbackConverter<T> { private static final String TAG = "LifecycleCallbackTelephony"; private final Runnable mRegisterCallback; private final Runnable mUnRegisterCallback; /** * Constructor * @param lifecycle {@link Lifecycle} to monitor * @param telephonyManager {@link TelephonyManager} to interact with * @param telephonyCallback {@link TelephonyCallback} * @param executor {@link Executor} for receiving the notify from telephony framework. * @param resultCallback for the result from {@link TelephonyCallback} */ @VisibleForTesting public LifecycleCallbackTelephonyAdapter(@NonNull Lifecycle lifecycle, @NonNull TelephonyManager telephonyManager, @NonNull TelephonyCallback telephonyCallback, Executor executor, @NonNull Consumer<T> resultCallback) { super(lifecycle, resultCallback); // Register operation mRegisterCallback = () -> { telephonyManager.registerTelephonyCallback(executor, telephonyCallback); }; // Un-Register operation mUnRegisterCallback = () -> { telephonyManager.unregisterTelephonyCallback(telephonyCallback); }; } @Override public void setCallbackActive(boolean isActive) { super.setCallbackActive(isActive); Runnable op = (isActive) ? mRegisterCallback : mUnRegisterCallback; op.run(); } } Loading
res/xml/mobile_network_settings.xml +1 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ android:title="@string/network_operator_category" settings:controller="com.android.settings.network.telephony.NetworkPreferenceCategoryController"> <SwitchPreferenceCompat <com.android.settings.spa.preference.ComposePreference android:key="auto_select_key" android:title="@string/select_automatically" settings:controller="com.android.settings.network.telephony.gsm.AutoSelectPreferenceController"/> Loading
src/com/android/settings/network/helper/LifecycleCallbackAdapter.javadeleted 100644 → 0 +0 −100 Original line number Diff line number Diff line /* * 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.network.helper; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleEventObserver; import androidx.lifecycle.LifecycleOwner; import java.util.concurrent.atomic.AtomicReference; /** * A {@link androidx.lifecycle.LifecycleObserver} implementation of adapter over callback. * * Which including: * 1. Request to active callback when Lifecycle.State.STARTED * 2. Request to inactive callback when Lifecycle.State.STOPPED * 3. Close (no further resume) when Lifecycle.State.DESTROYED */ @VisibleForTesting abstract class LifecycleCallbackAdapter implements LifecycleEventObserver, AutoCloseable { private static final String TAG = "LifecycleCallbackAdapter"; private AtomicReference<Lifecycle> mLifecycle = new AtomicReference<Lifecycle>(); /** * Constructor * @param lifecycle {@link Lifecycle} to monitor */ @VisibleForTesting protected LifecycleCallbackAdapter(@NonNull Lifecycle lifecycle) { mLifecycle.set(lifecycle); lifecycle.addObserver(this); } /** * Get {@link Lifecycle} under monitor. * @return {@link Lifecycle}. Return {@code null} when closed. */ @VisibleForTesting public Lifecycle getLifecycle() { return mLifecycle.get(); } /** * Check current callback status. * @return true when callback is active. */ public abstract boolean isCallbackActive(); /** * Change callback status. * @param isActive true to active callback, otherwise inactive. */ public abstract void setCallbackActive(boolean isActive); /** * Implementation of LifecycleEventObserver. */ public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mLifecycle.get() == null) { return; } Lifecycle.State state = event.getTargetState(); boolean expectCallbackActive = state.isAtLeast(Lifecycle.State.STARTED); if (expectCallbackActive != isCallbackActive()) { setCallbackActive(expectCallbackActive); } if (state == Lifecycle.State.DESTROYED) { close(); } } /** * Implementation of AutoCloseable. */ @MainThread public void close() { Lifecycle lifecycle = mLifecycle.getAndSet(null); if (lifecycle != null) { lifecycle.removeObserver(this); } } }
src/com/android/settings/network/helper/LifecycleCallbackConverter.javadeleted 100644 → 0 +0 −132 Original line number Diff line number Diff line /* * 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.network.helper; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import com.android.settingslib.utils.ThreadUtils; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; /** * A {@link LifecycleCallbackAdapter} which support carrying a result from any threads back to UI * thread through {@link #postResult(T)}. * * A {@link Consumer<T>} would be invoked from UI thread for further processing on the result. * * Note: Result not in STARTED or RESUMED stage will be discarded silently. * This is to align with the criteria set within * {@link LifecycleCallbackAdapter#onStateChanged()}. */ @VisibleForTesting public class LifecycleCallbackConverter<T> extends LifecycleCallbackAdapter { private static final String TAG = "LifecycleCallbackConverter"; private final Thread mUiThread; private final Consumer<T> mResultCallback; /** * A record of number of active status change. * Even numbers (0, 2, 4, 6 ...) are inactive status. * Odd numbers (1, 3, 5, 7 ...) are active status. */ private final AtomicLong mNumberOfActiveStatusChange = new AtomicLong(); /** * Constructor * * @param lifecycle {@link Lifecycle} to monitor * @param resultCallback for further processing the result */ @VisibleForTesting @UiThread public LifecycleCallbackConverter( @NonNull Lifecycle lifecycle, @NonNull Consumer<T> resultCallback) { super(lifecycle); mUiThread = Thread.currentThread(); mResultCallback = resultCallback; } /** * Post a result (from any thread) back to UI thread. * * @param result the object ready to be passed back to {@link Consumer<T>}. */ @AnyThread @VisibleForTesting public void postResult(T result) { /** * Since mNumberOfActiveStatusChange only increase, it is a concept of sequence number. * Carry it when sending data in between different threads allow to verify if the data * has arrived on time. And drop the data when expired. */ long currentNumberOfChange = mNumberOfActiveStatusChange.get(); if (Thread.currentThread() == mUiThread) { dispatchExtResult(currentNumberOfChange, result); // Dispatch directly } else { postResultToUiThread(currentNumberOfChange, result); } } @AnyThread protected void postResultToUiThread(long numberOfStatusChange, T result) { ThreadUtils.postOnMainThread(() -> dispatchExtResult(numberOfStatusChange, result)); } @UiThread protected void dispatchExtResult(long numberOfStatusChange, T result) { /** * For a postResult() sending in between different threads, not only create a latency * but also enqueued into main UI thread for dispatch. * * To align behavior within {@link LifecycleCallbackAdapter#onStateChanged()}, * some checking on both numberOfStatusChange and {@link Lifecycle} status are required. */ if (isActiveStatus(numberOfStatusChange) && (numberOfStatusChange == mNumberOfActiveStatusChange.get()) && getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) { mResultCallback.accept(result); } } private static final boolean isActiveStatus(long numberOfStatusChange) { return ((numberOfStatusChange & 1L) != 0L); } /* Implementation of LifecycleCallbackAdapter */ @UiThread public boolean isCallbackActive() { return isActiveStatus(mNumberOfActiveStatusChange.get()); } /* Implementation of LifecycleCallbackAdapter */ @UiThread public void setCallbackActive(boolean updatedActiveStatus) { /** * Make sure only increase when active status got changed. * This is to implement the definition of mNumberOfActiveStatusChange. */ if (isCallbackActive() != updatedActiveStatus) { mNumberOfActiveStatusChange.getAndIncrement(); } } }
src/com/android/settings/network/helper/LifecycleCallbackIntentReceiver.javadeleted 100644 → 0 +0 −104 Original line number Diff line number Diff line /* * 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.network.helper; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import java.util.function.Consumer; /** * A {@link BroadcastReceiver} for {@link Intent}. * * This is {@link BroadcastReceiver} supported by {@link LifecycleCallbackConverter}, * and only register when state is either START or RESUME. */ @VisibleForTesting public class LifecycleCallbackIntentReceiver extends LifecycleCallbackConverter<Intent> { private static final String TAG = "LifecycleCallbackIntentReceiver"; @VisibleForTesting protected final BroadcastReceiver mReceiver; private final Runnable mRegisterCallback; private final Runnable mUnRegisterCallback; /** * Constructor * @param lifecycle {@link Lifecycle} to monitor * @param context for this BroadcastReceiver * @param filter the IntentFilter for BroadcastReceiver * @param broadcastPermission for permission when listening * @param scheduler for running in background thread * @param resultCallback for the Intent from BroadcastReceiver */ @VisibleForTesting public LifecycleCallbackIntentReceiver(@NonNull Lifecycle lifecycle, @NonNull Context context, @NonNull IntentFilter filter, String broadcastPermission, Handler scheduler, @NonNull Consumer<Intent> resultCallback) { super(lifecycle, resultCallback); // BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { if (isInitialStickyBroadcast()) { return; } final String action = intent.getAction(); if ((action == null) || (action.length() <= 0)) { return; } postResult(intent); } }; // Register operation mRegisterCallback = () -> { Intent initIntent = context.registerReceiver(mReceiver, filter, broadcastPermission, scheduler); if (initIntent != null) { postResult(initIntent); } }; // Un-Register operation mUnRegisterCallback = () -> { context.unregisterReceiver(mReceiver); }; } @Override public void setCallbackActive(boolean isActive) { super.setCallbackActive(isActive); Runnable op = (isActive) ? mRegisterCallback : mUnRegisterCallback; op.run(); } @Override public void close() { super.close(); if (isCallbackActive()) { setCallbackActive(false); } } }
src/com/android/settings/network/helper/LifecycleCallbackTelephonyAdapter.javadeleted 100644 → 0 +0 −72 Original line number Diff line number Diff line /* * 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.network.helper; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; import java.util.concurrent.Executor; import java.util.function.Consumer; /** * A {@link LifecycleCallbackConverter} for supporting the register/unregister work for * {@link TelephonyCallback}. */ @VisibleForTesting public class LifecycleCallbackTelephonyAdapter<T> extends LifecycleCallbackConverter<T> { private static final String TAG = "LifecycleCallbackTelephony"; private final Runnable mRegisterCallback; private final Runnable mUnRegisterCallback; /** * Constructor * @param lifecycle {@link Lifecycle} to monitor * @param telephonyManager {@link TelephonyManager} to interact with * @param telephonyCallback {@link TelephonyCallback} * @param executor {@link Executor} for receiving the notify from telephony framework. * @param resultCallback for the result from {@link TelephonyCallback} */ @VisibleForTesting public LifecycleCallbackTelephonyAdapter(@NonNull Lifecycle lifecycle, @NonNull TelephonyManager telephonyManager, @NonNull TelephonyCallback telephonyCallback, Executor executor, @NonNull Consumer<T> resultCallback) { super(lifecycle, resultCallback); // Register operation mRegisterCallback = () -> { telephonyManager.registerTelephonyCallback(executor, telephonyCallback); }; // Un-Register operation mUnRegisterCallback = () -> { telephonyManager.unregisterTelephonyCallback(telephonyCallback); }; } @Override public void setCallbackActive(boolean isActive) { super.setCallbackActive(isActive); Runnable op = (isActive) ? mRegisterCallback : mUnRegisterCallback; op.run(); } }