Merge "Fix NPE when starting advertising with null GATT"
diff --git a/Android.bp b/Android.bp
index 75fd2e6..2e3073f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -735,22 +735,24 @@
     name: "framework-javastream-protos",
     depfile: true,
 
+    tool_files: [ "tools/genprotos.sh", ],
     tools: [
         "aprotoc",
         "protoc-gen-javastream",
         "soong_zip",
     ],
 
-    cmd: "mkdir -p $(genDir)/$(in) " +
-        "&& $(location aprotoc) " +
-        "  --plugin=$(location protoc-gen-javastream) " +
-        "  --dependency_out=$(depfile) " +
-        "  --javastream_out=$(genDir)/$(in) " +
-        "  -Iexternal/protobuf/src " +
-        "  -I . " +
-        "  $(in) " +
-        "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
-
+    // TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can
+    // end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to
+    // the way sbox rewrites the command. See b/70221552.
+    cmd: "$(location tools/genprotos.sh) " +
+              " $(location aprotoc) " +
+              " $(location protoc-gen-javastream) " +
+              " $(location soong_zip) " +
+              " $(genDir) " +
+              " $(depfile) " +
+              " $(in) " +
+              " $(out)",
     srcs: [
         "core/proto/**/*.proto",
         "libs/incident/**/*.proto",
diff --git a/api/test-current.txt b/api/test-current.txt
index e34614e..4c3c0f8 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -215,6 +215,14 @@
 
 }
 
+package android.bluetooth {
+
+  public final class BluetoothClass implements android.os.Parcelable {
+    method public int getClassOfDevice();
+  }
+
+}
+
 package android.content {
 
   public abstract class ContentResolver {
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 8557f38..3a78cbd 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -16,6 +16,7 @@
 
 package android.bluetooth;
 
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -293,6 +294,7 @@
      *
      * @hide
      */
+    @TestApi
     public int getClassOfDevice() {
         return mClass;
     }
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
index 2773da5..94441ca 100644
--- a/core/java/android/os/SELinux.java
+++ b/core/java/android/os/SELinux.java
@@ -18,9 +18,9 @@
 
 import android.util.Slog;
 
-import java.io.IOException;
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.IOException;
 
 /**
  * This class provides access to the centralized jni bindings for
@@ -79,6 +79,13 @@
     public static final native String getPeerContext(FileDescriptor fd);
 
     /**
+     * Get the security context of a file descriptor of a file.
+     * @param fd FileDescriptor of a file.
+     * @return a String representing the file descriptor security context.
+     */
+    public static final native String getFileContext(FileDescriptor fd);
+
+    /**
      * Gets the security context of the current process.
      * @return a String representing the security context of the current process.
      */
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index a6b29c5..061011b 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -31,6 +31,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -1031,6 +1032,10 @@
         try {
             ParcelFileDescriptor pfd = service.getStatisticsStream();
             if (pfd != null) {
+                if (false) {
+                    Log.d(TAG, "selinux context: "
+                            + SELinux.getFileContext(pfd.getFileDescriptor()));
+                }
                 try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
                     byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
                     Parcel parcel = Parcel.obtain();
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 6778b29..8cb1078 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -60,6 +60,41 @@
     return (security_getenforce() == 1) ? true : false;
 }
 
+static jstring getFdConInner(JNIEnv *env, jobject fileDescriptor, bool isSocket) {
+    if (isSELinuxDisabled) {
+        return NULL;
+    }
+
+    if (fileDescriptor == NULL) {
+        jniThrowNullPointerException(env,
+                "Trying to check security context of a null FileDescriptor.");
+        return NULL;
+    }
+
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (env->ExceptionCheck()) {
+        ALOGE("getFdCon => getFD for %p failed", fileDescriptor);
+        return NULL;
+    }
+
+    security_context_t tmp = NULL;
+    int ret;
+    if (isSocket) {
+        ret = getpeercon(fd, &tmp);
+    } else{
+        ret = fgetfilecon(fd, &tmp);
+    }
+    Unique_SecurityContext context(tmp);
+
+    ScopedLocalRef<jstring> contextStr(env, NULL);
+    if (ret != -1) {
+        contextStr.reset(env->NewStringUTF(context.get()));
+    }
+
+    ALOGV("getFdCon(%d) => %s", fd, context.get());
+    return contextStr.release();
+}
+
 /*
  * Function: getPeerCon
  * Purpose: retrieves security context of peer socket
@@ -69,33 +104,19 @@
  * Exceptions: NullPointerException if fileDescriptor object is NULL
  */
 static jstring getPeerCon(JNIEnv *env, jobject, jobject fileDescriptor) {
-    if (isSELinuxDisabled) {
-        return NULL;
-    }
+    return getFdConInner(env, fileDescriptor, true);
+}
 
-    if (fileDescriptor == NULL) {
-        jniThrowNullPointerException(env,
-                "Trying to check security context of a null peer socket.");
-        return NULL;
-    }
-
-    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (env->ExceptionCheck()) {
-        ALOGE("getPeerCon => getFD for %p failed", fileDescriptor);
-        return NULL;
-    }
-
-    security_context_t tmp = NULL;
-    int ret = getpeercon(fd, &tmp);
-    Unique_SecurityContext context(tmp);
-
-    ScopedLocalRef<jstring> contextStr(env, NULL);
-    if (ret != -1) {
-        contextStr.reset(env->NewStringUTF(context.get()));
-    }
-
-    ALOGV("getPeerCon(%d) => %s", fd, context.get());
-    return contextStr.release();
+/*
+ * Function: getFdCon
+ * Purpose: retrieves security context of a file descriptor.
+ * Parameters:
+ *        fileDescriptor: a FileDescriptor object
+ * Returns: jstring representing the security_context of socket or NULL if error
+ * Exceptions: NullPointerException if fileDescriptor object is NULL
+ */
+static jstring getFdCon(JNIEnv *env, jobject, jobject fileDescriptor) {
+    return getFdConInner(env, fileDescriptor, false);
 }
 
 /*
@@ -326,6 +347,7 @@
     { "getContext"               , "()Ljava/lang/String;"                         , (void*)getCon           },
     { "getFileContext"           , "(Ljava/lang/String;)Ljava/lang/String;"       , (void*)getFileCon       },
     { "getPeerContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon       },
+    { "getFileContext"           , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getFdCon         },
     { "getPidContext"            , "(I)Ljava/lang/String;"                        , (void*)getPidCon        },
     { "isSELinuxEnforced"        , "()Z"                                          , (void*)isSELinuxEnforced},
     { "isSELinuxEnabled"         , "()Z"                                          , (void*)isSELinuxEnabled },
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index ccbf483..0064e77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -162,7 +162,7 @@
         mMobileRoaming.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
         mMobileRoamingSpace.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
         mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
-        mOut.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
+        mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE);
         mInoutContainer.setVisibility((mState.activityIn || mState.activityOut)
                 ? View.VISIBLE : View.GONE);
     }
@@ -188,7 +188,7 @@
         mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
         mMobileRoamingSpace.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
         mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
-        mOut.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
+        mOut.setVisibility(state.activityOut ? View.VISIBLE : View.GONE);
         mInoutContainer.setVisibility((state.activityIn || state.activityOut)
                 ? View.VISIBLE : View.GONE);
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index cd9efdc..9eb9ab9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2418,30 +2418,30 @@
 
     private int doWriteSplit(int sessionId, String inPath, long sizeBytes, String splitName,
             boolean logSuccess) throws RemoteException {
-        final PrintWriter pw = getOutPrintWriter();
-        final ParcelFileDescriptor fd;
-        if (STDIN_PATH.equals(inPath)) {
-            fd = new ParcelFileDescriptor(getInFileDescriptor());
-        } else if (inPath != null) {
-            fd = openFileForSystem(inPath, "r");
-            if (fd == null) {
-                return -1;
-            }
-            sizeBytes = fd.getStatSize();
-            if (sizeBytes < 0) {
-                getErrPrintWriter().println("Unable to get size of: " + inPath);
-                return -1;
-            }
-        } else {
-            fd = new ParcelFileDescriptor(getInFileDescriptor());
-        }
-        if (sizeBytes <= 0) {
-            getErrPrintWriter().println("Error: must specify a APK size");
-            return 1;
-        }
-
         PackageInstaller.Session session = null;
         try {
+            final PrintWriter pw = getOutPrintWriter();
+            final ParcelFileDescriptor fd;
+            if (STDIN_PATH.equals(inPath)) {
+                fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+            } else if (inPath != null) {
+                fd = openFileForSystem(inPath, "r");
+                if (fd == null) {
+                    return -1;
+                }
+                sizeBytes = fd.getStatSize();
+                if (sizeBytes < 0) {
+                    getErrPrintWriter().println("Unable to get size of: " + inPath);
+                    return -1;
+                }
+            } else {
+                fd = ParcelFileDescriptor.dup(getInFileDescriptor());
+            }
+            if (sizeBytes <= 0) {
+                getErrPrintWriter().println("Error: must specify a APK size");
+                return 1;
+            }
+
             session = new PackageInstaller.Session(
                     mInterface.getPackageInstaller().openSession(sessionId));
             session.write(splitName, 0, sizeBytes, fd);
diff --git a/tools/genprotos.sh b/tools/genprotos.sh
new file mode 100755
index 0000000..f901c9f
--- /dev/null
+++ b/tools/genprotos.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# TODO This should not be needed. If you set a custom OUT_DIR or OUT_DIR_COMMON_BASE you can
+# end up with a command that is extremely long, potentially going passed MAX_ARG_STRLEN due to
+# the way sbox rewrites the command. See b/70221552.
+
+set -e
+
+location_aprotoc=$1
+location_protoc=$2
+location_soong_zip=$3
+genDir=$4
+depfile=$5
+in=$6
+out=$7
+
+mkdir -p ${genDir}/${in} && \
+  ${location_aprotoc} --plugin=${location_protoc} \
+                      --dependency_out=${depfile} \
+                      --javastream_out=${genDir}/${in} \
+                      -Iexternal/protobuf/src \
+                      -I . \
+                      ${in} && \
+  ${location_soong_zip} -jar -o ${out} -C ${genDir}/${in} -D ${genDir}/${in}