Note OP_ENABLE_MOBILE_DATA_BY_USER when user enables mobile data

Bug: 222650148
Test: atest PhoneInterfaceManagerTest
Change-Id: Ic123ebe5ddf2d37e7479a8247de5ca9f3165cfce
diff --git a/Android.bp b/Android.bp
index 122015e..fc6853a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,6 +45,7 @@
         "nist-sip",
         "service-entitlement",
         "telephony_flags_core_java_lib",
+        "android.permission.flags-aconfig-java",
     ],
 
     srcs: [
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 6c5e916..adb4203 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -17,6 +17,7 @@
 package com.android.phone;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.permission.flags.Flags.opEnableMobileDataByUser;
 import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
 import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
 
@@ -8824,6 +8825,12 @@
             enforceModifyPermission();
         }
 
+        if (reason == TelephonyManager.DATA_ENABLED_REASON_USER && enabled
+                && null != callingPackage && opEnableMobileDataByUser()) {
+            mAppOps.noteOp(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER, Binder.getCallingUid(),
+                    callingPackage, null, null);
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
             Phone phone = getPhone(subId);
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index e702279..87ce690 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -34,6 +34,8 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.permission.flags.Flags;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.telephony.RadioAccessFamily;
 import android.telephony.TelephonyManager;
 
@@ -47,6 +49,7 @@
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -70,6 +73,8 @@
     @Mock
     private SubscriptionManagerService mSubscriptionManagerService;
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Before
     @UiThreadTest
     public void setUp() throws Exception {
@@ -283,4 +288,72 @@
         mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer,
                 "com.test.package");
     }
+
+    @Test
+    public void notifyEnableDataWithAppOps_enableByUser_doNoteOp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+        String packageName = "INVALID_PACKAGE";
+        String error = "";
+        try {
+            mPhoneInterfaceManager.setDataEnabledForReason(1,
+                    TelephonyManager.DATA_ENABLED_REASON_USER, true, packageName);
+        } catch (SecurityException expected) {
+            // The test doesn't have access to note the op, but we're just interested that it makes
+            // the attempt.
+            error = expected.getMessage();
+        }
+
+        String appop = "ENABLE_MOBILE_DATA_BY_USER";
+        assertTrue("expected error to contain " + packageName + " but it didn't: " + error,
+                error.contains(packageName));
+        assertTrue("expected error to contain " + appop + " but it didn't: " + error,
+                error.contains(appop));
+    }
+
+    @Test
+    public void notifyEnableDataWithAppOps_enableByCarrier_doNotNoteOp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+        String packageName = "INVALID_PACKAGE";
+        String error = "";
+        try {
+            mPhoneInterfaceManager.setDataEnabledForReason(1,
+                    TelephonyManager.DATA_ENABLED_REASON_CARRIER, true, packageName);
+        } catch (SecurityException expected) {
+            // The test doesn't have access to note the op, but we're just interested that it makes
+            // the attempt.
+            error = expected.getMessage();
+        }
+        assertEquals("Expected error to be empty, was " + error, error, "");
+    }
+
+    @Test
+    public void notifyEnableDataWithAppOps_disableByUser_doNotNoteOp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+        String packageName = "INVALID_PACKAGE";
+        String error = "";
+        try {
+            mPhoneInterfaceManager.setDataEnabledForReason(1,
+                    TelephonyManager.DATA_ENABLED_REASON_USER, false, packageName);
+        } catch (SecurityException expected) {
+            // The test doesn't have access to note the op, but we're just interested that it makes
+            // the attempt.
+            error = expected.getMessage();
+        }
+        assertEquals("Expected error to be empty, was " + error, error, "");
+    }
+
+    @Test
+    public void notifyEnableDataWithAppOps_noPackageNameAndEnableByUser_doNotnoteOp() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+        String error = "";
+        try {
+            mPhoneInterfaceManager.setDataEnabledForReason(1,
+                    TelephonyManager.DATA_ENABLED_REASON_USER, false, null);
+        } catch (SecurityException expected) {
+            // The test doesn't have access to note the op, but we're just interested that it makes
+            // the attempt.
+            error = expected.getMessage();
+        }
+        assertEquals("Expected error to be empty, was " + error, error, "");
+    }
 }