Merge "Import translations. DO NOT MERGE ANYWHERE" into tm-d1-dev
diff --git a/src/com/android/settings/network/apn/ApnEditor.java b/src/com/android/settings/network/apn/ApnEditor.java
index 926c77e..bfb4943 100644
--- a/src/com/android/settings/network/apn/ApnEditor.java
+++ b/src/com/android/settings/network/apn/ApnEditor.java
@@ -78,7 +78,8 @@
     private static final String KEY_MVNO_TYPE = "mvno_type";
     private static final String KEY_PASSWORD = "apn_password";
 
-    private static final int MENU_DELETE = Menu.FIRST;
+    @VisibleForTesting
+    static final int MENU_DELETE = Menu.FIRST;
     private static final int MENU_SAVE = Menu.FIRST + 1;
     private static final int MENU_CANCEL = Menu.FIRST + 2;
 
@@ -148,6 +149,17 @@
     String mDefaultApnRoamingProtocol;
     private String[] mReadOnlyApnFields;
     private boolean mReadOnlyApn;
+    /**
+     * The APN deletion feature within menu is aligned with the APN adding feature.
+     * Having only one of them could lead to a UX which not that make sense from user's
+     * perspective.
+     *
+     * mIsAddApnAllowed stores the configuration value reading from
+     * CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL to support the presentation
+     * control of the menu options. When false, delete option would be invisible to
+     * the end user.
+     */
+    private boolean mIsAddApnAllowed;
     private Uri mCarrierUri;
     private boolean mIsCarrierIdApn;
 
@@ -282,7 +294,7 @@
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
 
         initApnEditorUi();
-        getCarrierCustomizedConfig();
+        getCarrierCustomizedConfig(getContext());
 
         Uri uri = null;
         if (action.equals(Intent.ACTION_EDIT)) {
@@ -826,7 +838,8 @@
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
         // If it's a new APN, then cancel will delete the new entry in onPause
-        if (!mNewApn && !mReadOnlyApn) {
+        // If APN add is not allowed, delete might lead to issue regarding recovery
+        if (!mNewApn && !mReadOnlyApn && mIsAddApnAllowed) {
             menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
                 .setIcon(R.drawable.ic_delete);
         }
@@ -1319,13 +1332,15 @@
         mMvnoMatchData = (EditTextPreference) findPreference("mvno_match_data");
     }
 
-    private void getCarrierCustomizedConfig() {
+    @VisibleForTesting
+    protected void getCarrierCustomizedConfig(Context context) {
         mReadOnlyApn = false;
         mReadOnlyApnTypes = null;
         mReadOnlyApnFields = null;
+        mIsAddApnAllowed = true;
 
         final CarrierConfigManager configManager = (CarrierConfigManager)
-                getSystemService(Context.CARRIER_CONFIG_SERVICE);
+            context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         if (configManager != null) {
             final PersistableBundle b = configManager.getConfigForSubId(mSubId);
             if (b != null) {
@@ -1357,6 +1372,11 @@
                     Log.d(TAG, "onCreate: default apn roaming protocol: "
                             + mDefaultApnRoamingProtocol);
                 }
+
+                mIsAddApnAllowed = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
+                if (!mIsAddApnAllowed) {
+                    Log.d(TAG, "onCreate: not allow to add new APN");
+                }
             }
         }
     }
diff --git a/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java
index 0a430cd..f03b6d8 100644
--- a/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/apn/ApnEditorTest.java
@@ -17,14 +17,15 @@
 package com.android.settings.network.apn;
 
 import static com.google.common.truth.Truth.assertThat;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.ContentResolver;
@@ -34,22 +35,21 @@
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
-
 import androidx.fragment.app.FragmentActivity;
 import androidx.preference.EditTextPreference;
 import androidx.preference.ListPreference;
 import androidx.preference.MultiSelectListPreference;
 import androidx.preference.SwitchPreference;
-
 import com.android.settings.R;
 import com.android.settings.network.ProxySubscriptionManager;
 import com.android.settings.network.apn.ApnEditor.ApnData;
 import com.android.settings.testutils.shadow.ShadowFragment;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -103,13 +103,15 @@
     private FragmentActivity mActivity;
     @Mock
     private ProxySubscriptionManager mProxySubscriptionMgr;
-
+    @Mock
+    private CarrierConfigManager mCarrierConfigManager;
     @Captor
     private ArgumentCaptor<Uri> mUriCaptor;
 
     private ApnEditor mApnEditorUT;
     private Context mContext;
     private Resources mResources;
+    private PersistableBundle mBundle = new PersistableBundle();
 
     @Before
     public void setUp() {
@@ -127,6 +129,10 @@
         doReturn(mContext.getTheme()).when(mActivity).getTheme();
         doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
 
+        doReturn(mCarrierConfigManager).when(mContext)
+                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
         setMockPreference(mContext);
         mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
         mApnEditorUT.sNotSet = "Not Set";
@@ -379,6 +385,20 @@
         verify(mApnEditorUT).finish();
     }
 
+    @Test
+    public void testDeleteApnData_shouldNotPresentMenuWhenNotSupportAdding() {
+        mBundle.putBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL, false);
+
+        MenuItem item = Mockito.mock(MenuItem.class);
+        Menu menu = Mockito.mock(Menu.class);
+        doReturn(item).when(menu).add(anyInt(), anyInt(), anyInt(), anyInt());
+
+        mApnEditorUT.getCarrierCustomizedConfig(mContext);
+        mApnEditorUT.onCreateOptionsMenu(menu, null);
+
+        verify(menu, times(0)).add(anyInt(), eq(ApnEditor.MENU_DELETE), anyInt(), anyInt());
+    }
+
     @Test(expected = ClassCastException.class)
     public void testApnData_invalidIntegerType_throwsInvalidTypeException() {
         // GIVEN a ApnData constructed from cursor