Merge "Adopt prev preferred APN on APN reset"
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index c01c327..dd4a25c 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -487,6 +487,16 @@
                 if (preferredDataProfile != null) {
                     // Save the carrier specified preferred data profile into database
                     setPreferredDataProfile(preferredDataProfile);
+                } else {
+                    preferredDataProfile = mAllDataProfiles.stream()
+                            .filter(dp -> areDataProfileSharingApn(dp, mPreferredDataProfile))
+                            .findFirst()
+                            .orElse(null);
+                    if (preferredDataProfile != null) {
+                        log("updatePreferredDataProfile: preferredDB is empty and no carrier "
+                                + "default configured, setting preferred to be prev preferred DP.");
+                        setPreferredDataProfile(preferredDataProfile);
+                    }
                 }
             }
         } else {
@@ -702,13 +712,14 @@
     }
 
     /**
-     * Check if the data profile is the preferred data profile.
+     * Check if the data profile is essentially the preferred data profile. The non-essential
+     * elements include e.g.APN Id.
      *
      * @param dataProfile The data profile to check.
-     * @return {@code true} if the data profile is the preferred data profile.
+     * @return {@code true} if the data profile is essentially the preferred data profile.
      */
     public boolean isDataProfilePreferred(@NonNull DataProfile dataProfile) {
-        return dataProfile.equals(mPreferredDataProfile);
+        return areDataProfileSharingApn(dataProfile, mPreferredDataProfile);
     }
 
     /**
@@ -935,9 +946,19 @@
 
         // Only check the APN from the profile is compatible or not.
         return mAllDataProfiles.stream()
-                .filter(dp -> dp.getApnSetting() != null)
-                .anyMatch(dp -> dp.getApnSetting().equals(dataProfile.getApnSetting(),
-                        mPhone.getServiceState().getDataRoamingFromRegistration()));
+                .anyMatch(dp -> areDataProfileSharingApn(dataProfile, dp));
+    }
+
+    /**
+     * @return {@code true} if both data profiles' APN setting are non-null and essentially the same
+     * (non-essential elements include e.g.APN Id).
+     */
+    private boolean areDataProfileSharingApn(@Nullable DataProfile a, @Nullable DataProfile b) {
+        return a != null
+                && b != null
+                && a.getApnSetting() != null
+                && a.getApnSetting().equals(b.getApnSetting(),
+                mPhone.getServiceState().getDataRoamingFromRegistration());
     }
 
     /**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 157f62b..d9d436b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -65,8 +65,10 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @RunWith(AndroidTestingRunner.class)
@@ -303,6 +305,8 @@
                 }
         );
 
+        private Set<Object> mDeletedApns = new HashSet<>();
+
         @Override
         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                 String sortOrder) {
@@ -324,7 +328,9 @@
                     MatrixCursor mc = new MatrixCursor(APN_COLUMNS);
                     if (mSimInserted) {
                         for (Object apnSetting : mAllApnSettings) {
-                            mc.addRow((Object[]) apnSetting);
+                            if (!mDeletedApns.contains(apnSetting)) {
+                                mc.addRow((Object[]) apnSetting);
+                            }
                         }
                     }
                     return mc;
@@ -339,11 +345,13 @@
                 return mc;
             } else if (uri.isPathPrefixMatch(Telephony.Carriers.PREFERRED_APN_URI)) {
                 for (Object apnSetting : mAllApnSettings) {
-                    int id = (int) ((Object[]) apnSetting)[0];
-                    if (id == mPreferredApnId) {
-                        MatrixCursor mc = new MatrixCursor(APN_COLUMNS);
-                        mc.addRow((Object[]) apnSetting);
-                        return mc;
+                    if (!mDeletedApns.contains(apnSetting)) {
+                        int id = (int) ((Object[]) apnSetting)[0];
+                        if (id == mPreferredApnId) {
+                            MatrixCursor mc = new MatrixCursor(APN_COLUMNS);
+                            mc.addRow((Object[]) apnSetting);
+                            return mc;
+                        }
                     }
                 }
             }
@@ -381,6 +389,21 @@
             }
             return null;
         }
+
+        public boolean removeApnByApnId(int apnId) {
+            for (Object apnSetting : mAllApnSettings) {
+                int id = (int) ((Object[]) apnSetting)[0];
+                if (apnId == id) {
+                    mDeletedApns.add(apnSetting);
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public void restoreApnSettings() {
+            mDeletedApns.clear();
+        }
     }
 
     /**
@@ -877,9 +900,22 @@
         mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
         processAllMessages();
 
+        // preferred APN should set to be the prev preferred
+        assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isTrue();
+        assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+
+        //APN reset and removed GENERAL_PURPOSE_APN(as if user created) from APN DB
+        mPreferredApnId = -1;
+        mApnSettingContentProvider.removeApnByApnId(1);
+        mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+        processAllMessages();
+
         // There should be no preferred APN after APN reset
         assertThat(mDataProfileManagerUT.isAnyPreferredDataProfileExisting()).isFalse();
         assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isFalse();
+
+        // restore mApnSettingContentProvider
+        mApnSettingContentProvider.restoreApnSettings();
     }
 
     @Test