Merge "Update DockObserver to send dock intent after device provisioning" into tm-qpr-dev

This commit is contained in:
Lucas Silva
2022-11-30 00:05:29 +00:00
committed by Android (Google) Code Review
2 changed files with 86 additions and 9 deletions

View File

@@ -19,6 +19,7 @@ package com.android.server;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.database.ContentObserver;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.Ringtone; import android.media.Ringtone;
import android.media.RingtoneManager; import android.media.RingtoneManager;
@@ -73,6 +74,7 @@ final class DockObserver extends SystemService {
private final boolean mAllowTheaterModeWakeFromDock; private final boolean mAllowTheaterModeWakeFromDock;
private final List<ExtconStateConfig> mExtconStateConfigs; private final List<ExtconStateConfig> mExtconStateConfigs;
private DeviceProvisionedObserver mDeviceProvisionedObserver;
static final class ExtconStateProvider { static final class ExtconStateProvider {
private final Map<String, String> mState; private final Map<String, String> mState;
@@ -110,7 +112,7 @@ final class DockObserver extends SystemService {
Slog.w(TAG, "No state file found at: " + stateFilePath); Slog.w(TAG, "No state file found at: " + stateFilePath);
return new ExtconStateProvider(new HashMap<>()); return new ExtconStateProvider(new HashMap<>());
} catch (Exception e) { } catch (Exception e) {
Slog.e(TAG, "" , e); Slog.e(TAG, "", e);
return new ExtconStateProvider(new HashMap<>()); return new ExtconStateProvider(new HashMap<>());
} }
} }
@@ -136,7 +138,7 @@ final class DockObserver extends SystemService {
private static List<ExtconStateConfig> loadExtconStateConfigs(Context context) { private static List<ExtconStateConfig> loadExtconStateConfigs(Context context) {
String[] rows = context.getResources().getStringArray( String[] rows = context.getResources().getStringArray(
com.android.internal.R.array.config_dockExtconStateMapping); com.android.internal.R.array.config_dockExtconStateMapping);
try { try {
ArrayList<ExtconStateConfig> configs = new ArrayList<>(); ArrayList<ExtconStateConfig> configs = new ArrayList<>();
for (String row : rows) { for (String row : rows) {
@@ -167,6 +169,7 @@ final class DockObserver extends SystemService {
com.android.internal.R.bool.config_allowTheaterModeWakeFromDock); com.android.internal.R.bool.config_allowTheaterModeWakeFromDock);
mKeepDreamingWhenUndocking = context.getResources().getBoolean( mKeepDreamingWhenUndocking = context.getResources().getBoolean(
com.android.internal.R.bool.config_keepDreamingWhenUndocking); com.android.internal.R.bool.config_keepDreamingWhenUndocking);
mDeviceProvisionedObserver = new DeviceProvisionedObserver(mHandler);
mExtconStateConfigs = loadExtconStateConfigs(context); mExtconStateConfigs = loadExtconStateConfigs(context);
@@ -199,15 +202,19 @@ final class DockObserver extends SystemService {
if (phase == PHASE_ACTIVITY_MANAGER_READY) { if (phase == PHASE_ACTIVITY_MANAGER_READY) {
synchronized (mLock) { synchronized (mLock) {
mSystemReady = true; mSystemReady = true;
mDeviceProvisionedObserver.onSystemReady();
// don't bother broadcasting undocked here updateIfDockedLocked();
if (mReportedDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
updateLocked();
}
} }
} }
} }
private void updateIfDockedLocked() {
// don't bother broadcasting undocked here
if (mReportedDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
updateLocked();
}
}
private void setActualDockStateLocked(int newState) { private void setActualDockStateLocked(int newState) {
mActualDockState = newState; mActualDockState = newState;
if (!mUpdatesStopped) { if (!mUpdatesStopped) {
@@ -252,8 +259,7 @@ final class DockObserver extends SystemService {
// Skip the dock intent if not yet provisioned. // Skip the dock intent if not yet provisioned.
final ContentResolver cr = getContext().getContentResolver(); final ContentResolver cr = getContext().getContentResolver();
if (Settings.Global.getInt(cr, if (!mDeviceProvisionedObserver.isDeviceProvisioned()) {
Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
Slog.i(TAG, "Device not provisioned, skipping dock broadcast"); Slog.i(TAG, "Device not provisioned, skipping dock broadcast");
return; return;
} }
@@ -419,4 +425,48 @@ final class DockObserver extends SystemService {
} }
} }
} }
private final class DeviceProvisionedObserver extends ContentObserver {
private boolean mRegistered;
public DeviceProvisionedObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
updateRegistration();
if (isDeviceProvisioned()) {
// Send the dock broadcast if device is docked after provisioning.
updateIfDockedLocked();
}
}
}
void onSystemReady() {
updateRegistration();
}
private void updateRegistration() {
boolean register = !isDeviceProvisioned();
if (register == mRegistered) {
return;
}
final ContentResolver resolver = getContext().getContentResolver();
if (register) {
resolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
false, this);
} else {
resolver.unregisterContentObserver(this);
}
mRegistered = register;
}
boolean isDeviceProvisioned() {
return Settings.Global.getInt(getContext().getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
}
} }

View File

@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Intent; import android.content.Intent;
import android.os.Looper; import android.os.Looper;
import android.provider.Settings;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableContext; import android.testing.TestableContext;
import android.testing.TestableLooper; import android.testing.TestableLooper;
@@ -74,6 +75,11 @@ public class DockObserverTest {
.isEqualTo(Intent.EXTRA_DOCK_STATE_UNDOCKED); .isEqualTo(Intent.EXTRA_DOCK_STATE_UNDOCKED);
} }
void setDeviceProvisioned(boolean provisioned) {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
provisioned ? 1 : 0);
}
@Before @Before
public void setUp() { public void setUp() {
if (Looper.myLooper() == null) { if (Looper.myLooper() == null) {
@@ -131,4 +137,25 @@ public class DockObserverTest {
assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY5=5", assertDockEventIntentWithExtraThenUndock(observer, "DOCK=1\nKEY5=5",
Intent.EXTRA_DOCK_STATE_HE_DESK); Intent.EXTRA_DOCK_STATE_HE_DESK);
} }
@Test
public void testDockIntentBroadcast_deviceNotProvisioned()
throws ExecutionException, InterruptedException {
DockObserver observer = new DockObserver(mInterceptingContext);
// Set the device as not provisioned.
setDeviceProvisioned(false);
observer.onBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
BroadcastInterceptingContext.FutureIntent futureIntent =
updateExtconDockState(observer, "DOCK=1");
TestableLooper.get(this).processAllMessages();
// Verify no broadcast was sent as device was not provisioned.
futureIntent.assertNotReceived();
// Ensure we send the broadcast when the device is provisioned.
setDeviceProvisioned(true);
TestableLooper.get(this).processAllMessages();
assertThat(futureIntent.get().getIntExtra(Intent.EXTRA_DOCK_STATE, -1))
.isEqualTo(Intent.EXTRA_DOCK_STATE_DESK);
}
} }