From 529c720a797901a475c60ff2fddc3d439672d2aa Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 13 Feb 2023 01:54:26 +0000 Subject: [PATCH] Log when emergency state changes to track location-related AppOps Bug: 262906568 Test: manual test Change-Id: If703872633c9a31857260911091590953cbfe387 --- .../location/LocationManagerService.java | 7 ++++ .../location/injector/EmergencyHelper.java | 41 +++++++++++++++++++ .../server/location/injector/Injector.java | 2 - .../injector/LocationUsageLogger.java | 7 ++++ .../injector/SystemEmergencyHelper.java | 15 +++++++ .../injector/FakeEmergencyHelper.java | 1 + 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index 1cc958b0f5293..fa2ba217a047c 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -296,6 +296,8 @@ public class LocationManagerService extends ILocationManager.Stub implements refreshAppOpsRestrictions(userId); } }); + mInjector.getEmergencyHelper().addOnEmergencyStateChangedListener( + this::onEmergencyStateChanged); // set up passive provider first since it will be required for all other location providers, // which are loaded later once the system is ready. @@ -567,6 +569,11 @@ public class LocationManagerService extends ILocationManager.Stub implements refreshAppOpsRestrictions(userId); } + private void onEmergencyStateChanged() { + boolean isInEmergency = mInjector.getEmergencyHelper().isInEmergency(Long.MIN_VALUE); + mInjector.getLocationUsageLogger().logEmergencyStateChanged(isInEmergency); + } + private void logLocationEnabledState() { boolean locationEnabled = false; // Location setting is considered on if it is enabled for any one user diff --git a/services/core/java/com/android/server/location/injector/EmergencyHelper.java b/services/core/java/com/android/server/location/injector/EmergencyHelper.java index be4bf5083c65b..10cf7143529bd 100644 --- a/services/core/java/com/android/server/location/injector/EmergencyHelper.java +++ b/services/core/java/com/android/server/location/injector/EmergencyHelper.java @@ -16,14 +16,55 @@ package com.android.server.location.injector; +import java.util.concurrent.CopyOnWriteArrayList; + /** * Provides helpers for emergency sessions. */ public abstract class EmergencyHelper { + private final CopyOnWriteArrayList mListeners; + + protected EmergencyHelper() { + mListeners = new CopyOnWriteArrayList<>(); + } + + /** + * Listener for emergency state changes. + */ + public interface EmergencyStateChangedListener { + /** + * Called when state changes. + */ + void onStateChanged(); + } + /** * Returns true if the device is in an emergency session, or if an emergency session ended * within the given extension time. */ public abstract boolean isInEmergency(long extensionTimeMs); + + /** + * Add a listener for changes to the emergency location state. + */ + public void addOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) { + mListeners.add(listener); + } + + /** + * Remove a listener for changes to the emergency location state. + */ + public void removeOnEmergencyStateChangedListener(EmergencyStateChangedListener listener) { + mListeners.remove(listener); + } + + /** + * Notify listeners for emergency state of state change + */ + protected final void dispatchEmergencyStateChanged() { + for (EmergencyStateChangedListener listener : mListeners) { + listener.onStateChanged(); + } + } } diff --git a/services/core/java/com/android/server/location/injector/Injector.java b/services/core/java/com/android/server/location/injector/Injector.java index b2c86721fdcce..4a0c4b2ae9243 100644 --- a/services/core/java/com/android/server/location/injector/Injector.java +++ b/services/core/java/com/android/server/location/injector/Injector.java @@ -16,13 +16,11 @@ package com.android.server.location.injector; -import com.android.internal.annotations.VisibleForTesting; import com.android.server.location.settings.LocationSettings; /** * Injects various location dependencies so that they may be controlled by tests. */ -@VisibleForTesting public interface Injector { /** Returns a UserInfoHelper. */ diff --git a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java index a9701b3bd4193..9319e899e42f0 100644 --- a/services/core/java/com/android/server/location/injector/LocationUsageLogger.java +++ b/services/core/java/com/android/server/location/injector/LocationUsageLogger.java @@ -129,6 +129,13 @@ public class LocationUsageLogger { FrameworkStatsLog.write(FrameworkStatsLog.LOCATION_ENABLED_STATE_CHANGED, enabled); } + /** + * Log emergency location state change event + */ + public synchronized void logEmergencyStateChanged(boolean isInEmergency) { + FrameworkStatsLog.write(FrameworkStatsLog.EMERGENCY_STATE_CHANGED, isInEmergency); + } + private static int bucketizeProvider(String provider) { if (LocationManager.NETWORK_PROVIDER.equals(provider)) { return LocationStatsEnums.PROVIDER_NETWORK; diff --git a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java index 1fb00eff86d78..c772e08b5f9f6 100644 --- a/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java +++ b/services/core/java/com/android/server/location/injector/SystemEmergencyHelper.java @@ -27,6 +27,7 @@ import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.util.Log; +import com.android.internal.telephony.TelephonyIntents; import com.android.server.FgThread; import java.util.Objects; @@ -73,12 +74,25 @@ public class SystemEmergencyHelper extends EmergencyHelper { try { mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber( intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER)); + dispatchEmergencyStateChanged(); } catch (IllegalStateException e) { Log.w(TAG, "Failed to call TelephonyManager.isEmergencyNumber().", e); } } } }, new IntentFilter(Intent.ACTION_NEW_OUTGOING_CALL)); + + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (!TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals( + intent.getAction())) { + return; + } + + dispatchEmergencyStateChanged(); + } + }, new IntentFilter(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)); } @Override @@ -108,6 +122,7 @@ public class SystemEmergencyHelper extends EmergencyHelper { if (mIsInEmergencyCall) { mEmergencyCallEndRealtimeMs = SystemClock.elapsedRealtime(); mIsInEmergencyCall = false; + dispatchEmergencyStateChanged(); } } } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java index 2cf57dafc7d9a..7ee411b437827 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/FakeEmergencyHelper.java @@ -27,6 +27,7 @@ public class FakeEmergencyHelper extends EmergencyHelper { public void setInEmergency(boolean inEmergency) { mInEmergency = inEmergency; + dispatchEmergencyStateChanged(); } @Override