Limit access to package names in brightness slider data.

Only allow access to package names if the calling package
has PACKAGE_USAGE_STATS.

Bug: 69405990
Test: runtest -c com.android.server.display.BrightnessTrackerTest frameworks-services
Change-Id: I1c924d408a7c74620b9aa9d672c99a6424bb85ca
diff --git a/core/java/android/hardware/display/BrightnessChangeEvent.java b/core/java/android/hardware/display/BrightnessChangeEvent.java
index fe24e32..3003607 100644
--- a/core/java/android/hardware/display/BrightnessChangeEvent.java
+++ b/core/java/android/hardware/display/BrightnessChangeEvent.java
@@ -21,6 +21,8 @@
 
 /**
  * Data about a brightness settings change.
+ *
+ * {@see DisplayManager.getBrightnessEvents()}
  * TODO make this SystemAPI
  * @hide
  */
@@ -31,7 +33,9 @@
     /** Timestamp of the change {@see System.currentTimeMillis()} */
     public long timeStamp;
 
-    /** Package name of focused activity when brightness was changed. */
+    /** Package name of focused activity when brightness was changed.
+     *  This will be null if the caller of {@see DisplayManager.getBrightnessEvents()}
+     *  does not have access to usage stats {@see UsageStatsManager} */
     public String packageName;
 
     /** User id of of the user running when brightness was changed.
@@ -59,6 +63,20 @@
     public BrightnessChangeEvent() {
     }
 
+    /** @hide */
+    public BrightnessChangeEvent(BrightnessChangeEvent other) {
+        this.brightness = other.brightness;
+        this.timeStamp = other.timeStamp;
+        this.packageName = other.packageName;
+        this.userId = other.userId;
+        this.luxValues = other.luxValues;
+        this.luxTimestamps = other.luxTimestamps;
+        this.batteryLevel = other.batteryLevel;
+        this.nightMode = other.nightMode;
+        this.colorTemperature = other.colorTemperature;
+        this.lastBrightness = other.lastBrightness;
+    }
+
     private BrightnessChangeEvent(Parcel source) {
         brightness = source.readInt();
         timeStamp = source.readLong();
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 8935745..97ca231 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -16,8 +16,10 @@
 
 package android.hardware.display;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.app.KeyguardManager;
@@ -619,8 +621,9 @@
      * Fetch {@link BrightnessChangeEvent}s.
      * @hide until we make it a system api.
      */
+    @RequiresPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE)
     public List<BrightnessChangeEvent> getBrightnessEvents() {
-        return mGlobal.getBrightnessEvents();
+        return mGlobal.getBrightnessEvents(mContext.getOpPackageName());
     }
 
     /**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index d93d0e4..c3f82f5 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -462,9 +462,10 @@
     /**
      * Retrieves brightness change events.
      */
-    public List<BrightnessChangeEvent> getBrightnessEvents() {
+    public List<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
         try {
-            ParceledListSlice<BrightnessChangeEvent> events = mDm.getBrightnessEvents();
+            ParceledListSlice<BrightnessChangeEvent> events =
+                    mDm.getBrightnessEvents(callingPackage);
             if (events == null) {
                 return Collections.emptyList();
             }
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b796cf9..f2ed9e7 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -84,7 +84,7 @@
     Point getStableDisplaySize();
 
     // Requires BRIGHTNESS_SLIDER_USAGE permission.
-    ParceledListSlice getBrightnessEvents();
+    ParceledListSlice getBrightnessEvents(String callingPackage);
 
     // STOPSHIP remove when adaptive brightness code is updated to accept curves.
     // Requires BRIGHTNESS_SLIDER_USAGE permission.
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 2c6fe94..61b6fa0 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -196,9 +196,10 @@
 
     /**
      * @param userId userId to fetch data for.
+     * @param includePackage if false we will null out BrightnessChangeEvent.packageName
      * @return List of recent {@link BrightnessChangeEvent}s
      */
-    public ParceledListSlice<BrightnessChangeEvent> getEvents(int userId) {
+    public ParceledListSlice<BrightnessChangeEvent> getEvents(int userId, boolean includePackage) {
         // TODO include apps from any managed profiles in the brightness information.
         BrightnessChangeEvent[] events;
         synchronized (mEventsLock) {
@@ -207,7 +208,13 @@
         ArrayList<BrightnessChangeEvent> out = new ArrayList<>(events.length);
         for (int i = 0; i < events.length; ++i) {
             if (events[i].userId == userId) {
-                out.add(events[i]);
+                if (includePackage) {
+                    out.add(events[i]);
+                } else {
+                    BrightnessChangeEvent event = new BrightnessChangeEvent((events[i]));
+                    event.packageName = null;
+                    out.add(event);
+                }
             }
         }
         return new ParceledListSlice<>(out);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 379aaad..19a74d7 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -29,6 +29,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
@@ -1752,14 +1753,30 @@
         }
 
         @Override // Binder call
-        public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents() {
+        public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(String callingPackage) {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.BRIGHTNESS_SLIDER_USAGE,
                     "Permission to read brightness events.");
-            int userId = UserHandle.getUserId(Binder.getCallingUid());
+
+            final int callingUid = Binder.getCallingUid();
+            AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+            final int mode = appOpsManager.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
+                    callingUid, callingPackage);
+            final boolean hasUsageStats;
+            if (mode == AppOpsManager.MODE_DEFAULT) {
+                // The default behavior here is to check if PackageManager has given the app
+                // permission.
+                hasUsageStats = mContext.checkCallingPermission(
+                        Manifest.permission.PACKAGE_USAGE_STATS)
+                        == PackageManager.PERMISSION_GRANTED;
+            } else {
+                hasUsageStats = mode == AppOpsManager.MODE_ALLOWED;
+            }
+
+            final int userId = UserHandle.getUserId(callingUid);
             final long token = Binder.clearCallingIdentity();
             try {
-                return mBrightnessTracker.getEvents(userId);
+                return mBrightnessTracker.getEvents(userId, hasUsageStats);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 6a1d268..926009e 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -134,7 +134,7 @@
         mInjector.incrementTime(TimeUnit.SECONDS.toMillis(2));
         mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                 Settings.System.SCREEN_BRIGHTNESS));
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         mTracker.stop();
 
         assertEquals(1, events.size());
@@ -169,7 +169,9 @@
         final long sensorTime = mInjector.currentTimeMillis();
         mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                 Settings.System.SCREEN_BRIGHTNESS));
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> eventsNoPackage
+                = mTracker.getEvents(0, false).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         mTracker.stop();
 
         assertEquals(1, events.size());
@@ -184,6 +186,9 @@
         assertEquals(3333, event.colorTemperature);
         assertEquals("a.package", event.packageName);
         assertEquals(0, event.userId);
+
+        assertEquals(1, eventsNoPackage.size());
+        assertNull(eventsNoPackage.get(0).packageName);
     }
 
     @Test
@@ -200,7 +205,7 @@
                 (int) mInjector.mSystemIntSettings.get(Settings.System.SCREEN_BRIGHTNESS));
         mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                 Settings.System.SCREEN_BRIGHTNESS));
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         // No events because we filtered out our change.
         assertEquals(0, events.size());
 
@@ -217,7 +222,7 @@
                 secondUserUpdateBrightness);
         mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                 Settings.System.SCREEN_BRIGHTNESS));
-        events = mTracker.getEvents(0).getList();
+        events = mTracker.getEvents(0, true).getList();
 
         assertEquals(2, events.size());
         // First event is change from system update (20) to first user update (20)
@@ -242,7 +247,7 @@
             mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                     Settings.System.SCREEN_BRIGHTNESS));
         }
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         mTracker.stop();
 
         // Should be capped at 100 events, and they should be the most recent 100.
@@ -266,7 +271,7 @@
         }
         mInjector.mSettingsObserver.onChange(false, Settings.System.getUriFor(
                 Settings.System.SCREEN_BRIGHTNESS));
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         mTracker.stop();
 
         assertEquals(1, events.size());
@@ -317,7 +322,7 @@
                 + Long.toString(twoMonthsAgo) + "," + Long.toString(twoMonthsAgo) + "\"/>"
                 + "</events>";
         tracker.readEventsLocked(getInputStream(eventFile));
-        List<BrightnessChangeEvent> events = tracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = tracker.getEvents(0, true).getList();
         assertEquals(1, events.size());
         BrightnessChangeEvent event = events.get(0);
         assertEquals(someTimeAgo, event.timeStamp);
@@ -330,7 +335,7 @@
         assertEquals(1.0f, event.batteryLevel, 0.01);
         assertEquals("com.example.app", event.packageName);
 
-        events = tracker.getEvents(1).getList();
+        events = tracker.getEvents(1, true).getList();
         assertEquals(1, events.size());
         event = events.get(0);
         assertEquals(someTimeAgo, event.timeStamp);
@@ -359,7 +364,7 @@
         } catch (IOException e) {
             // Expected;
         }
-        assertEquals(0, tracker.getEvents(0).getList().size());
+        assertEquals(0, tracker.getEvents(0, true).getList().size());
 
         // Missing lux value.
         eventFile =
@@ -374,7 +379,7 @@
         } catch (IOException e) {
             // Expected;
         }
-        assertEquals(0, tracker.getEvents(0).getList().size());
+        assertEquals(0, tracker.getEvents(0, true).getList().size());
     }
 
     @Test
@@ -405,7 +410,7 @@
         BrightnessTracker tracker = new BrightnessTracker(InstrumentationRegistry.getContext(),
                 mInjector);
         tracker.readEventsLocked(input);
-        List<BrightnessChangeEvent> events = tracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = tracker.getEvents(0, true).getList();
 
         assertEquals(1, events.size());
         BrightnessChangeEvent event = events.get(0);
@@ -442,12 +447,12 @@
                 Settings.System.SCREEN_BRIGHTNESS));
         final long eventTime = mInjector.currentTimeMillis();
 
-        List<BrightnessChangeEvent> events = mTracker.getEvents(0).getList();
+        List<BrightnessChangeEvent> events = mTracker.getEvents(0, true).getList();
         assertEquals(2, events.size());
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         mTracker.writeEventsLocked(baos);
-        events = mTracker.getEvents(0).getList();
+        events = mTracker.getEvents(0, true).getList();
         mTracker.stop();
 
         assertEquals(1, events.size());