Merge "When updating a split app, copy compiled files from base.apk only." into oc-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index d3b4b40..e5fe240 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -24,6 +24,7 @@
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.SystemClock;
import android.service.voice.IVoiceInteractionSession;
import android.util.SparseIntArray;
@@ -134,8 +135,10 @@
*
* @param reasons A map from stack id to a reason integer why the transition was started,, which
* must be one of the APP_TRANSITION_* values.
+ * @param timestamp The time at which the app transition started in
+ * {@link SystemClock#uptimeMillis()} timebase.
*/
- public abstract void notifyAppTransitionStarting(SparseIntArray reasons);
+ public abstract void notifyAppTransitionStarting(SparseIntArray reasons, long timestamp);
/**
* Callback for window manager to let activity manager know that the app transition was
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 163c4b0..f408e57 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -177,6 +177,7 @@
}
void JNIImageReaderContext::returnBufferItem(BufferItem* buffer) {
+ buffer->mGraphicBuffer = nullptr;
mBuffers.push_back(buffer);
}
diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml
index 61ac6f6..0b7bce1 100644
--- a/packages/SystemUI/res/layout/tv_pip_controls.xml
+++ b/packages/SystemUI/res/layout/tv_pip_controls.xml
@@ -22,24 +22,24 @@
<com.android.systemui.pip.tv.PipControlButtonView
android:id="@+id/full_button"
- android:layout_width="100dp"
+ android:layout_width="@dimen/picture_in_picture_button_width"
android:layout_height="wrap_content"
android:src="@drawable/ic_fullscreen_white_24dp"
android:text="@string/pip_fullscreen" />
<com.android.systemui.pip.tv.PipControlButtonView
android:id="@+id/close_button"
- android:layout_width="100dp"
+ android:layout_width="@dimen/picture_in_picture_button_width"
android:layout_height="wrap_content"
- android:layout_marginStart="-50dp"
+ android:layout_marginStart="@dimen/picture_in_picture_button_start_margin"
android:src="@drawable/ic_close_white"
android:text="@string/pip_close" />
<com.android.systemui.pip.tv.PipControlButtonView
android:id="@+id/play_pause_button"
- android:layout_width="100dp"
+ android:layout_width="@dimen/picture_in_picture_button_width"
android:layout_height="wrap_content"
- android:layout_marginStart="-50dp"
+ android:layout_marginStart="@dimen/picture_in_picture_button_start_margin"
android:src="@drawable/ic_pause_white"
android:text="@string/pip_pause"
android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/tv_pip_custom_control.xml b/packages/SystemUI/res/layout/tv_pip_custom_control.xml
new file mode 100644
index 0000000..dd0fce4
--- /dev/null
+++ b/packages/SystemUI/res/layout/tv_pip_custom_control.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<com.android.systemui.pip.tv.PipControlButtonView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/picture_in_picture_button_width"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/picture_in_picture_button_start_margin" />
diff --git a/packages/SystemUI/res/values-tvdpi/dimens.xml b/packages/SystemUI/res/values-tvdpi/dimens.xml
index 5327cee..4d978aa 100644
--- a/packages/SystemUI/res/values-tvdpi/dimens.xml
+++ b/packages/SystemUI/res/values-tvdpi/dimens.xml
@@ -24,4 +24,8 @@
<fraction name="battery_subpixel_smoothing_right">10%</fraction>
<dimen name="battery_margin_bottom">1px</dimen>
+
+ <!-- The dimensions to user for picture-in-picture action buttons. -->
+ <dimen name="picture_in_picture_button_width">100dp</dimen>
+ <dimen name="picture_in_picture_button_start_margin">-50dp</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 0f69f47..a5ee198 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -427,11 +427,7 @@
} else {
actionsContainer.setVisibility(View.VISIBLE);
if (mActionsGroup != null) {
- // Hide extra views
- for (int i = mActions.size(); i < mActionsGroup.getChildCount(); i++) {
- mActionsGroup.getChildAt(i).setVisibility(View.GONE);
- }
- // Add needed views
+ // Ensure we have as many buttons as actions
final LayoutInflater inflater = LayoutInflater.from(this);
while (mActionsGroup.getChildCount() < mActions.size()) {
final ImageView actionView = (ImageView) inflater.inflate(
@@ -439,6 +435,13 @@
mActionsGroup.addView(actionView);
}
+ // Update the visibility of all views
+ for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
+ mActionsGroup.getChildAt(i).setVisibility(i < mActions.size()
+ ? View.VISIBLE
+ : View.GONE);
+ }
+
// Recreate the layout
final boolean isLandscapePip = stackBounds != null &&
(stackBounds.width() > stackBounds.height());
@@ -460,10 +463,9 @@
Log.w(TAG, "Failed to send action", e);
}
});
- } else {
- actionView.setAlpha(DISABLED_ACTION_ALPHA);
}
actionView.setEnabled(action.isEnabled());
+ actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
// Update the margin between actions
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
index 40a63d7..b21cd95 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlButtonView.java
@@ -20,6 +20,7 @@
import android.animation.AnimatorInflater;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -33,6 +34,7 @@
* A view containing PIP controls including fullscreen, close, and media controls.
*/
public class PipControlButtonView extends RelativeLayout {
+
private OnFocusChangeListener mFocusChangeListener;
private ImageView mIconImageView;
ImageView mButtonImageView;
@@ -122,18 +124,37 @@
}
/**
+ * Sets the drawable for the button with the given drawable.
+ */
+ public void setImageDrawable(Drawable d) {
+ mIconImageView.setImageDrawable(d);
+ }
+
+ /**
* Sets the drawable for the button with the given resource id.
*/
public void setImageResource(int resId) {
- mIconImageView.setImageResource(resId);
+ if (resId != 0) {
+ mIconImageView.setImageResource(resId);
+ }
+ }
+
+ /**
+ * Sets the text for description the with the given string.
+ */
+ public void setText(CharSequence text) {
+ mButtonImageView.setContentDescription(text);
+ mDescriptionTextView.setText(text);
}
/**
* Sets the text for description the with the given resource id.
*/
public void setText(int resId) {
- mButtonImageView.setContentDescription(getContext().getString(resId));
- mDescriptionTextView.setText(resId);
+ if (resId != 0) {
+ mButtonImageView.setContentDescription(getContext().getString(resId));
+ mDescriptionTextView.setText(resId);
+ }
}
private static void cancelAnimator(Animator animator) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index acea3b6..10206d4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -16,12 +16,20 @@
package com.android.systemui.pip.tv;
+import android.app.ActivityManager;
+import android.app.PendingIntent.CanceledException;
+import android.app.RemoteAction;
import android.content.Context;
+import android.graphics.Color;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
import android.view.View;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.util.AttributeSet;
@@ -30,11 +38,19 @@
import static android.media.session.PlaybackState.ACTION_PAUSE;
import static android.media.session.PlaybackState.ACTION_PLAY;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* A view containing PIP controls including fullscreen, close, and media controls.
*/
public class PipControlsView extends LinearLayout {
+
+ private static final String TAG = PipControlsView.class.getSimpleName();
+
+ private static final float DISABLED_ACTION_ALPHA = 0.54f;
+
/**
* An interface to listen user action.
*/
@@ -47,19 +63,23 @@
private MediaController mMediaController;
- final PipManager mPipManager = PipManager.getInstance();
- Listener mListener;
+ private final PipManager mPipManager = PipManager.getInstance();
+ private final LayoutInflater mLayoutInflater;
+ private final Handler mHandler;
+ private Listener mListener;
private PipControlButtonView mFullButtonView;
private PipControlButtonView mCloseButtonView;
private PipControlButtonView mPlayPauseButtonView;
+ private ArrayList<PipControlButtonView> mCustomButtonViews = new ArrayList<>();
+ private List<RemoteAction> mCustomActions = new ArrayList<>();
private PipControlButtonView mFocusedChild;
private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
@Override
public void onPlaybackStateChanged(PlaybackState state) {
- updatePlayPauseView();
+ updateUserActions();
}
};
@@ -95,9 +115,10 @@
public PipControlsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- LayoutInflater inflater = (LayoutInflater) getContext()
+ mLayoutInflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.tv_pip_controls, this);
+ mLayoutInflater.inflate(R.layout.tv_pip_controls, this);
+ mHandler = new Handler();
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
@@ -176,21 +197,74 @@
if (mMediaController != null) {
mMediaController.registerCallback(mMediaControllerCallback);
}
- updatePlayPauseView();
+ updateUserActions();
}
- private void updatePlayPauseView() {
- int state = mPipManager.getPlaybackState();
- if (state == PipManager.PLAYBACK_STATE_UNAVAILABLE) {
+ /**
+ * Updates the actions for the PIP. If there are no custom actions, then the media session
+ * actions are shown.
+ */
+ private void updateUserActions() {
+ if (!mCustomActions.isEmpty()) {
+ // Ensure we have as many buttons as actions
+ while (mCustomButtonViews.size() < mCustomActions.size()) {
+ PipControlButtonView buttonView = (PipControlButtonView) mLayoutInflater.inflate(
+ R.layout.tv_pip_custom_control, this, false);
+ addView(buttonView);
+ mCustomButtonViews.add(buttonView);
+ }
+
+ // Update the visibility of all views
+ for (int i = 0; i < mCustomButtonViews.size(); i++) {
+ mCustomButtonViews.get(i).setVisibility(i < mCustomActions.size()
+ ? View.VISIBLE
+ : View.GONE);
+ }
+
+ // Update the state and visibility of the action buttons, and hide the rest
+ for (int i = 0; i < mCustomActions.size(); i++) {
+ final RemoteAction action = mCustomActions.get(i);
+ PipControlButtonView actionView = mCustomButtonViews.get(i);
+
+ // TODO: Check if the action drawable has changed before we reload it
+ action.getIcon().loadDrawableAsync(getContext(), d -> {
+ d.setTint(Color.WHITE);
+ actionView.setImageDrawable(d);
+ }, mHandler);
+ actionView.setText(action.getContentDescription());
+ if (action.isEnabled()) {
+ actionView.setOnClickListener(v -> {
+ try {
+ action.getActionIntent().send();
+ } catch (CanceledException e) {
+ Log.w(TAG, "Failed to send action", e);
+ }
+ });
+ }
+ actionView.setEnabled(action.isEnabled());
+ actionView.setAlpha(action.isEnabled() ? 1f : DISABLED_ACTION_ALPHA);
+ }
+
+ // Hide the media session buttons
mPlayPauseButtonView.setVisibility(View.GONE);
} else {
- mPlayPauseButtonView.setVisibility(View.VISIBLE);
- if (state == PipManager.PLAYBACK_STATE_PLAYING) {
- mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white);
- mPlayPauseButtonView.setText(R.string.pip_pause);
+ int state = mPipManager.getPlaybackState();
+ if (state == PipManager.PLAYBACK_STATE_UNAVAILABLE) {
+ mPlayPauseButtonView.setVisibility(View.GONE);
} else {
- mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white);
- mPlayPauseButtonView.setText(R.string.pip_play);
+ mPlayPauseButtonView.setVisibility(View.VISIBLE);
+ if (state == PipManager.PLAYBACK_STATE_PLAYING) {
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_pause_white);
+ mPlayPauseButtonView.setText(R.string.pip_pause);
+ } else {
+ mPlayPauseButtonView.setImageResource(R.drawable.ic_play_arrow_white);
+ mPlayPauseButtonView.setText(R.string.pip_play);
+ }
+ }
+
+ // Hide all the custom action buttons
+ for (int i = 0; i < mCustomButtonViews.size(); i++) {
+ mCustomButtonViews.get(i).setVisibility(View.GONE);
}
}
}
@@ -203,6 +277,9 @@
mCloseButtonView.reset();
mPlayPauseButtonView.reset();
mFullButtonView.requestFocus();
+ for (int i = 0; i < mCustomButtonViews.size(); i++) {
+ mCustomButtonViews.get(i).reset();
+ }
}
/**
@@ -213,6 +290,15 @@
}
/**
+ * Updates the set of activity-defined actions.
+ */
+ public void setActions(List<RemoteAction> actions) {
+ mCustomActions.clear();
+ mCustomActions.addAll(actions);
+ updateUserActions();
+ }
+
+ /**
* Returns the focused control button view to animate focused button.
*/
PipControlButtonView getFocusedButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index f98310d..ca58080 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -20,6 +20,7 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
import android.app.IActivityManager;
+import android.app.RemoteAction;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -124,6 +125,7 @@
private MediaController mPipMediaController;
private String[] mLastPackagesResourceGranted;
private PipNotification mPipNotification;
+ private ParceledListSlice mCustomActions;
private final PinnedStackListener mPinnedStackListener = new PinnedStackListener();
@@ -187,7 +189,14 @@
}
@Override
- public void onActionsChanged(ParceledListSlice actions) {}
+ public void onActionsChanged(ParceledListSlice actions) {
+ mCustomActions = actions;
+ mHandler.post(() -> {
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ mListeners.get(i).onPipMenuActionsChanged(mCustomActions);
+ }
+ });
+ }
}
private PipManager() { }
@@ -432,6 +441,7 @@
}
Intent intent = new Intent(mContext, PipMenuActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(PipMenuActivity.EXTRA_CUSTOM_ACTIONS, mCustomActions);
mContext.startActivity(intent);
}
@@ -690,6 +700,8 @@
void onPipActivityClosed();
/** Invoked when the PIP menu gets shown. */
void onShowPipMenu();
+ /** Invoked when the PIP menu actions change. */
+ void onPipMenuActionsChanged(ParceledListSlice actions);
/** Invoked when the PIPed activity is about to return back to the fullscreen. */
void onMoveToFullscreen();
/** Invoked when we are above to start resizing the Pip. */
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index ce1bea1..82018ce 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -19,22 +19,27 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ParceledListSlice;
import android.os.Bundle;
import android.view.View;
import com.android.systemui.R;
+import java.util.Collections;
/**
* Activity to show the PIP menu to control PIP.
*/
public class PipMenuActivity extends Activity implements PipManager.Listener {
private static final String TAG = "PipMenuActivity";
+ static final String EXTRA_CUSTOM_ACTIONS = "custom_actions";
+
private final PipManager mPipManager = PipManager.getInstance();
private Animator mFadeInAnimation;
private Animator mFadeOutAnimation;
- private View mPipControlsView;
+ private PipControlsView mPipControlsView;
private boolean mRestorePipSizeWhenClose;
@Override
@@ -51,6 +56,15 @@
mFadeOutAnimation = AnimatorInflater.loadAnimator(
this, R.anim.tv_pip_menu_fade_out_animation);
mFadeOutAnimation.setTarget(mPipControlsView);
+
+ onPipMenuActionsChanged(getIntent().getParcelableExtra(EXTRA_CUSTOM_ACTIONS));
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ onPipMenuActionsChanged(getIntent().getParcelableExtra(EXTRA_CUSTOM_ACTIONS));
}
private void restorePipAndFinish() {
@@ -96,6 +110,12 @@
}
@Override
+ public void onPipMenuActionsChanged(ParceledListSlice actions) {
+ boolean hasCustomActions = actions != null && !actions.getList().isEmpty();
+ mPipControlsView.setActions(hasCustomActions ? actions.getList() : Collections.EMPTY_LIST);
+ }
+
+ @Override
public void onShowPipMenu() { }
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index c8f4185..f0745a0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
@@ -81,6 +82,11 @@
}
@Override
+ public void onPipMenuActionsChanged(ParceledListSlice actions) {
+ // no-op.
+ }
+
+ @Override
public void onMoveToFullscreen() {
dismissPipNotification();
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 73f1705..4810f4f 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -47,6 +47,7 @@
import android.os.IDeviceIdleController;
import android.os.IInterface;
import android.os.Parcel;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -345,7 +346,7 @@
}
private static boolean isCallerSystem() {
- return getCallingUserId() == UserHandle.USER_SYSTEM;
+ return Binder.getCallingUid() == Process.SYSTEM_UID;
}
private ServiceConnection createServiceConnection(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7b55e5f..4d44b63 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23752,9 +23752,10 @@
}
@Override
- public void notifyAppTransitionStarting(SparseIntArray reasons) {
+ public void notifyAppTransitionStarting(SparseIntArray reasons, long timestamp) {
synchronized (ActivityManagerService.this) {
- mStackSupervisor.mActivityMetricsLogger.notifyTransitionStarting(reasons);
+ mStackSupervisor.mActivityMetricsLogger.notifyTransitionStarting(
+ reasons, timestamp);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index bf7b663..98815d7 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -230,12 +230,12 @@
/**
* Notifies the tracker that all windows of the app have been drawn.
*/
- void notifyWindowsDrawn(int stackId) {
+ void notifyWindowsDrawn(int stackId, long timestamp) {
final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
if (info == null || info.loggedWindowsDrawn) {
return;
}
- info.windowsDrawnDelayMs = calculateCurrentDelay();
+ info.windowsDrawnDelayMs = calculateDelay(timestamp);
info.loggedWindowsDrawn = true;
if (allStacksWindowsDrawn() && mLoggedTransitionStarting) {
reset(false /* abort */);
@@ -245,13 +245,13 @@
/**
* Notifies the tracker that the starting window was drawn.
*/
- void notifyStartingWindowDrawn(int stackId) {
+ void notifyStartingWindowDrawn(int stackId, long timestamp) {
final StackTransitionInfo info = mStackTransitionInfo.get(stackId);
if (info == null || info.loggedStartingWindowDrawn) {
return;
}
info.loggedStartingWindowDrawn = true;
- info.startingWindowDelayMs = calculateCurrentDelay();
+ info.startingWindowDelayMs = calculateDelay(timestamp);
}
/**
@@ -260,11 +260,11 @@
* @param stackIdReasons A map from stack id to a reason integer, which must be on of
* ActivityManagerInternal.APP_TRANSITION_* reasons.
*/
- void notifyTransitionStarting(SparseIntArray stackIdReasons) {
+ void notifyTransitionStarting(SparseIntArray stackIdReasons, long timestamp) {
if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
return;
}
- mCurrentTransitionDelayMs = calculateCurrentDelay();
+ mCurrentTransitionDelayMs = calculateDelay(timestamp);
mLoggedTransitionStarting = true;
for (int index = stackIdReasons.size() - 1; index >= 0; index--) {
final int stackId = stackIdReasons.keyAt(index);
@@ -344,6 +344,11 @@
return (int) (SystemClock.uptimeMillis() - mCurrentTransitionStartTime);
}
+ private int calculateDelay(long timestamp) {
+ // Shouldn't take more than 25 days to launch an app, so int is fine here.
+ return (int) (timestamp - mCurrentTransitionStartTime);
+ }
+
private void logAppTransitionMultiEvents() {
for (int index = mStackTransitionInfo.size() - 1; index >= 0; index--) {
final StackTransitionInfo info = mStackTransitionInfo.valueAt(index);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a826b68..68f4d0d 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1928,18 +1928,19 @@
}
@Override
- public void onStartingWindowDrawn() {
+ public void onStartingWindowDrawn(long timestamp) {
synchronized (service) {
- mStackSupervisor.mActivityMetricsLogger.notifyStartingWindowDrawn(getStackId());
+ mStackSupervisor.mActivityMetricsLogger.notifyStartingWindowDrawn(
+ getStackId(), timestamp);
}
}
@Override
- public void onWindowsDrawn() {
+ public void onWindowsDrawn(long timestamp) {
synchronized (service) {
- mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn(getStackId());
+ mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn(getStackId(), timestamp);
if (displayStartTime != 0) {
- reportLaunchTimeLocked(SystemClock.uptimeMillis());
+ reportLaunchTimeLocked(timestamp);
}
mStackSupervisor.sendWaitingVisibleReportLocked(this);
startTime = 0;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 07d548d..5f96b91 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -19309,7 +19309,7 @@
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
- return true;
+ return false;
}
return mSettings.getBlockUninstallLPr(userId, packageName);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index e550a5e..fe74947 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -38,6 +38,8 @@
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.Trace;
import android.util.Slog;
import android.view.DisplayInfo;
@@ -62,23 +64,38 @@
private final IApplicationToken mToken;
private final Handler mHandler;
- private final Runnable mOnStartingWindowDrawn = () -> {
- if (mListener == null) {
- return;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
- + AppWindowContainerController.this.mToken);
- mListener.onStartingWindowDrawn();
- };
+ private final class H extends Handler {
+ public static final int NOTIFY_WINDOWS_DRAWN = 1;
+ public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
- private final Runnable mOnWindowsDrawn = () -> {
- if (mListener == null) {
- return;
+ public H(Looper looper) {
+ super(looper);
}
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
- + AppWindowContainerController.this.mToken);
- mListener.onWindowsDrawn();
- };
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case NOTIFY_WINDOWS_DRAWN:
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onWindowsDrawn(msg.getWhen());
+ break;
+ case NOTIFY_STARTING_WINDOW_DRAWN:
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onStartingWindowDrawn(msg.getWhen());
+ break;
+ default:
+ break;
+ }
+ }
+ }
private final Runnable mOnWindowsVisible = () -> {
if (mListener == null) {
@@ -213,7 +230,7 @@
int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
WindowManagerService service, Configuration overrideConfig, Rect bounds) {
super(listener, service);
- mHandler = new Handler(service.mH.getLooper());
+ mHandler = new H(service.mH.getLooper());
mToken = token;
synchronized(mWindowMap) {
AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
@@ -761,11 +778,11 @@
}
void reportStartingWindowDrawn() {
- mHandler.post(mOnStartingWindowDrawn);
+ mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_STARTING_WINDOW_DRAWN));
}
void reportWindowsDrawn() {
- mHandler.post(mOnWindowsDrawn);
+ mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
}
void reportWindowsVisible() {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
index 26537f2..8a39a74 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
@@ -19,7 +19,7 @@
/** Interface used by the creator of the controller to listen to changes with the container. */
public interface AppWindowContainerListener extends WindowContainerListener {
/** Called when the windows associated app window container are drawn. */
- void onWindowsDrawn();
+ void onWindowsDrawn(long timestamp);
/** Called when the windows associated app window container are visible. */
void onWindowsVisible();
/** Called when the windows associated app window container are no longer visible. */
@@ -28,7 +28,7 @@
/**
* Called when the starting window for this container is drawn.
*/
- void onStartingWindowDrawn();
+ void onStartingWindowDrawn(long timestamp);
/**
* Called when the key dispatching to a window associated with the app window container
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 947731e..ec7ab23 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5158,7 +5158,8 @@
}
break;
case NOTIFY_APP_TRANSITION_STARTING: {
- mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj);
+ mAmInternal.notifyAppTransitionStarting((SparseIntArray) msg.obj,
+ msg.getWhen());
}
break;
case NOTIFY_APP_TRANSITION_CANCELLED: {