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());