diff options
14 files changed, 185 insertions, 70 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 6a02b6b2e6e7..bda80390a614 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -256,6 +256,15 @@ public final class DisplayManager { */ public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6; + /** + * Virtual display flag: Indicates that the orientation of this display device is coupled to + * the rotation of its associated logical display. + * + * @see #createVirtualDisplay + * @hide + */ + public static final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7; + /** @hide */ public DisplayManager(Context context) { mContext = context; diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 72023ce058a5..1614efbd6b65 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3052,6 +3052,8 @@ <java-symbol type="drawable" name="stat_sys_vitals" /> + <java-symbol type="color" name="text_color_primary" /> + <java-symbol type="array" name="config_batteryPackageTypeSystem" /> <java-symbol type="array" name="config_batteryPackageTypeService" /> <java-symbol type="bool" name="config_showAreaUpdateInfoSettings" /> diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java index d8bebabf0c5e..12f75bb2d56c 100644 --- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java +++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java @@ -29,10 +29,8 @@ import android.graphics.Rect; import android.graphics.Typeface; import android.os.PowerManager; import android.os.SystemClock; -import android.os.UserHandle; import android.provider.Settings; import android.text.InputType; -import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; @@ -252,9 +250,9 @@ public class PasswordTextView extends View { mText = mText.substring(0, length - 1); CharState charState = mTextChars.get(length - 1); charState.startRemoveAnimation(0, 0); + sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } userActivity(); - sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0); } public String getText() { diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java index 6397eb5d756b..61325400846a 100644 --- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java +++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java @@ -98,9 +98,13 @@ public class RoundedCorners extends SystemUI implements Tunable { TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING, padding, FLAG_END); - FragmentHostManager.get(sb.getNavigationBarWindow()).addTagListener( + View navigationBarWindow = sb.getNavigationBarWindow(); + // Not all devices have on screen navigation bars. + if (navigationBarWindow != null) { + FragmentHostManager.get(navigationBarWindow).addTagListener( NavigationBarFragment.TAG, new TunablePaddingTagListener(padding, 0)); + } FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar); fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java index 5a163d4d56c2..f8591247f1d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java @@ -417,7 +417,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl @Override public void onHeightUpdate() { - if (mParent == null || mMenuItems.size() == 0) { + if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) { return; } int parentHeight = mParent.getCollapsedHeight(); @@ -477,7 +477,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl private void setMenuLocation() { boolean showOnLeft = mTranslation > 0; - if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping + if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mMenuContainer == null || !mMenuContainer.isAttachedToWindow()) { // Do nothing return; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 419aefe3e9e9..754c34486954 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -61,11 +61,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, public static final float GRADIENT_SCRIM_ALPHA = 0.45f; // A scrim varies its opacity based on a busyness factor, for example // how many notifications are currently visible. - public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.90f; + public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.70f; protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA; protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f; - private static final float SCRIM_IN_FRONT_ALPHA = GRADIENT_SCRIM_ALPHA; - private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA; + private static final float SCRIM_IN_FRONT_ALPHA = GRADIENT_SCRIM_ALPHA_BUSY; + private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA_BUSY; private static final int TAG_KEY_ANIM = R.id.scrim; private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target; private static final int TAG_START_ALPHA = R.id.scrim_alpha_start; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java index 630da2e7eabc..2a2acabc8cee 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java @@ -57,4 +57,10 @@ public class NotificationMenuRowTest extends LeakCheckedTest { row.createMenu(null, null); assertTrue(row.getMenuView() != null); } + + @Test + public void testResetUncreatedMenu() { + NotificationMenuRowPlugin row = new NotificationMenuRow(mContext); + row.resetMenu(); + } } diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 702cbbed17de..f9e4d946a178 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -29,6 +29,8 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import com.android.internal.util.ArrayUtils; + import java.io.PrintWriter; import java.text.DateFormat; import java.util.ArrayList; @@ -67,6 +69,12 @@ public final class PlaybackActivityMonitor .createIfNeeded() .build(); + // TODO support VolumeShaper on those players + private static final int[] UNDUCKABLE_PLAYER_TYPES = { + AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO, + AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL, + }; + // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp private static final VolumeShaper.Operation PLAY_SKIP_RAMP = new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build(); @@ -298,12 +306,12 @@ public final class PlaybackActivityMonitor + " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid() + " - SPEECH"); return false; - } else if (apc.getPlayerType() - == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) { - // TODO support ducking of SoundPool players + } else if (ArrayUtils.contains(UNDUCKABLE_PLAYER_TYPES, apc.getPlayerType())) { Log.v(TAG, "not ducking player " + apc.getPlayerInterfaceId() + " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid() - + " - SoundPool"); + + " due to type:" + + AudioPlaybackConfiguration.toLogFriendlyPlayerType( + apc.getPlayerType())); return false; } apcsToDuck.add(apc); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 8129f450a85b..ab3aff99937d 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -1221,6 +1221,18 @@ public final class DisplayManagerService extends SystemService { } } + @VisibleForTesting + DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) { + synchronized (mSyncRoot) { + LogicalDisplay display = mLogicalDisplays.get(displayId); + if (display != null) { + DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); + return displayDevice.getDisplayDeviceInfoLocked(); + } + return null; + } + } + private final class DisplayManagerHandler extends Handler { public DisplayManagerHandler(Looper looper) { super(looper, null, true /*async*/); diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 9d3021af1ac2..d6ab88813f4d 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -23,6 +23,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESE import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT; import android.content.Context; import android.hardware.display.IVirtualDisplayCallback; @@ -359,6 +360,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter { if ((mFlags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; } + if ((mFlags & VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; + } + mInfo.type = Display.TYPE_VIRTUAL; mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ? DisplayDeviceInfo.TOUCH_NONE : DisplayDeviceInfo.TOUCH_VIRTUAL; diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index fe2c5bd87df4..c1e820c9b787 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -142,6 +142,7 @@ public class LockSettingsService extends ILockSettings.Stub { private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1; // Order of holding lock: mSeparateChallengeLock -> mSpManager -> this + // Do not call into ActivityManager while holding mSpManager lock. private final Object mSeparateChallengeLock = new Object(); private final DeviceProvisionedObserver mDeviceProvisionedObserver = @@ -1434,16 +1435,14 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.e(TAG, "FRP credential can only be verified prior to provisioning."); return VerifyCredentialResponse.ERROR; } - synchronized (mSpManager) { - if (isSyntheticPasswordBasedCredentialLocked(userId)) { - VerifyCredentialResponse response = spBasedDoVerifyCredentialLocked(credential, - credentialType, hasChallenge, challenge, userId, progressCallback); - if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { - mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); - } - return response; - } + VerifyCredentialResponse response = null; + response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge, + userId, progressCallback); + // The user employs synthetic password based credential. + if (response != null) { + return response; } + final CredentialHash storedHash; if (userId == USER_FRP) { PersistentData data = mStorage.readPersistentDataBlock(); @@ -1472,7 +1471,7 @@ public class LockSettingsService extends ILockSettings.Stub { credentialToVerify = credential; } - VerifyCredentialResponse response = verifyCredential(userId, storedHash, credentialToVerify, + response = verifyCredential(userId, storedHash, credentialToVerify, hasChallenge, challenge, progressCallback); if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { @@ -1995,33 +1994,46 @@ public class LockSettingsService extends ILockSettings.Stub { setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM); } - private VerifyCredentialResponse spBasedDoVerifyCredentialLocked(String userCredential, int + private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int credentialType, boolean hasChallenge, long challenge, int userId, ICheckCredentialProgressCallback progressCallback) throws RemoteException { - if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredentialLocked: user=" + userId); + if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId); if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { userCredential = null; } - if (userId == USER_FRP) { - return mSpManager.verifyFrpCredential(getGateKeeperService(), - userCredential, credentialType, progressCallback); - } - long handle = getSyntheticPasswordHandleLocked(userId); - AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( - getGateKeeperService(), handle, userCredential, userId); + final AuthenticationResult authResult; + VerifyCredentialResponse response; + synchronized (mSpManager) { + if (!isSyntheticPasswordBasedCredentialLocked(userId)) { + return null; + } + if (userId == USER_FRP) { + return mSpManager.verifyFrpCredential(getGateKeeperService(), + userCredential, credentialType, progressCallback); + } - VerifyCredentialResponse response = authResult.gkResponse; - if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + long handle = getSyntheticPasswordHandleLocked(userId); + authResult = mSpManager.unwrapPasswordBasedSyntheticPassword( + getGateKeeperService(), handle, userCredential, userId); + + response = authResult.gkResponse; // credential has matched - // perform verifyChallenge with synthetic password which generates the real auth - // token for the current user - response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, - challenge, userId); - if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { - Slog.wtf(TAG, "verifyChallenge with SP failed."); - return VerifyCredentialResponse.ERROR; + if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { + // perform verifyChallenge with synthetic password which generates the real GK auth + // token and response for the current user + response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken, + challenge, userId); + if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { + // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't + // match the recorded GK password handle. + Slog.wtf(TAG, "verifyChallenge with SP failed."); + return VerifyCredentialResponse.ERROR; + } } + } + + if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { if (progressCallback != null) { progressCallback.onCredentialVerified(); } @@ -2032,12 +2044,14 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length); unlockUser(userId, null, secret); + activateEscrowTokens(authResult.authToken, userId); + if (isManagedProfileWithSeparatedLock(userId)) { TrustManager trustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE); trustManager.setDeviceLockedForUser(userId, false); } - activateEscrowTokens(authResult.authToken, userId); + mStrongAuth.reportSuccessfulStrongAuthUnlock(userId); } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) { if (response.getTimeout() > 0) { requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId); @@ -2184,8 +2198,8 @@ public class LockSettingsService extends ILockSettings.Stub { private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException { if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId); - disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); synchronized (mSpManager) { + disableEscrowTokenOnNonManagedDevicesIfNeeded(userId); for (long handle : mSpManager.getPendingTokensForUser(userId)) { Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId)); mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId); diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java index 4a1297f8af71..8335243d590f 100644 --- a/services/core/java/com/android/server/vr/Vr2dDisplay.java +++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java @@ -266,6 +266,7 @@ class Vr2dDisplay { } int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH; + flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT; mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */, DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi, null /* surface */, flags, null /* callback */, null /* handler */, diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java index 70c7e586d3fe..608635491849 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java @@ -25,8 +25,8 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.SystemClock; -import android.util.Log; import android.util.LongSparseArray; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -60,16 +60,21 @@ final class NetworkLoggingHandler extends Handler { /** Delay after which older batches get discarded after a retrieval. */ private static final long RETRIEVED_BATCH_DISCARD_DELAY_MS = 5 * 60 * 1000; // 5m + /** Do not call into mDpm with locks held */ private final DevicePolicyManagerService mDpm; private final AlarmManager mAlarmManager; private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() { @Override public void onAlarm() { - Log.d(TAG, "Received a batch finalization timeout alarm, finalizing " + Slog.d(TAG, "Received a batch finalization timeout alarm, finalizing " + mNetworkEvents.size() + " pending events."); + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } }; @@ -110,17 +115,21 @@ final class NetworkLoggingHandler extends Handler { case LOG_NETWORK_EVENT_MSG: { final NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY); if (networkEvent != null) { + Bundle notificationExtras = null; synchronized (NetworkLoggingHandler.this) { mNetworkEvents.add(networkEvent); if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) { - finalizeBatchAndNotifyDeviceOwnerLocked(); + notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked(); } } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); + } } break; } default: { - Log.d(TAG, "NetworkLoggingHandler received an unknown of message."); + Slog.d(TAG, "NetworkLoggingHandler received an unknown of message."); break; } } @@ -133,40 +142,48 @@ final class NetworkLoggingHandler extends Handler { mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG, mBatchTimeoutAlarmListener, this); - Log.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + Slog.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS + "ms from now."); } synchronized void pause() { - Log.d(TAG, "Paused network logging"); + Slog.d(TAG, "Paused network logging"); mPaused = true; } - synchronized void resume() { - if (!mPaused) { - Log.d(TAG, "Attempted to resume network logging, but logging is not paused."); - return; - } + void resume() { + Bundle notificationExtras = null; + synchronized (this) { + if (!mPaused) { + Slog.d(TAG, "Attempted to resume network logging, but logging is not paused."); + return; + } - Log.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken - + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); - mPaused = false; + Slog.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken + + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); + mPaused = false; - // If there is a batch ready that the device owner hasn't been notified about, do it now. - if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { - scheduleBatchFinalization(); - notifyDeviceOwnerLocked(); + // If there is a batch ready that the device owner hasn't been notified about, do it now. + if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { + scheduleBatchFinalization(); + notificationExtras = buildDeviceOwnerMessageLocked(); + } + } + if (notificationExtras != null) { + notifyDeviceOwner(notificationExtras); } } synchronized void discardLogs() { mBatches.clear(); mNetworkEvents = new ArrayList<>(); - Log.d(TAG, "Discarded all network logs"); + Slog.d(TAG, "Discarded all network logs"); } @GuardedBy("this") - private void finalizeBatchAndNotifyDeviceOwnerLocked() { + /** @returns extras if a message should be sent to the device owner */ + private Bundle finalizeBatchAndBuildDeviceOwnerMessageLocked() { + Bundle notificationExtras = null; if (mNetworkEvents.size() > 0) { // Finalize the batch and start a new one from scratch. if (mBatches.size() >= MAX_BATCHES) { @@ -177,27 +194,39 @@ final class NetworkLoggingHandler extends Handler { mBatches.append(mCurrentBatchToken, mNetworkEvents); mNetworkEvents = new ArrayList<>(); if (!mPaused) { - notifyDeviceOwnerLocked(); + notificationExtras = buildDeviceOwnerMessageLocked(); } } else { // Don't notify the DO, since there are no events; DPC can still retrieve // the last full batch if not paused. - Log.d(TAG, "Was about to finalize the batch, but there were no events to send to" + Slog.d(TAG, "Was about to finalize the batch, but there were no events to send to" + " the DPC, the batchToken of last available batch: " + mCurrentBatchToken); } // Regardless of whether the batch was non-empty schedule a new finalization after timeout. scheduleBatchFinalization(); + return notificationExtras; } - /** Sends a notification to the DO. Should only be called when there is a batch available. */ @GuardedBy("this") - private void notifyDeviceOwnerLocked() { + /** Build extras notification to the DO. Should only be called when there + is a batch available. */ + private Bundle buildDeviceOwnerMessageLocked() { final Bundle extras = new Bundle(); final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size(); extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken); extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, lastBatchSize); - Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " - + mCurrentBatchToken); + return extras; + } + + /** Sends a notification to the DO. Should not hold locks as DevicePolicyManagerService may + call into NetworkLoggingHandler. */ + private void notifyDeviceOwner(Bundle extras) { + Slog.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " + + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1)); + if (Thread.holdsLock(this)) { + Slog.wtfStack(TAG, "Shouldn't be called with NetworkLoggingHandler lock held"); + return; + } mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras); } diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java index c399a5de46dd..e3ce17bcd2d8 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -29,6 +29,7 @@ import android.view.SurfaceControl; import android.view.WindowManagerInternal; import com.android.server.LocalServices; +import com.android.server.display.DisplayDeviceInfo; import com.android.server.display.DisplayManagerService.SyncRoot; import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory; @@ -115,4 +116,30 @@ public class DisplayManagerServiceTest extends AndroidTestCase { assertEquals(uniqueIdPrefix + uniqueId, dv.uniqueId); assertEquals(displayId, dv.displayId); } + + public void testCreateVirtualDisplayRotatesWithContent() throws Exception { + // This is effectively the DisplayManager service published to ServiceManager. + DisplayManagerService.BinderService bs = mDisplayManager.new BinderService(); + + String uniqueId = "uniqueId --- Rotates With Content Test"; + int width = 600; + int height = 800; + int dpi = 320; + int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT; + + when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); + int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */, + null /* projection */, "com.android.frameworks.servicestests", + "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */, + uniqueId); + + mDisplayManager.performTraversalInTransactionFromWindowManagerInternal(); + + // flush the handler + mHandler.runWithScissors(() -> {}, 0 /* now */); + + DisplayDeviceInfo ddi = mDisplayManager.getDisplayDeviceInfoInternal(displayId); + assertNotNull(ddi); + assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0); + } } |