1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.datasubscription; 18 19 20 import static com.android.car.datasubscription.DataSubscriptionStatus.PAID; 21 22 import android.content.Context; 23 import android.database.ContentObserver; 24 import android.provider.Settings; 25 26 import androidx.annotation.GuardedBy; 27 28 /** 29 * This class provides a mechanism to indicate if a data plan is provided on a trial vs paid basis. 30 */ 31 public class DataSubscription { 32 public static final String DATA_SUBSCRIPTION_ACTION = 33 "android.intent.action.DATA_SUBSCRIPTION"; 34 private static final String SETTING = "car_data_subscription_status"; 35 private static final int MIN_VALUE = 1; 36 private static final int MAX_VALUE = 3; 37 38 @DataSubscriptionStatus private static final int DEFAULT_VALUE = PAID; 39 40 @GuardedBy("this") 41 private DataSubscriptionChangeListener mDataSubscriptionChangeListener; 42 private final Context mContext; 43 private final ContentObserver mContentObserver = 44 new ContentObserver(/* handler= */ null) { 45 @Override 46 public void onChange(boolean selfChange) { 47 synchronized (DataSubscription.this) { 48 if (mDataSubscriptionChangeListener != null) { 49 mDataSubscriptionChangeListener.onChange(getDataSubscriptionStatus()); 50 } 51 } 52 } 53 }; 54 DataSubscription(Context context)55 public DataSubscription(Context context) { 56 mContext = context; 57 58 } 59 60 /** Returns the data subscription status of the vehicle. */ 61 @DataSubscriptionStatus getDataSubscriptionStatus()62 public int getDataSubscriptionStatus() { 63 int subscriptionStatus = 64 Settings.Global.getInt(mContext.getContentResolver(), SETTING, DEFAULT_VALUE); 65 return (subscriptionStatus < MIN_VALUE || subscriptionStatus > MAX_VALUE) 66 ? DEFAULT_VALUE 67 : subscriptionStatus; 68 } 69 70 /** 71 * Registers a listener to data subscription status change updates. Supports registering 72 * only one listener. Throws IllegalStateException if a listeners is already registered. 73 */ addDataSubscriptionListener(DataSubscriptionChangeListener listener)74 public synchronized void addDataSubscriptionListener(DataSubscriptionChangeListener listener) { 75 if (mDataSubscriptionChangeListener != null) { 76 throw new IllegalStateException( 77 "A listener is already registered. Multiple listeners are not supported."); 78 } 79 mDataSubscriptionChangeListener = listener; 80 mContext 81 .getContentResolver() 82 .registerContentObserver( 83 Settings.Global.getUriFor(SETTING), 84 /* notifyForDescendants= */ false, 85 mContentObserver); 86 } 87 88 /** 89 * Unregisters the listener for data subscription status change updates. This method must be 90 * called after registering a listener to avoid memory leaks. Throws IllegalStateException if no 91 * listener is registered. 92 */ removeDataSubscriptionListener()93 public synchronized void removeDataSubscriptionListener() { 94 if (mDataSubscriptionChangeListener == null) { 95 throw new IllegalStateException("No listener is registered."); 96 } 97 mContext.getContentResolver().unregisterContentObserver(mContentObserver); 98 mDataSubscriptionChangeListener = null; 99 } 100 101 /** 102 * Checks if the data subscription status is inactive 103 */ isDataSubscriptionInactive()104 public boolean isDataSubscriptionInactive() { 105 return getDataSubscriptionStatus() == DataSubscriptionStatus.INACTIVE; 106 } 107 108 /** 109 * Interface to implement for listening to Data Subscription status changes. 110 */ 111 public interface DataSubscriptionChangeListener { 112 /** 113 * Receive the Data Subscription status changes. 114 */ onChange(@ataSubscriptionStatus int value)115 void onChange(@DataSubscriptionStatus int value); 116 } 117 } 118