Support Gba Api

Added api to support generic authentication architecture, and the test
application

Bug: 154865133
Test: atest cts/tests/tests/telephony/current/src/android/telephony/gba/cts/
Test: manual by GbaTestApp
Merged-In: Ib82637056e7daa451c644bb7a33ed308707b6b53
Change-Id: Ib82637056e7daa451c644bb7a33ed308707b6b53
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 4910884..cee57a2 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -77,6 +77,7 @@
 import android.telephony.CellInfoWcdma;
 import android.telephony.ClientRequestStats;
 import android.telephony.DataThrottlingRequest;
+import android.telephony.IBootstrapAuthenticationCallback;
 import android.telephony.ICellInfoCallback;
 import android.telephony.IccOpenLogicalChannelResponse;
 import android.telephony.LocationAccessPolicy;
@@ -102,6 +103,8 @@
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
+import android.telephony.gba.GbaAuthRequest;
+import android.telephony.gba.UaSecurityProtocolIdentifier;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.RegistrationManager;
@@ -132,6 +135,7 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DefaultPhoneNotifier;
+import com.android.internal.telephony.GbaManager;
 import com.android.internal.telephony.HalVersion;
 import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.ICallForwardingInfoCallback;
@@ -9137,6 +9141,44 @@
         }
     }
 
+    @Override
+    public void bootstrapAuthenticationRequest(int subId, int appType, Uri nafUrl,
+            UaSecurityProtocolIdentifier securityProtocol,
+            boolean forceBootStrapping, IBootstrapAuthenticationCallback callback)
+            throws RemoteException {
+        enforceModifyPermission();
+        if (DBG) {
+            log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
+                    + appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
+                    + ", forceBootStrapping:" + forceBootStrapping + ", callback:" + callback);
+        }
+
+        if (!SubscriptionManager.isValidSubscriptionId(subId)
+                || appType < TelephonyManager.APPTYPE_UNKNOWN
+                || appType > TelephonyManager.APPTYPE_ISIM
+                || nafUrl == null || securityProtocol == null || callback == null) {
+            Log.d(LOG_TAG, "bootstrapAuthenticationRequest failed due to invalid parameters");
+            if (callback != null) {
+                try {
+                    callback.onAuthenticationFailure(
+                            0, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED);
+                } catch (RemoteException exception) {
+                    log("Fail to notify onAuthenticationFailure due to " + exception);
+                }
+                return;
+            }
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            getGbaManager(subId).bootstrapAuthenticationRequest(
+                    new GbaAuthRequest(subId, appType, nafUrl, securityProtocol.toByteArray(),
+                    forceBootStrapping, callback));
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     /**
      * Attempts to set the radio power state for thermal reason. This does not guarantee that the
      * requested radio power state will actually be set. See {@link
@@ -9289,4 +9331,88 @@
 
         return thermalMitigationResult;
     }
+
+    /**
+     * Set the GbaService Package Name that Telephony will bind to.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @param packageName The name of the package to be replaced with.
+     * @return true if setting the GbaService to bind to succeeded, false if it did not.
+     */
+    @Override
+    public boolean setBoundGbaServiceOverride(int subId, String packageName) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).overrideServicePackage(packageName);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Return the package name of the currently bound GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @return the package name of the GbaService configuration, null if GBA is not supported.
+     */
+    @Override
+    public String getBoundGbaService(int subId) {
+        enforceReadPrivilegedPermission("getBoundGbaServicePackage");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).getServicePackage();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Set the release time for telephony to unbind GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @param interval The release time to unbind GbaService by millisecond.
+     * @return true if setting the GbaService to bind to succeeded, false if it did not.
+     */
+    @Override
+    public boolean setGbaReleaseTimeOverride(int subId, int interval) {
+        enforceModifyPermission();
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).overrideReleaseTime(interval);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Return the release time for telephony to unbind GbaService.
+     *
+     * @param subId The sim that the GbaService is associated with.
+     * @return The release time to unbind GbaService by millisecond.
+     */
+    @Override
+    public int getGbaReleaseTime(int subId) {
+        enforceReadPrivilegedPermission("getGbaReleaseTime");
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getGbaManager(subId).getReleaseTime();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    private GbaManager getGbaManager(int subId) {
+        GbaManager instance = GbaManager.getInstance(subId);
+        if (instance == null) {
+            String packageName = mApp.getResources().getString(R.string.config_gba_package);
+            int releaseTime = mApp.getResources().getInteger(R.integer.config_gba_release_time);
+            instance = GbaManager.make(mApp, subId, packageName, releaseTime);
+        }
+        return instance;
+    }
 }
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 33d0721..8d67092 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -81,6 +81,12 @@
     private static final String CC_SET_VALUE = "set-value";
     private static final String CC_CLEAR_VALUES = "clear-values";
 
+    private static final String GBA_SUBCOMMAND = "gba";
+    private static final String GBA_SET_SERVICE = "set-service";
+    private static final String GBA_GET_SERVICE = "get-service";
+    private static final String GBA_SET_RELEASE_TIME = "set-release";
+    private static final String GBA_GET_RELEASE_TIME = "get-release";
+
     // Take advantage of existing methods that already contain permissions checks when possible.
     private final ITelephony mInterface;
 
@@ -161,6 +167,8 @@
                 return handleDataTestModeCommand();
             case END_BLOCK_SUPPRESSION:
                 return handleEndBlockSuppressionCommand();
+            case GBA_SUBCOMMAND:
+                return handleGbaCommand();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -183,11 +191,14 @@
         pw.println("    Data Test Mode Commands.");
         pw.println("  cc");
         pw.println("    Carrier Config Commands.");
+        pw.println("  gba");
+        pw.println("    GBA Commands.");
         onHelpIms();
         onHelpEmergencyNumber();
         onHelpEndBlockSupperssion();
         onHelpDataTestMode();
         onHelpCc();
+        onHelpGba();
     }
 
     private void onHelpIms() {
@@ -293,6 +304,32 @@
         pw.println("          is specified, it will choose the default voice SIM slot.");
     }
 
+    private void onHelpGba() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("Gba Commands:");
+        pw.println("  gba set-service [-s SLOT_ID] PACKAGE_NAME");
+        pw.println("    Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba get-service [-s SLOT_ID]");
+        pw.println("    Gets the package name of the currently defined GbaService.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba set-release [-s SLOT_ID] n");
+        pw.println("    Sets the time to release/unbind GbaService in n milli-second.");
+        pw.println("    Do not release/unbind if n is -1.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+        pw.println("  gba get-release [-s SLOT_ID]");
+        pw.println("    Gets the time to release/unbind GbaService in n milli-sencond.");
+        pw.println("    Options are:");
+        pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
+        pw.println("          is specified, it will choose the default voice SIM slot.");
+    }
+
     private int handleImsCommand() {
         String arg = getNextArg();
         if (arg == null) {
@@ -1246,4 +1283,139 @@
         }
         return 0;
     }
+
+    private int handleGbaCommand() {
+        String arg = getNextArg();
+        if (arg == null) {
+            onHelpGba();
+            return 0;
+        }
+
+        switch (arg) {
+            case GBA_SET_SERVICE: {
+                return handleGbaSetServiceCommand();
+            }
+            case GBA_GET_SERVICE: {
+                return handleGbaGetServiceCommand();
+            }
+            case GBA_SET_RELEASE_TIME: {
+                return handleGbaSetReleaseCommand();
+            }
+            case GBA_GET_RELEASE_TIME: {
+                return handleGbaGetReleaseCommand();
+            }
+        }
+
+        return -1;
+    }
+
+    private int getSubId(String cmd) {
+        int slotId = getDefaultSlot();
+        String opt = getNextOption();
+        if (opt != null && opt.equals("-s")) {
+            try {
+                slotId = Integer.parseInt(getNextArgRequired());
+            } catch (NumberFormatException e) {
+                getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+            }
+        }
+        int[] subIds = SubscriptionManager.getSubId(slotId);
+        return subIds[0];
+    }
+
+    private int handleGbaSetServiceCommand() {
+        int subId = getSubId("gba set-service");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String packageName = getNextArg();
+        try {
+            if (packageName == null) {
+                packageName = "";
+            }
+            boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
+            if (VDBG) {
+                Log.v(LOG_TAG, "gba set-service -s " + subId + " "
+                        + packageName + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "gba set-service " + subId + " "
+                    + packageName + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleGbaGetServiceCommand() {
+        String result;
+
+        int subId = getSubId("gba get-service");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        try {
+            result = mInterface.getBoundGbaService(subId);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
+
+    private int handleGbaSetReleaseCommand() {
+        //the release time value could be -1
+        int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
+                : SubscriptionManager.getDefaultSubscriptionId();
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        String intervalStr = getNextArg();
+        if (intervalStr == null) {
+            return -1;
+        }
+
+        try {
+            int interval = Integer.parseInt(intervalStr);
+            boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
+            if (VDBG) {
+                Log.v(LOG_TAG, "gba set-release -s " + subId + " "
+                        + intervalStr + ", result=" + result);
+            }
+            getOutPrintWriter().println(result);
+        } catch (NumberFormatException | RemoteException e) {
+            Log.w(LOG_TAG, "gba set-release -s " + subId + " "
+                    + intervalStr + ", error" + e.getMessage());
+            getErrPrintWriter().println("Exception: " + e.getMessage());
+            return -1;
+        }
+        return 0;
+    }
+
+    private int handleGbaGetReleaseCommand() {
+        int subId = getSubId("gba get-release");
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            return -1;
+        }
+
+        int result = 0;
+        try {
+            result = mInterface.getGbaReleaseTime(subId);
+        } catch (RemoteException e) {
+            return -1;
+        }
+        if (VDBG) {
+            Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
+        }
+        getOutPrintWriter().println(result);
+        return 0;
+    }
 }