Bluetooth: Use content observer for airplane mode
am: 400279def2

Change-Id: I16d88bbe5e0326223b74903804ee1f40d367035d
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index c44cdb2..30af60e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -62,6 +62,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -293,7 +294,7 @@
 
     @Override
     public boolean isPermissionReviewModeEnabled() {
-        return mContext.getResources().getBoolean(
+        return Build.PERMISSIONS_REVIEW_REQUIRED || mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_permissionReviewRequired);
     }
 
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 3fc3aaf..f1fa76a 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -205,6 +205,10 @@
     if (type == CursorWindow::FIELD_TYPE_BLOB || type == CursorWindow::FIELD_TYPE_STRING) {
         size_t size;
         const void* value = window->getFieldSlotValueBlob(fieldSlot, &size);
+        if (!value) {
+            throw_sqlite3_exception(env, "Native could not read blob slot");
+            return NULL;
+        }
         jbyteArray byteArray = env->NewByteArray(size);
         if (!byteArray) {
             env->ExceptionClear();
@@ -240,6 +244,10 @@
     if (type == CursorWindow::FIELD_TYPE_STRING) {
         size_t sizeIncludingNull;
         const char* value = window->getFieldSlotValueString(fieldSlot, &sizeIncludingNull);
+        if (!value) {
+            throw_sqlite3_exception(env, "Native could not read string slot");
+            return NULL;
+        }
         if (sizeIncludingNull <= 1) {
             return gEmptyString;
         }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4d2dee5..e81bec9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -212,6 +212,7 @@
     <protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
     <protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
     <protected-broadcast android:name="android.btopp.intent.action.ACCEPT" />
+    <protected-broadcast android:name="android.btopp.intent.action.DECLINE" />
     <protected-broadcast android:name="com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
     <protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index fbcb62a..3c529ba 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -1398,7 +1398,7 @@
             return VerifyCredentialResponse.OK;
         }
 
-        if (TextUtils.isEmpty(credential)) {
+        if (storedHash == null || TextUtils.isEmpty(credential)) {
             return VerifyCredentialResponse.ERROR;
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index df7c660..43a5eba 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2533,7 +2533,6 @@
         final int userId = ActivityManager.handleIncomingUser(callingPid,
                 callingUid, incomingUserId, true, false, "enqueueNotification", pkg);
         final UserHandle user = new UserHandle(userId);
-
         // Fix the notification as best we can.
         try {
             final ApplicationInfo ai = getContext().getPackageManager().getApplicationInfoAsUser(
@@ -2547,13 +2546,16 @@
 
         mUsageStats.registerEnqueuedByApp(pkg);
 
-
         if (pkg == null || notification == null) {
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
+
+        // The system can post notifications for any package, let us resolve that.
+        final int notificationUid = resolveNotificationUid(opPkg, callingUid, userId);
+
         final StatusBarNotification n = new StatusBarNotification(
-                pkg, opPkg, id, tag, callingUid, callingPid, 0, notification,
+                pkg, opPkg, id, tag, notificationUid, callingPid, 0, notification,
                 user);
 
         // Limit the number of notifications that any given package except the android
@@ -2623,6 +2625,19 @@
         idOut[0] = id;
     }
 
+    private int resolveNotificationUid(String opPackageName, int callingUid, int userId) {
+        // The system can post notifications on behalf of any package it wants
+        if (isCallerSystem() && opPackageName != null && !"android".equals(opPackageName)) {
+            try {
+                return getContext().getPackageManager()
+                        .getPackageUidAsUser(opPackageName, userId);
+            } catch (NameNotFoundException e) {
+                /* ignore */
+            }
+        }
+        return callingUid;
+    }
+
     private class EnqueueNotificationRunnable implements Runnable {
         private final NotificationRecord r;
         private final int userId;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4b064b8..2652347 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15174,6 +15174,20 @@
                                     + perm.info.name + "; ignoring new declaration");
                             pkg.permissions.remove(i);
                         }
+                    } else if (!PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) {
+                        // Prevent apps to change protection level to dangerous from any other
+                        // type as this would allow a privilege escalation where an app adds a
+                        // normal/signature permission in other app's group and later redefines
+                        // it as dangerous leading to the group auto-grant.
+                        if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                                == PermissionInfo.PROTECTION_DANGEROUS) {
+                            if (bp != null && !bp.isRuntime()) {
+                                Slog.w(TAG, "Package " + pkg.packageName + " trying to change a "
+                                        + "non-runtime permission " + perm.info.name
+                                        + " to runtime; keeping old protection level");
+                                perm.info.protectionLevel = bp.protectionLevel;
+                            }
+                        }
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java
index cf05e9f..ee9c5bf 100644
--- a/services/core/java/com/android/server/storage/AppCollector.java
+++ b/services/core/java/com/android/server/storage/AppCollector.java
@@ -16,6 +16,7 @@
 
 package com.android.server.storage;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageStatsObserver;
@@ -32,6 +33,7 @@
 import android.os.storage.VolumeInfo;
 import android.util.Log;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,7 +58,9 @@
      * @param context Android context used to get
      * @param volume Volume to check for apps.
      */
-    public AppCollector(Context context, VolumeInfo volume) {
+    public AppCollector(Context context, @NonNull VolumeInfo volume) {
+        Preconditions.checkNotNull(volume);
+
         mBackgroundHandler = new BackgroundHandler(BackgroundThread.get().getLooper(),
                 volume,
                 context.getPackageManager(),
@@ -117,7 +121,7 @@
         private final PackageManager mPm;
         private final UserManager mUm;
 
-        BackgroundHandler(Looper looper, VolumeInfo volume, PackageManager pm, UserManager um) {
+        BackgroundHandler(Looper looper, @NonNull VolumeInfo volume, PackageManager pm, UserManager um) {
             super(looper);
             mVolume = volume;
             mPm = pm;
diff --git a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
index 7c43162..4035ade 100644
--- a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
+++ b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
@@ -29,6 +29,7 @@
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.UserHandle;
+import android.os.storage.VolumeInfo;
 import android.provider.Settings;
 import android.util.Log;
 
@@ -61,10 +62,16 @@
             return false;
         }
 
+
+        VolumeInfo volume = getPackageManager().getPrimaryStorageCurrentVolume();
+        // volume is null if the primary storage is not yet mounted.
+        if (volume == null) {
+            return false;
+        }
+        AppCollector collector = new AppCollector(this, volume);
+
         final int userId = UserHandle.myUserId();
         UserEnvironment environment = new UserEnvironment(userId);
-        AppCollector collector = new AppCollector(this,
-                getPackageManager().getPrimaryStorageCurrentVolume());
         LogRunnable task = new LogRunnable();
         task.setRootDirectory(environment.getExternalStorageDirectory());
         task.setDownloadsDirectory(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e3b6ecc..65a42ae 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3809,7 +3809,12 @@
 
     private boolean isActivePasswordSufficientForUserLocked(
             DevicePolicyData policy, int userHandle, boolean parent) {
-        enforceUserUnlocked(userHandle, parent);
+        final long id = Binder.clearCallingIdentity();
+        try {
+            enforceUserUnlocked(userHandle, parent);
+        } finally {
+            Binder.restoreCallingIdentity(id);
+        }
 
         final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
         if (policy.mActivePasswordQuality < requiredPasswordQuality) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f0d5549..d79773d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -157,12 +157,8 @@
             "com.android.server.search.SearchManagerService$Lifecycle";
     private static final String THERMAL_OBSERVER_CLASS =
             "com.google.android.clockwork.ThermalObserver";
-    private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
-            "com.google.android.clockwork.bluetooth.WearBluetoothService";
-    private static final String WEAR_WIFI_MEDIATOR_SERVICE_CLASS =
-            "com.google.android.clockwork.wifi.WearWifiMediatorService";
-    private static final String WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS =
-            "com.google.android.clockwork.cellular.WearCellularMediatorService";
+    private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
+            "com.google.android.clockwork.connectivity.WearConnectivityService";
     private static final String WEAR_TIME_SERVICE_CLASS =
             "com.google.android.clockwork.time.WearTimeService";
     private static final String ACCOUNT_SERVICE_CLASS =
@@ -1192,11 +1188,7 @@
         }
 
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
-            mSystemServiceManager.startService(WEAR_BLUETOOTH_SERVICE_CLASS);
-            mSystemServiceManager.startService(WEAR_WIFI_MEDIATOR_SERVICE_CLASS);
-            if (SystemProperties.getBoolean("config.enable_cellmediator", false)) {
-                mSystemServiceManager.startService(WEAR_CELLULAR_MEDIATOR_SERVICE_CLASS);
-            }
+            mSystemServiceManager.startService(WEAR_CONNECTIVITY_SERVICE_CLASS);
           if (!disableNonCoreServices) {
               mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
           }
diff --git a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
index da22e77..29185e9 100644
--- a/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/storage/AppCollectorTest.java
@@ -187,10 +187,14 @@
         }).start();
         latch.await();
 
-        // This should
         assertThat(myStats).containsAllOf(stats, otherStats);
     }
 
+    @Test(expected=NullPointerException.class)
+    public void testNullVolumeShouldCauseNPE() throws Exception {
+        AppCollector collector = new AppCollector(mContext, null);
+    }
+
     private void addApplication(String packageName, String uuid) {
         ApplicationInfo info = new ApplicationInfo();
         info.packageName = packageName;