Merge "Add SMS over IMS APIs"
diff --git a/Android.mk b/Android.mk
index c61227f..825d192 100644
--- a/Android.mk
+++ b/Android.mk
@@ -525,11 +525,13 @@
 	telephony/java/com/android/ims/internal/IImsService.aidl \
 	telephony/java/com/android/ims/internal/IImsServiceController.aidl \
 	telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl \
+        telephony/java/com/android/ims/internal/IImsSmsFeature.aidl \
 	telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \
 	telephony/java/com/android/ims/internal/IImsUt.aidl \
 	telephony/java/com/android/ims/internal/IImsUtListener.aidl \
 	telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl \
 	telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl \
+        telephony/java/com/android/ims/internal/ISmsListener.aidl \
         telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl \
         telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl \
         telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl \
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 062858d..ca4a210 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -188,6 +188,11 @@
     }
 
     /**
+     * Called when the feature is ready to use.
+     */
+    public abstract void onFeatureReady();
+
+    /**
      * Called when the feature is being removed and must be cleaned up.
      */
     public abstract void onFeatureRemoved();
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index e790d14..4e095e3a 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -346,6 +346,11 @@
         return null;
     }
 
+    @Override
+    public void onFeatureReady() {
+
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index a82e608..40c5181 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -36,6 +36,11 @@
     }
 
     @Override
+    public void onFeatureReady() {
+
+    }
+
+    @Override
     public void onFeatureRemoved() {
 
     }
diff --git a/telephony/java/android/telephony/ims/feature/SmsFeature.java b/telephony/java/android/telephony/ims/feature/SmsFeature.java
new file mode 100644
index 0000000..c1366db
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/SmsFeature.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telephony.ims.feature;
+
+import android.annotation.SystemApi;
+import android.os.RemoteException;
+import com.android.ims.internal.IImsSmsFeature;
+import com.android.ims.internal.ISmsListener;
+
+/**
+ * Base implementation of SMS over IMS functionality.
+ *
+ * @hide
+ */
+public class SmsFeature extends ImsFeature {
+  /**
+   * SMS over IMS format is 3gpp.
+   */
+  public static final int IMS_SMS_FORMAT_3GPP = 1;
+
+  /**
+   * SMS over IMS format is 3gpp2.
+   */
+  public static final int IMS_SMS_FORMAT_3GPP2 = 2;
+
+  /**
+   * Message was sent successfully.
+   */
+  public static final int SEND_STATUS_OK = 1;
+
+  /**
+   * IMS provider failed to send the message and platform should not retry falling back to sending
+   * the message using the radio.
+   */
+  public static final int SEND_STATUS_ERROR = 2;
+
+  /**
+   * IMS provider failed to send the message and platform should retry again after setting TP-RD bit
+   * to high.
+   */
+  public static final int SEND_STATUS_ERROR_RETRY = 3;
+
+  /**
+   * IMS provider failed to send the message and platform should retry falling back to sending
+   * the message using the radio.
+   */
+  public static final int SEND_STATUS_ERROR_FALLBACK = 4;
+
+  /**
+   * Message was delivered successfully.
+   */
+  public static final int DELIVER_STATUS_OK = 1;
+
+  /**
+   * Message was not delivered.
+   */
+  public static final int DELIVER_STATUS_ERROR = 2;
+
+  // Lock for feature synchronization
+  private final Object mLock = new Object();
+  private ISmsListener mSmsListener;
+
+  private final IImsSmsFeature mIImsSmsBinder = new IImsSmsFeature.Stub() {
+    @Override
+    public void registerSmsListener(ISmsListener listener) {
+      synchronized (mLock) {
+        SmsFeature.this.registerSmsListener(listener);
+      }
+    }
+
+    @Override
+    public void sendSms(int format, int messageRef, boolean retry, byte[] pdu) {
+      synchronized (mLock) {
+        SmsFeature.this.sendSms(format, messageRef, retry, pdu);
+      }
+    }
+
+    @Override
+    public void acknowledgeSms(int messageRef, int result) {
+      synchronized (mLock) {
+        SmsFeature.this.acknowledgeSms(messageRef, result);
+      }
+    }
+
+    @Override
+    public int getSmsFormat() {
+      synchronized (mLock) {
+        return SmsFeature.this.getSmsFormat();
+      }
+    }
+  };
+
+  /**
+   * Registers a listener responsible for handling tasks like delivering messages.
+
+   * @param listener listener to register.
+   *
+   * @hide
+   */
+  @SystemApi
+  public final void registerSmsListener(ISmsListener listener) {
+    synchronized (mLock) {
+      mSmsListener = listener;
+    }
+  }
+
+  /**
+   * This method will be triggered by the platform when the user attempts to send an SMS. This
+   * method should be implemented by the IMS providers to provide implementation of sending an SMS
+   * over IMS.
+   *
+   * @param format the format of the message. One of {@link #IMS_SMS_FORMAT_3GPP} or
+   *                {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param messageRef the message reference.
+   * @param retry whether it is a retry of an already attempted message or not.
+   * @param pdu PDUs representing the contents of the message.
+   */
+  public void sendSms(int format, int messageRef, boolean isRetry, byte[] pdu) {
+  }
+
+  /**
+   * This method will be triggered by the platform after {@link #deliverSms(int, byte[])} has been
+   * called to deliver the result to the IMS provider. It will also be triggered after
+   * {@link #setSentSmsResult(int, int)} has been called to provide the result of the operation.
+   *
+   * @param result Should be {@link #DELIVER_STATUS_OK} if the message was delivered successfully,
+   * {@link #DELIVER_STATUS_ERROR} otherwise.
+   * @param messageRef the message reference.
+   */
+  public void acknowledgeSms(int messageRef, int result) {
+
+  }
+
+  /**
+   * This method should be triggered by the IMS providers when there is an incoming message. The
+   * platform will deliver the message to the messages database and notify the IMS provider of the
+   * result by calling {@link #acknowledgeSms(int)}.
+   *
+   * This method must not be called before {@link #onFeatureReady()} is called.
+   *
+   * @param format the format of the message.One of {@link #IMS_SMS_FORMAT_3GPP} or
+   *                {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param pdu PDUs representing the contents of the message.
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void deliverSms(int format, byte[] pdu) throws IllegalStateException {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.deliverSms(format, pdu);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * This method should be triggered by the IMS providers to pass the result of the sent message
+   * to the platform.
+   *
+   * This method must not be called before {@link #onFeatureReady()} is called.
+   *
+   * @param messageRef the message reference.
+   * @param result One of {@link #SEND_STATUS_OK}, {@link #SEND_STATUS_ERROR},
+   *                {@link #SEND_STATUS_ERROR_RETRY}, {@link #SEND_STATUS_ERROR_FALLBACK}
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void setSentSmsResult(int messageRef, int result) throws IllegalStateException {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.setSentSmsResult(messageRef, result);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * Sets the status report of the sent message.
+   *
+   * @param format Should be {@link #IMS_SMS_FORMAT_3GPP} or {@link #IMS_SMS_FORMAT_3GPP2}
+   * @param pdu PDUs representing the content of the status report.
+   * @throws IllegalStateException if called before {@link #onFeatureReady()}
+   */
+  public final void setSentSmsStatusReport(int format, byte[] pdu) {
+    // TODO: Guard against NPE/ Check if feature is ready and thrown an exception
+    // otherwise.
+    try {
+      mSmsListener.setSentSmsStatusReport(format, pdu);
+    } catch (RemoteException e) {
+    }
+  }
+
+  /**
+   * Returns the SMS format. Default is {@link #IMS_SMS_FORMAT_3GPP} unless overridden by IMS
+   * Provider.
+   *
+   * @return sms format.
+   */
+  public int getSmsFormat() {
+    return IMS_SMS_FORMAT_3GPP;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void onFeatureReady() {
+
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void onFeatureRemoved() {
+
+  }
+
+  /**
+   * @hide
+   */
+  @Override
+  public final IImsSmsFeature getBinder() {
+    return mIImsSmsBinder;
+  }
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl b/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl
new file mode 100644
index 0000000..5068128
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsSmsFeature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ims.internal;
+
+import com.android.ims.internal.ISmsListener;
+
+/**
+ * See SmsFeature for more information.
+ *
+ * {@hide}
+ */
+interface IImsSmsFeature {
+    void registerSmsListener(in ISmsListener listener);
+    void sendSms(in int format, in int messageRef, in boolean retry, in byte[] pdu);
+    void acknowledgeSms(in int messageRef, in int result);
+    int getSmsFormat();
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/ims/internal/ISmsListener.aidl b/telephony/java/com/android/ims/internal/ISmsListener.aidl
new file mode 100644
index 0000000..1266f04
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/ISmsListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ims.internal;
+
+/**
+ * See SmsFeature for more information.
+ * {@hide}
+ */
+interface ISmsListener {
+    void setSentSmsResult(in int messageRef, in int result);
+    void setSentSmsStatusReport(in int format, in byte[] pdu);
+    void deliverSms(in int format, in byte[] pdu);
+}
\ No newline at end of file