summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java60
-rw-r--r--media/java/android/media/MediaPlayer2.java18
-rw-r--r--media/java/android/media/MediaPlayer2Impl.java111
-rw-r--r--media/jni/android_media_MediaPlayer2.cpp2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java75
-rw-r--r--proto/src/metrics_constants.proto26
6 files changed, 215 insertions, 77 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ee5ea806da34..3d169b0656a6 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2865,7 +2865,7 @@ public class DevicePolicyManager {
* false if the profile has empty password as a separate challenge.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a profile owner of a managed profile.
+ * @throws SecurityException if {@code admin} is not a profile owner.
* @see UserManager#DISALLOW_UNIFIED_PASSWORD
*/
public boolean isUsingUnifiedPassword(@NonNull ComponentName admin) {
@@ -5579,10 +5579,13 @@ public class DevicePolicyManager {
}
/**
- * Called by a profile owner or device owner to add a default intent handler activity for
- * intents that match a certain intent filter. This activity will remain the default intent
- * handler even if the set of potential event handlers for the intent filter changes and if the
- * intent preferences are reset.
+ * Called by a profile owner or device owner to set a default activity that the system selects
+ * to handle intents that match the given {@link IntentFilter}. This activity will remain the
+ * default intent handler even if the set of potential event handlers for the intent filter
+ * changes and if the intent preferences are reset.
+ * <p>
+ * Note that the caller should still declare the activity in the manifest, the API just sets
+ * the activity to be the default one to handle the given intent filter.
* <p>
* The default disambiguation mechanism takes over if the activity is not installed (anymore).
* When the activity is (re)installed, it is automatically reset as default intent handler for
@@ -5878,7 +5881,7 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true caller-Id information in the managed profile is not displayed.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setCrossProfileCallerIdDisabled");
@@ -5899,7 +5902,7 @@ public class DevicePolicyManager {
* thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getCrossProfileCallerIdDisabled");
@@ -5939,7 +5942,7 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true contacts search in the managed profile is not displayed.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin,
boolean disabled) {
@@ -5961,7 +5964,7 @@ public class DevicePolicyManager {
* thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getCrossProfileContactsSearchDisabled");
@@ -6032,7 +6035,7 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true, bluetooth devices cannot access enterprise contacts.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
throwIfParentInstance("setBluetoothContactSharingDisabled");
@@ -6055,7 +6058,7 @@ public class DevicePolicyManager {
* This API works on managed profile only.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
throwIfParentInstance("getBluetoothContactSharingDisabled");
@@ -6125,7 +6128,7 @@ public class DevicePolicyManager {
* {@link UserManager#DISALLOW_SHARE_INTO_MANAGED_PROFILE}.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @throws SecurityException if {@code admin} is not a device or profile owner.
+ * @throws SecurityException if {@code admin} is not a profile owner.
*/
public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
throwIfParentInstance("clearCrossProfileIntentFilters");
@@ -6139,21 +6142,22 @@ public class DevicePolicyManager {
}
/**
- * Called by a profile or device owner to set the permitted accessibility services. When set by
+ * Called by a profile or device owner to set the permitted
+ * {@link android.accessibilityservice.AccessibilityService}. When set by
* a device owner or profile owner the restriction applies to all profiles of the user the
- * device owner or profile owner is an admin for. By default the user can use any accessiblity
- * service. When zero or more packages have been added, accessiblity services that are not in
+ * device owner or profile owner is an admin for. By default, the user can use any accessibility
+ * service. When zero or more packages have been added, accessibility services that are not in
* the list and not part of the system can not be enabled by the user.
* <p>
* Calling with a null value for the list disables the restriction so that all services can be
- * used, calling with an empty list only allows the builtin system's services.
+ * used, calling with an empty list only allows the built-in system services. Any non-system
+ * accessibility service that's currently enabled must be included in the list.
* <p>
* System accessibility services are always available to the user the list can't modify this.
- *
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames List of accessibility service package names.
- * @return true if setting the restriction succeeded. It fail if there is one or more non-system
- * accessibility services enabled, that are not in the list.
+ * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
+ * contain every enabled non-system accessibility service.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
@@ -6242,10 +6246,11 @@ public class DevicePolicyManager {
/**
* Called by a profile or device owner to set the permitted input methods services. When set by
* a device owner or profile owner the restriction applies to all profiles of the user the
- * device owner or profile owner is an admin for. By default the user can use any input method.
+ * device owner or profile owner is an admin for. By default, the user can use any input method.
* When zero or more packages have been added, input method that are not in the list and not
* part of the system can not be enabled by the user. This method will fail if it is called for
- * a admin that is not for the foreground user or a profile of the foreground user.
+ * a admin that is not for the foreground user or a profile of the foreground user. Any
+ * non-system input method service that's currently enabled must be included in the list.
* <p>
* Calling with a null value for the list disables the restriction so that all input methods can
* be used, calling with an empty list disables all but the system's own input methods.
@@ -6254,8 +6259,8 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames List of input method package names.
- * @return true if setting the restriction succeeded. It will fail if there are one or more
- * non-system input methods currently enabled that are not in the packageNames list.
+ * @return {@code true} if the operation succeeded, or {@code false} if the list didn't
+ * contain every enabled non-system input method service.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
public boolean setPermittedInputMethods(
@@ -7854,11 +7859,14 @@ public class DevicePolicyManager {
* {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it through the UI,
* {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission is denied and the user
* cannot manage it through the UI, and {@link #PERMISSION_GRANT_STATE_GRANTED granted} in which
- * the permission is granted and the user cannot manage it through the UI. This might affect all
- * permissions in a group that the runtime permission belongs to. This method can only be called
- * by a profile owner, device owner, or a delegate given the
+ * the permission is granted and the user cannot manage it through the UI. This method can only
+ * be called by a profile owner, device owner, or a delegate given the
* {@link #DELEGATION_PERMISSION_GRANT} scope via {@link #setDelegatedScopes}.
* <p/>
+ * Note that user cannot manage other permissions in the affected group through the UI
+ * either and their granted state will be kept as the current value. Thus, it's recommended that
+ * you set the grant state of all the permissions in the affected group.
+ * <p/>
* Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke
* the permission. It retains the previous grant, if any.
* <p/>
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 0d472abe9f9c..0cc744186a75 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -22,17 +22,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.SurfaceTexture;
-import android.media.MediaDrm;
-import android.media.MediaFormat;
-import android.media.MediaPlayer2Impl;
-import android.media.MediaPlayerBase;
-import android.media.MediaTimeProvider;
-import android.media.PlaybackParams;
-import android.media.SubtitleController;
-import android.media.SubtitleController.Anchor;
-import android.media.SubtitleData;
-import android.media.SubtitleTrack.RenderingWidget;
-import android.media.SyncParams;
import android.net.Uri;
import android.os.Handler;
import android.os.Parcel;
@@ -43,14 +32,13 @@ import android.view.SurfaceHolder;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.AutoCloseable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.Executor;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Executor;
/**
@@ -2019,12 +2007,12 @@ public abstract class MediaPlayer2 extends MediaPlayerBase
public static final int MEDIA_CALL_DESELECT_TRACK = 2;
/** The player just completed a call {@code loopCurrent}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
*/
public static final int MEDIA_CALL_LOOP_CURRENT = 3;
/** The player just completed a call {@code pause}.
- * @see android.media.MediaPlayer2.MediaPlayer2EventCallback.CallComplete
+ * @see android.media.MediaPlayer2.MediaPlayer2EventCallback#onCallComplete
*/
public static final int MEDIA_CALL_PAUSE = 4;
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 50e354317162..7c114df66037 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -35,16 +35,16 @@ import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.os.Process;
import android.os.PowerManager;
+import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
-import android.util.ArrayMap;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.widget.VideoView;
@@ -63,10 +63,7 @@ import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.Runnable;
import java.lang.ref.WeakReference;
-import java.net.CookieHandler;
-import java.net.CookieManager;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -74,15 +71,15 @@ import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
-import java.util.Collections;
-import java.util.concurrent.Executor;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
+import java.util.concurrent.Executor;
/**
@@ -135,6 +132,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
private ProvisioningThread mDrmProvisioningThread;
//--- guarded by |mDrmLock| end
+ private HandlerThread mHandlerThread;
+ private final Handler mTaskHandler;
+ private final Object mTaskLock = new Object();
+ @GuardedBy("mTaskLock")
+ private final List<Task> mPendingTasks = new LinkedList<>();
+ @GuardedBy("mTaskLock")
+ private Task mCurrentTask;
+
/**
* Default constructor.
* <p>When done with the MediaPlayer2Impl, you should call {@link #close()},
@@ -151,6 +156,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
mEventHandler = null;
}
+ mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
+ mHandlerThread.start();
+ looper = mHandlerThread.getLooper();
+ mTaskHandler = new Handler(looper);
+
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
mGuard.open("close");
@@ -201,8 +211,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
*/
@Override
public void play() {
- stayAwake(true);
- _start();
+ synchronized (mTaskLock) {
+ mPendingTasks.add(new Task(MEDIA_CALL_PLAY, false) {
+ @Override
+ int process() {
+ stayAwake(true);
+ _start();
+ // TODO: define public constants for return value (status).
+ return 0;
+ }
+ });
+ processPendingTask_l();
+ }
}
private native void _start() throws IllegalStateException;
@@ -218,7 +238,21 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
* @throws IllegalStateException if it is called in an invalid state
*/
@Override
- public native void prepare();
+ public void prepare() {
+ synchronized (mTaskLock) {
+ mPendingTasks.add(new Task(MEDIA_CALL_PREPARE, true) {
+ @Override
+ int process() {
+ _prepare();
+ // TODO: define public constants for return value (status).
+ return 0;
+ }
+ });
+ processPendingTask_l();
+ }
+ }
+
+ public native void _prepare();
/**
* Pauses playback. Call play() to resume.
@@ -695,6 +729,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
public void clearPendingCommands() {
}
+ @GuardedBy("mTaskLock")
+ private void processPendingTask_l() {
+ if (mCurrentTask != null) {
+ return;
+ }
+ if (!mPendingTasks.isEmpty()) {
+ Task task = mPendingTasks.remove(0);
+ mCurrentTask = task;
+ mTaskHandler.post(task);
+ }
+ }
+
private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
throws IOException {
Preconditions.checkNotNull(dsd, "the DataSourceDesc cannot be null");
@@ -2525,6 +2571,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
synchronized (mEventCbLock) {
mEventCallbackRecords.clear();
}
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ mHandlerThread = null;
+ }
if (mTimeProvider != null) {
mTimeProvider.close();
mTimeProvider = null;
@@ -2638,6 +2688,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
}
}
}
+ synchronized (mTaskLock) {
+ if (mCurrentTask.mMediaCallType == MEDIA_CALL_PREPARE
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
return;
}
@@ -4506,4 +4563,38 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
}
}
}
+
+ private abstract class Task implements Runnable {
+ private final int mMediaCallType;
+ private final boolean mNeedToWaitForEventToComplete;
+
+ public Task (int mediaCallType, boolean needToWaitForEventToComplete) {
+ mMediaCallType = mediaCallType;
+ mNeedToWaitForEventToComplete = needToWaitForEventToComplete;
+ }
+
+ abstract int process();
+
+ @Override
+ public void run() {
+ int status = process();
+
+ if (!mNeedToWaitForEventToComplete) {
+ final DataSourceDesc dsd;
+ synchronized (mSrcLock) {
+ dsd = mCurrentDSD;
+ }
+ synchronized (mEventCbLock) {
+ for (Pair<Executor, MediaPlayer2EventCallback> cb : mEventCallbackRecords) {
+ cb.first.execute(() -> cb.second.onCallComplete(
+ MediaPlayer2Impl.this, dsd, mMediaCallType, status));
+ }
+ }
+ synchronized (mTaskLock) {
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
+ }
+ };
}
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index af78777a900b..918b82b06570 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -1490,7 +1490,7 @@ static const JNINativeMethod gMethods[] = {
{"_setVideoSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaPlayer2_setVideoSurface},
{"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
{"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
- {"prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
+ {"_prepare", "()V", (void *)android_media_MediaPlayer2_prepare},
{"_start", "()V", (void *)android_media_MediaPlayer2_start},
{"_stop", "()V", (void *)android_media_MediaPlayer2_stop},
{"native_getMediaPlayer2State", "()I", (void *)android_media_MediaPlayer2_getMediaPlayer2State},
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index da042d2bb8ce..407be6253bfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -113,7 +113,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
private static final String EXTRA_DISABLE_STATE = "disabled_state";
private final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
- private final static int ROTATE_BUTTON_LOOP_DURATION_MS = 2000;
+ private final static int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000;
private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
@@ -152,11 +152,14 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
public boolean mHomeBlockedThisTouch;
private int mLastRotationSuggestion;
+ private boolean mPendingRotationSuggestion;
private boolean mHoveringRotationSuggestion;
private RotationLockController mRotationLockController;
private TaskStackListenerImpl mTaskStackListener;
private final Runnable mRemoveRotationProposal = () -> setRotateSuggestionButtonState(false);
+ private final Runnable mCancelPendingRotationProposal =
+ () -> mPendingRotationSuggestion = false;
private Animator mRotateHideAnimator;
private ViewRippler mViewRippler = new ViewRippler();
@@ -365,6 +368,11 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
&& mNavigationBarWindowState != state) {
mNavigationBarWindowState = state;
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
+
+ // If the navbar is visible, show the rotate button if there's a pending suggestion
+ if (state == WINDOW_STATE_SHOWING && mPendingRotationSuggestion) {
+ showAndLogRotationSuggestion();
+ }
}
}
@@ -373,40 +381,53 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
// This method will be called on rotation suggestion changes even if the proposed rotation
// is not valid for the top app. Use invalid rotation choices as a signal to remove the
// rotate button if shown.
-
if (!isValid) {
setRotateSuggestionButtonState(false);
return;
}
+ // If window rotation matches suggested rotation, remove any current suggestions
final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
if (rotation == winRotation) {
- // Use this as a signal to remove any current suggestions
- getView().getHandler().removeCallbacks(mRemoveRotationProposal);
+ getView().removeCallbacks(mRemoveRotationProposal);
setRotateSuggestionButtonState(false);
- } else {
- mLastRotationSuggestion = rotation; // Remember rotation for click
-
- // Update the icon style to change animation parameters
- if (mNavigationBarView != null) {
- final boolean rotationCCW = isRotationAnimationCCW(winRotation, rotation);
- int style;
- if (winRotation == Surface.ROTATION_0 || winRotation == Surface.ROTATION_180) {
- style = rotationCCW ? R.style.RotateButtonCCWStart90 :
- R.style.RotateButtonCWStart90;
- } else { // 90 or 270
- style = rotationCCW ? R.style.RotateButtonCCWStart0 :
- R.style.RotateButtonCWStart0;
- }
- mNavigationBarView.updateRotateSuggestionButtonStyle(style, true);
+ return;
+ }
+
+ // Prepare to show the navbar icon by updating the icon style to change anim params
+ mLastRotationSuggestion = rotation; // Remember rotation for click
+ if (mNavigationBarView != null) {
+ final boolean rotationCCW = isRotationAnimationCCW(winRotation, rotation);
+ int style;
+ if (winRotation == Surface.ROTATION_0 || winRotation == Surface.ROTATION_180) {
+ style = rotationCCW ? R.style.RotateButtonCCWStart90 :
+ R.style.RotateButtonCWStart90;
+ } else { // 90 or 270
+ style = rotationCCW ? R.style.RotateButtonCCWStart0 :
+ R.style.RotateButtonCWStart0;
}
+ mNavigationBarView.updateRotateSuggestionButtonStyle(style, true);
+ }
+
+ if (mNavigationBarWindowState != WINDOW_STATE_SHOWING) {
+ // If the navbar isn't shown, flag the rotate icon to be shown should the navbar become
+ // visible given some time limit.
+ mPendingRotationSuggestion = true;
+ getView().removeCallbacks(mCancelPendingRotationProposal);
+ getView().postDelayed(mCancelPendingRotationProposal,
+ NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS);
- setRotateSuggestionButtonState(true);
- rescheduleRotationTimeout(false);
- mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN);
+ } else { // The navbar is visible so show the icon right away
+ showAndLogRotationSuggestion();
}
}
+ private void showAndLogRotationSuggestion() {
+ setRotateSuggestionButtonState(true);
+ rescheduleRotationTimeout(false);
+ mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN);
+ }
+
private boolean isRotationAnimationCCW(int from, int to) {
// All 180deg WM rotation animations are CCW, match that
if (from == Surface.ROTATION_0 && to == Surface.ROTATION_90) return false;
@@ -453,6 +474,11 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
}
+ // Clear any pending suggestion flag as it has either been nullified or is being shown
+ mPendingRotationSuggestion = false;
+ getView().removeCallbacks(mCancelPendingRotationProposal);
+
+ // Handle the visibility change and animation
if (visible) { // Appear and change (cannot force)
// Stop and clear any currently running hide animations
if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
@@ -516,9 +542,8 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
if (!mNavigationBarView.isRotateButtonVisible()) return;
}
- Handler h = getView().getHandler();
- h.removeCallbacks(mRemoveRotationProposal); // Stop any pending removal
- h.postDelayed(mRemoveRotationProposal,
+ getView().removeCallbacks(mRemoveRotationProposal); // Stop any pending removal
+ getView().postDelayed(mRemoveRotationProposal,
computeRotationProposalTimeout()); // Schedule timeout
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index a1f184d726f1..796ac4fb0bd9 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5419,6 +5419,32 @@ message MetricsEvent {
// OS: P
ZEN_WHAT_TO_BLOCK = 1339;
+ // ACTION: DND Settings > Priority only allows > System toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_ZEN_ALLOW_SYSTEM = 1340;
+
+ // OPEN: Settings > Sounds > Do Not Disturb > Duration
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DURATION_DIALOG = 1341;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > Duration -> Time Option (ie: for one hour)
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DURATION_TIME = 1342;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > Duration -> Until you turn off
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DURATION_FOREVER = 1343;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > Duration -> Ask every time
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_DURATION_PROMPT = 1344;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS