summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/test-current.txt1
-rw-r--r--config/hiddenapi-light-greylist.txt13
-rw-r--r--core/java/android/app/ActivityThread.java25
-rw-r--r--core/java/android/content/pm/PackageManager.java1
-rw-r--r--core/java/android/view/ThreadedRenderer.java19
-rw-r--r--core/java/android/view/ViewRootImpl.java40
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp70
-rw-r--r--libs/hwui/Android.bp1
-rw-r--r--libs/hwui/pipeline/skia/GLFunctorDrawable.cpp139
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp16
-rw-r--r--libs/hwui/renderthread/CanvasContext.h6
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp8
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h6
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp4
-rw-r--r--libs/hwui/renderthread/RenderProxy.h1
-rw-r--r--packages/SettingsLib/res/values-pl/arrays.xml4
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java6
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java3
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java7
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java7
-rw-r--r--services/core/java/com/android/server/wm/StackWindowController.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java22
-rw-r--r--telephony/java/android/telephony/MbmsDownloadSession.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/TetheringTest.java7
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java2
28 files changed, 385 insertions, 61 deletions
diff --git a/api/test-current.txt b/api/test-current.txt
index adb06c79eaf5..e34614e966c4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -249,6 +249,7 @@ package android.content.pm {
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
+ method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
method public abstract java.lang.String[] getNamesForUids(int[]);
method public abstract java.lang.String getPermissionControllerPackageName();
method public abstract java.lang.String getServicesSystemSharedLibraryPackageName();
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 7176a5d2d26a..f3091b113985 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -697,6 +697,7 @@ Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/app/INotificationManager$Stub$Proxy;->areNotificationsEnabledForPackage(Ljava/lang/String;I)Z
Landroid/app/INotificationManager$Stub;-><init>()V
Landroid/app/INotificationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/INotificationManager;
+Landroid/app/INotificationManager$Stub;->TRANSACTION_enqueueNotificationWithTag:I
Landroid/app/INotificationManager;->areNotificationsEnabledForPackage(Ljava/lang/String;I)Z
Landroid/app/INotificationManager;->cancelAllNotifications(Ljava/lang/String;I)V
Landroid/app/INotificationManager;->cancelNotificationWithTag(Ljava/lang/String;Ljava/lang/String;II)V
@@ -1234,6 +1235,7 @@ Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetooth$Stub$Proxy;->getConnectionState(Landroid/bluetooth/BluetoothDevice;)I
Landroid/bluetooth/IBluetooth$Stub;-><init>()V
Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
+Landroid/bluetooth/IBluetooth$Stub;->TRANSACTION_enable:I
Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetooth;->getRemoteAlias(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String;
Landroid/bluetooth/IBluetooth;->isEnabled()Z
@@ -1260,6 +1262,7 @@ Landroid/bluetooth/IBluetoothHeadset;->setPriority(Landroid/bluetooth/BluetoothD
Landroid/bluetooth/IBluetoothHidDeviceCallback$Stub;-><init>()V
Landroid/bluetooth/IBluetoothManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/bluetooth/IBluetoothManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothManager;
+Landroid/bluetooth/IBluetoothManager$Stub;->TRANSACTION_enable:I
Landroid/bluetooth/IBluetoothManager;->getBluetoothGatt()Landroid/bluetooth/IBluetoothGatt;
Landroid/bluetooth/IBluetoothManager;->registerStateChangeCallback(Landroid/bluetooth/IBluetoothStateChangeCallback;)V
Landroid/bluetooth/IBluetoothManager;->unregisterStateChangeCallback(Landroid/bluetooth/IBluetoothStateChangeCallback;)V
@@ -1371,6 +1374,7 @@ Landroid/content/IContentProvider;->call(Ljava/lang/String;Ljava/lang/String;Lja
Landroid/content/IContentProvider;->delete(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
Landroid/content/IContentProvider;->descriptor:Ljava/lang/String;
Landroid/content/IContentProvider;->insert(Ljava/lang/String;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
+Landroid/content/IContentProvider;->QUERY_TRANSACTION:I
Landroid/content/IContentProvider;->update(Ljava/lang/String;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/IContentService$Stub;-><init>()V
@@ -1478,6 +1482,7 @@ Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBind
Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V
Landroid/content/pm/IPackageDeleteObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver2;
Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
Landroid/content/pm/IPackageInstaller;->uninstall(Landroid/content/pm/VersionedPackage;Ljava/lang/String;ILandroid/content/IntentSender;I)V
@@ -1507,6 +1512,7 @@ Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang
Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
Landroid/content/pm/IPackageManager$Stub;-><init>()V
Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
+Landroid/content/pm/IPackageManager$Stub;->TRANSACTION_getApplicationInfo:I
Landroid/content/pm/IPackageManager;->addPermission(Landroid/content/pm/PermissionInfo;)Z
Landroid/content/pm/IPackageManager;->addPermissionAsync(Landroid/content/pm/PermissionInfo;)Z
Landroid/content/pm/IPackageManager;->canonicalToCurrentPackageNames([Ljava/lang/String;)[Ljava/lang/String;
@@ -1991,6 +1997,7 @@ Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
Landroid/database/CursorWrapper;->mCursor:Landroid/database/Cursor;
Landroid/database/DatabaseUtils;->cursorPickFillWindowStartPosition(II)I
Landroid/database/DatabaseUtils;->getTypeOfObject(Ljava/lang/Object;)I
+Landroid/database/IContentObserver$Stub;-><init>()V
Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
Landroid/database/MatrixCursor;->data:[Ljava/lang/Object;
@@ -2699,6 +2706,7 @@ Landroid/location/ILocationListener;->onStatusChanged(Ljava/lang/String;ILandroi
Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/location/ILocationManager$Stub;-><init>()V
Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
+Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
Landroid/location/Location;->mElapsedRealtimeNanos:J
Landroid/location/Location;->mProvider:Ljava/lang/String;
@@ -3564,6 +3572,7 @@ Landroid/net/WebAddress;->setPath(Ljava/lang/String;)V
Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/net/wifi/IWifiManager$Stub;-><init>()V
Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
+Landroid/net/wifi/IWifiManager$Stub;->TRANSACTION_getScanResults:I
Landroid/net/wifi/IWifiManager;->getCurrentNetwork()Landroid/net/Network;
Landroid/net/wifi/IWifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;
Landroid/net/wifi/IWifiManager;->getWifiApEnabledState()I
@@ -3751,6 +3760,7 @@ Landroid/nfc/cardemulation/ApduServiceInfo;->mService:Landroid/content/pm/Resolv
Landroid/nfc/cardemulation/ApduServiceInfo;->mStaticAidGroups:Ljava/util/HashMap;
Landroid/nfc/cardemulation/ApduServiceInfo;->requiresUnlock()Z
Landroid/nfc/ErrorCodes;->isError(I)Z
+Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
Landroid/nfc/INfcAdapterExtras;->authenticate(Ljava/lang/String;[B)V
Landroid/nfc/INfcAdapterExtras;->close(Ljava/lang/String;Landroid/os/IBinder;)Landroid/os/Bundle;
Landroid/nfc/INfcAdapterExtras;->getCardEmulationRoute(Ljava/lang/String;)I
@@ -4010,6 +4020,7 @@ Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/os/IPowerManager$Stub$Proxy;->isLightDeviceIdleMode()Z
Landroid/os/IPowerManager$Stub;-><init>()V
Landroid/os/IPowerManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPowerManager;
+Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
Landroid/os/IPowerManager$Stub;->TRANSACTION_goToSleep:I
Landroid/os/IPowerManager;->isInteractive()Z
Landroid/os/IPowerManager;->nap(J)V
@@ -8234,6 +8245,7 @@ Lcom/android/internal/telephony/IPhoneStateListener;->onSignalStrengthsChanged(L
Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;-><init>()V
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo;
+Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->TRANSACTION_getDeviceId:I
Lcom/android/internal/telephony/IPhoneSubInfo;->getIccSerialNumber(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/IPhoneSubInfo;->getSubscriberId(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/ISms$Stub;-><init>()V
@@ -8253,6 +8265,7 @@ Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinde
Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_answerRingingCall:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
+Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_endCall:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
Lcom/android/internal/telephony/ITelephony;->answerRingingCall()V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 37bf21a898b1..87b334992d2d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -347,6 +347,13 @@ public final class ActivityThread extends ClientTransactionHandler {
final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
= new ArrayMap<ComponentName, ProviderClientRecord>();
+ // Mitigation for b/74523247: Used to serialize calls to AM.getContentProvider().
+ // Note we never removes items from this map but that's okay because there are only so many
+ // users and so many authorities.
+ // TODO Remove it once we move CPR.wait() from AMS to the client side.
+ @GuardedBy("mGetProviderLocks")
+ final ArrayMap<ProviderKey, Object> mGetProviderLocks = new ArrayMap<>();
+
final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
= new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -5959,8 +5966,10 @@ public final class ActivityThread extends ClientTransactionHandler {
// be re-entrant in the case where the provider is in the same process.
ContentProviderHolder holder = null;
try {
- holder = ActivityManager.getService().getContentProvider(
- getApplicationThread(), auth, userId, stable);
+ synchronized (getGetProviderLock(auth, userId)) {
+ holder = ActivityManager.getService().getContentProvider(
+ getApplicationThread(), auth, userId, stable);
+ }
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -5976,6 +5985,18 @@ public final class ActivityThread extends ClientTransactionHandler {
return holder.provider;
}
+ private Object getGetProviderLock(String auth, int userId) {
+ final ProviderKey key = new ProviderKey(auth, userId);
+ synchronized (mGetProviderLocks) {
+ Object lock = mGetProviderLocks.get(key);
+ if (lock == null) {
+ lock = key;
+ mGetProviderLocks.put(key, lock);
+ }
+ return lock;
+ }
+ }
+
private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
if (stable) {
prc.stableCount += 1;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3f9798b7d6c9..b677b5e2c947 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3798,6 +3798,7 @@ public abstract class PackageManager {
* deleted with {@code DONT_DELETE_DATA} flag set).
* @hide
*/
+ @TestApi
public abstract List<ApplicationInfo> getInstalledApplicationsAsUser(
@ApplicationInfoFlags int flags, @UserIdInt int userId);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index d19cc9c8fa92..5b61015e9d42 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -329,6 +329,7 @@ public final class ThreadedRenderer {
// in response, so it really just exists to differentiate from LOST_SURFACE
// but possibly both can just be deleted.
private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+ private static final int SYNC_FRAME_DROPPED = 1 << 3;
private static final String[] VISUALIZERS = {
PROFILE_PROPERTY_VISUALIZE_BARS,
@@ -832,6 +833,10 @@ public final class ThreadedRenderer {
}
}
+ void setFrameCompleteCallback(FrameCompleteCallback callback) {
+ nSetFrameCompleteCallback(mNativeProxy, callback);
+ }
+
static void invokeFunctor(long functor, boolean waitForCompletion) {
nInvokeFunctor(functor, waitForCompletion);
}
@@ -1067,6 +1072,18 @@ public final class ThreadedRenderer {
void onFrameDraw(long frame);
}
+ /**
+ * Interface used to be notified when a frame has finished rendering
+ */
+ public interface FrameCompleteCallback {
+ /**
+ * Invoked after a frame draw
+ *
+ * @param frameNr The id of the frame that was drawn.
+ */
+ void onFrameComplete(long frameNr);
+ }
+
private static class ProcessInitializer {
static ProcessInitializer sInstance = new ProcessInitializer();
@@ -1218,6 +1235,8 @@ public final class ThreadedRenderer {
private static native void nSetContentDrawBounds(long nativeProxy, int left,
int top, int right, int bottom);
private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+ private static native void nSetFrameCompleteCallback(long nativeProxy,
+ FrameCompleteCallback callback);
private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 48f380d87dcc..0506f30d04b8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3096,13 +3096,28 @@ public final class ViewRootImpl implements ViewParent,
return;
}
- final boolean fullRedrawNeeded = mFullRedrawNeeded;
+ final boolean fullRedrawNeeded = mFullRedrawNeeded || mReportNextDraw;
mFullRedrawNeeded = false;
mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
+
+ boolean usingAsyncReport = false;
+ if (mReportNextDraw && mAttachInfo.mThreadedRenderer != null
+ && mAttachInfo.mThreadedRenderer.isEnabled()) {
+ usingAsyncReport = true;
+ mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
+ // TODO: Use the frame number
+ pendingDrawFinished();
+ });
+ }
+
try {
- draw(fullRedrawNeeded);
+ boolean canUseAsync = draw(fullRedrawNeeded);
+ if (usingAsyncReport && !canUseAsync) {
+ mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null);
+ usingAsyncReport = false;
+ }
} finally {
mIsDrawing = false;
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
@@ -3132,7 +3147,6 @@ public final class ViewRootImpl implements ViewParent,
}
if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.fence();
mAttachInfo.mThreadedRenderer.setStopped(mStopped);
}
@@ -3145,16 +3159,19 @@ public final class ViewRootImpl implements ViewParent,
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
- } else {
+ } else if (!usingAsyncReport) {
+ if (mAttachInfo.mThreadedRenderer != null) {
+ mAttachInfo.mThreadedRenderer.fence();
+ }
pendingDrawFinished();
}
}
}
- private void draw(boolean fullRedrawNeeded) {
+ private boolean draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (!surface.isValid()) {
- return;
+ return false;
}
if (DEBUG_FPS) {
@@ -3203,7 +3220,7 @@ public final class ViewRootImpl implements ViewParent,
if (animating && mScroller != null) {
mScroller.abortAnimation();
}
- return;
+ return false;
}
if (fullRedrawNeeded) {
@@ -3250,6 +3267,7 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mDrawingTime =
mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
+ boolean useAsyncReport = false;
if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
// If accessibility focus moved, always invalidate the root.
@@ -3286,6 +3304,7 @@ public final class ViewRootImpl implements ViewParent,
requestDrawWindow();
}
+ useAsyncReport = true;
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this, mNextRtFrameCallback);
mNextRtFrameCallback = null;
} else {
@@ -3307,17 +3326,17 @@ public final class ViewRootImpl implements ViewParent,
mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
- return;
+ return false;
}
mFullRedrawNeeded = true;
scheduleTraversals();
- return;
+ return false;
}
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,
scalingRequired, dirty, surfaceInsets)) {
- return;
+ return false;
}
}
}
@@ -3326,6 +3345,7 @@ public final class ViewRootImpl implements ViewParent,
mFullRedrawNeeded = true;
scheduleTraversals();
}
+ return useAsyncReport;
}
/**
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7481f1c1fe53..ee9a123ab674 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -15,9 +15,11 @@
*/
#define LOG_TAG "ThreadedRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
#include <algorithm>
#include <atomic>
+#include <inttypes.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
@@ -37,6 +39,7 @@
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>
+#include <utils/TraceUtils.h>
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
@@ -72,6 +75,10 @@ struct {
jmethodID onFrameDraw;
} gFrameDrawingCallback;
+struct {
+ jmethodID onFrameComplete;
+} gFrameCompleteCallback;
+
static JNIEnv* getenv(JavaVM* vm) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
@@ -153,6 +160,49 @@ private:
std::string mMessage;
};
+class FrameCompleteWrapper : public MessageHandler {
+public:
+ FrameCompleteWrapper(JNIEnv* env, jobject jobject) {
+ mLooper = Looper::getForThread();
+ LOG_ALWAYS_FATAL_IF(!mLooper.get(), "Must create runnable on a Looper thread!");
+ env->GetJavaVM(&mVm);
+ mObject = env->NewGlobalRef(jobject);
+ LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
+ }
+
+ virtual ~FrameCompleteWrapper() {
+ releaseObject();
+ }
+
+ void postFrameComplete(int64_t frameNr) {
+ if (mObject) {
+ mFrameNr = frameNr;
+ mLooper->sendMessage(this, 0);
+ }
+ }
+
+ virtual void handleMessage(const Message&) {
+ if (mObject) {
+ ATRACE_FORMAT("frameComplete %" PRId64, mFrameNr);
+ getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, mFrameNr);
+ releaseObject();
+ }
+ }
+
+private:
+ JavaVM* mVm;
+ jobject mObject;
+ sp<Looper> mLooper;
+ int64_t mFrameNr = -1;
+
+ void releaseObject() {
+ if (mObject) {
+ getenv(mVm)->DeleteGlobalRef(mObject);
+ mObject = nullptr;
+ }
+ }
+};
+
class RootRenderNode : public RenderNode, ErrorHandler {
public:
explicit RootRenderNode(JNIEnv* env) : RenderNode() {
@@ -891,6 +941,19 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
}
}
+static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
+ jobject clazz, jlong proxyPtr, jobject callback) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ if (!callback) {
+ proxy->setFrameCompleteCallback(nullptr);
+ } else {
+ sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback};
+ proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) {
+ wrapper->postFrameComplete(frameNr);
+ });
+ }
+}
+
static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
jobject clazz, jobject jsurface, jint left, jint top,
jint right, jint bottom, jobject jbitmap) {
@@ -1091,6 +1154,8 @@ static const JNINativeMethod gMethods[] = {
{ "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
{ "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
(void*)android_view_ThreadedRenderer_setFrameCallback},
+ { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+ (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
{ "nAddFrameMetricsObserver",
"(JLandroid/view/FrameMetricsObserver;)J",
(void*)android_view_ThreadedRenderer_addFrameMetricsObserver },
@@ -1143,6 +1208,11 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {
gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
"onFrameDraw", "(J)V");
+ jclass frameCompleteClass = FindClassOrDie(env,
+ "android/view/ThreadedRenderer$FrameCompleteCallback");
+ gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
+ "onFrameComplete", "(J)V");
+
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0f04b5d16454..cb260b5b4b91 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -41,6 +41,7 @@ cc_defaults {
"external/skia/src/image",
"external/skia/src/utils",
"external/skia/src/gpu",
+ "external/skia/src/shaders",
],
product_variables: {
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 9c80ff86df53..3684bc1e6a1f 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -21,6 +21,11 @@
#include "RenderNode.h"
#include "SkAndroidFrameworkUtils.h"
#include "SkClipStack.h"
+#include "SkRect.h"
+#include "GrBackendSurface.h"
+#include "GrRenderTarget.h"
+#include "GrRenderTargetContext.h"
+#include "GrGLTypes.h"
namespace android {
namespace uirenderer {
@@ -44,6 +49,33 @@ static void setScissor(int viewportHeight, const SkIRect& clip) {
glScissor(clip.fLeft, y, clip.width(), height);
}
+static bool GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
+ GrRenderTargetContext *renderTargetContext =
+ canvas->internal_private_accessTopLayerRenderTargetContext();
+ if (!renderTargetContext) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ GrRenderTarget *renderTarget = renderTargetContext->accessRenderTarget();
+ if (!renderTarget) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ GrBackendRenderTarget backendTarget = renderTarget->getBackendRenderTarget();
+ const GrGLFramebufferInfo* fboInfo = backendTarget.getGLFramebufferInfo();
+
+ if (!fboInfo) {
+ ALOGW("Unable to extract renderTarget info from canvas; aborting GLFunctor draw");
+ return false;
+ }
+
+ *outFboID = fboInfo->fFBOID;
+ *outFboSize = SkISize::Make(renderTargetContext->width(), renderTargetContext->height());
+ return true;
+}
+
void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
if (canvas->getGrContext() == nullptr) {
SkDEBUGF(("Attempting to draw GLFunctor into an unsupported surface"));
@@ -55,41 +87,96 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
return;
}
- SkImageInfo canvasInfo = canvas->imageInfo();
+ GLuint fboID = 0;
+ SkISize fboSize;
+ if (!GetFboDetails(canvas, &fboID, &fboSize)) {
+ return;
+ }
+
+ SkIRect surfaceBounds = canvas->internal_private_getTopLayerBounds();
+ SkIRect clipBounds = canvas->getDeviceClipBounds();
SkMatrix44 mat4(canvas->getTotalMatrix());
+ SkRegion clipRegion;
+ canvas->temporary_internal_getRgnClip(&clipRegion);
+
+ sk_sp<SkSurface> tmpSurface;
+ // we are in a state where there is an unclipped saveLayer
+ if (fboID != 0 && !surfaceBounds.contains(clipBounds)) {
- SkIRect ibounds = canvas->getDeviceClipBounds();
+ // create an offscreen layer and clear it
+ SkImageInfo surfaceInfo = canvas->imageInfo().makeWH(clipBounds.width(), clipBounds.height());
+ tmpSurface = SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kYes,
+ surfaceInfo);
+ tmpSurface->getCanvas()->clear(SK_ColorTRANSPARENT);
+
+ GrBackendObject backendObject;
+ if (!tmpSurface->getRenderTargetHandle(&backendObject, SkSurface::kFlushWrite_BackendHandleAccess)) {
+ ALOGW("Unable to extract renderTarget info from offscreen canvas; aborting GLFunctor");
+ return;
+ }
+
+ fboSize = SkISize::Make(surfaceInfo.width(), surfaceInfo.height());
+ fboID = (GLuint)backendObject;
+
+ // update the matrix and clip that we pass to the WebView to match the coordinates of
+ // the offscreen layer
+ mat4.preTranslate(-clipBounds.fLeft, -clipBounds.fTop, 0);
+ clipBounds.offsetTo(0, 0);
+ clipRegion.translate(-surfaceBounds.fLeft, -surfaceBounds.fTop);
+
+ } else if (fboID != 0) {
+ // we are drawing into a (clipped) offscreen layer so we must update the clip and matrix
+ // from device coordinates to the layer's coordinates
+ clipBounds.offset(-surfaceBounds.fLeft, -surfaceBounds.fTop);
+ mat4.preTranslate(-surfaceBounds.fLeft, -surfaceBounds.fTop, 0);
+ }
DrawGlInfo info;
- info.clipLeft = ibounds.fLeft;
- info.clipTop = ibounds.fTop;
- info.clipRight = ibounds.fRight;
- info.clipBottom = ibounds.fBottom;
- // info.isLayer = hasLayer();
- info.isLayer = false;
- info.width = canvasInfo.width();
- info.height = canvasInfo.height();
+ info.clipLeft = clipBounds.fLeft;
+ info.clipTop = clipBounds.fTop;
+ info.clipRight = clipBounds.fRight;
+ info.clipBottom = clipBounds.fBottom;
+ info.isLayer = fboID != 0;
+ info.width = fboSize.width();
+ info.height = fboSize.height();
mat4.asColMajorf(&info.transform[0]);
- bool clearStencilAfterFunctor = false;
-
- // apply a simple clip with a scissor or a complex clip with a stencil
- SkRegion clipRegion;
- canvas->temporary_internal_getRgnClip(&clipRegion);
+ // ensure that the framebuffer that the webview will render into is bound before we clear
+ // the stencil and/or draw the functor.
canvas->flush();
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, info.width, info.height);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+
+ // apply a simple clip with a scissor or a complex clip with a stencil
+ bool clearStencilAfterFunctor = false;
if (CC_UNLIKELY(clipRegion.isComplex())) {
+ // clear the stencil
//TODO: move stencil clear and canvas flush to SkAndroidFrameworkUtils::clipWithStencil
glDisable(GL_SCISSOR_TEST);
glStencilMask(0x1);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
+
+ // notify Skia that we just updated the FBO and stencil
+ const uint32_t grState = kStencil_GrGLBackendState | kRenderTarget_GrGLBackendState;
+ canvas->getGrContext()->resetContext(grState);
+
+ SkCanvas* tmpCanvas = canvas;
+ if (tmpSurface) {
+ tmpCanvas = tmpSurface->getCanvas();
+ // set the clip on the new canvas
+ tmpCanvas->clipRegion(clipRegion);
+ }
+
// GL ops get inserted here if previous flush is missing, which could dirty the stencil
- bool stencilWritten = SkAndroidFrameworkUtils::clipWithStencil(canvas);
- canvas->flush(); //need this flush for the single op that draws into the stencil
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ bool stencilWritten = SkAndroidFrameworkUtils::clipWithStencil(tmpCanvas);
+ tmpCanvas->flush(); //need this flush for the single op that draws into the stencil
+
+ // ensure that the framebuffer that the webview will render into is bound before after we
+ // draw into the stencil
glViewport(0, 0, info.width, info.height);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+
if (stencilWritten) {
glStencilMask(0x1);
glStencilFunc(GL_EQUAL, 0x1, 0x1);
@@ -120,6 +207,20 @@ void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
}
canvas->getGrContext()->resetContext();
+
+ // if there were unclipped save layers involved we draw our offscreen surface to the canvas
+ if (tmpSurface) {
+ SkAutoCanvasRestore acr(canvas, true);
+ SkMatrix invertedMatrix;
+ if (!canvas->getTotalMatrix().invert(&invertedMatrix)) {
+ ALOGW("Unable to extract invert canvas matrix; aborting GLFunctor draw");
+ return;
+ }
+ canvas->concat(invertedMatrix);
+
+ const SkIRect deviceBounds = canvas->getDeviceClipBounds();
+ tmpSurface->draw(canvas, deviceBounds.fLeft, deviceBounds.fTop, nullptr);
+ }
}
}; // namespace skiapipeline
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2ddf55be7574..aed0620166dd 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -46,6 +46,7 @@
#include <algorithm>
#include <cstdlib>
+#include <functional>
#define TRIM_MEMORY_COMPLETE 80
#define TRIM_MEMORY_UI_HIDDEN 20
@@ -383,6 +384,12 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
info.out.canDrawThisFrame = true;
}
+ // TODO: Do we need to abort out if the backdrop is added but not ready? Should that even
+ // be an allowable combination?
+ if (mRenderNodes.size() > 2 && !mRenderNodes[1]->isRenderable()) {
+ info.out.canDrawThisFrame = false;
+ }
+
if (!info.out.canDrawThisFrame) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
}
@@ -449,6 +456,8 @@ void CanvasContext::draw() {
mContentDrawBounds, mOpaque, mWideColorGamut, mLightInfo,
mRenderNodes, &(profiler()));
+ int64_t frameCompleteNr = mFrameCompleteCallbacks.size() ? getFrameNumber() : -1;
+
waitOnFences();
bool requireSwap = false;
@@ -509,6 +518,13 @@ void CanvasContext::draw() {
}
#endif
+ if (didSwap) {
+ for (auto& func : mFrameCompleteCallbacks) {
+ std::invoke(func, frameCompleteNr);
+ }
+ mFrameCompleteCallbacks.clear();
+ }
+
mJankTracker.finishFrame(*mCurrentFrameInfo);
if (CC_UNLIKELY(mFrameMetricsReporter.get() != nullptr)) {
mFrameMetricsReporter->reportFrameMetrics(mCurrentFrameInfo->data());
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e52b6447a611..1c4e02d7df70 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -190,6 +190,10 @@ public:
IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); }
+ void addFrameCompleteListener(std::function<void(int64_t)>&& func) {
+ mFrameCompleteCallbacks.push_back(std::move(func));
+ }
+
private:
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
@@ -267,6 +271,8 @@ private:
std::vector<sp<FuncTask>> mFrameFences;
sp<TaskProcessor<bool>> mFrameWorkProcessor;
std::unique_ptr<IRenderPipeline> mRenderPipeline;
+
+ std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 60df514ecc2b..51eeab7e46ce 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -90,6 +90,11 @@ void DrawFrameTask::run() {
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
canUnblockUiThread = syncFrameState(info);
canDrawThisFrame = info.out.canDrawThisFrame;
+
+ if (mFrameCompleteCallback) {
+ mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback));
+ mFrameCompleteCallback = nullptr;
+ }
}
// Grab a copy of everything we need
@@ -152,6 +157,9 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mSyncResult |= SyncResult::UIRedrawRequired;
}
}
+ if (!info.out.canDrawThisFrame) {
+ mSyncResult |= SyncResult::FrameDropped;
+ }
// If prepareTextures is false, we ran out of texture cache space
return info.prepareTextures;
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index d8c43e0d8ca8..2c46762fee5c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -46,6 +46,7 @@ enum {
UIRedrawRequired = 1 << 0,
LostSurfaceRewardIfFound = 1 << 1,
ContextIsStopped = 1 << 2,
+ FrameDropped = 1 << 3,
};
}
@@ -78,6 +79,10 @@ public:
mFrameCallback = std::move(callback);
}
+ void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mFrameCompleteCallback = std::move(callback);
+ }
+
private:
void postAndWait();
bool syncFrameState(TreeInfo& info);
@@ -102,6 +107,7 @@ private:
int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
std::function<void(int64_t)> mFrameCallback;
+ std::function<void(int64_t)> mFrameCompleteCallback;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index c6a9b55f8ac1..59048be768e9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -274,6 +274,10 @@ void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) {
mDrawFrameTask.setFrameCallback(std::move(callback));
}
+void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) {
+ mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
+}
+
void RenderProxy::serializeDisplayListTree() {
mRenderThread.queue().post([=]() { mContext->serializeDisplayListTree(); });
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 3425c5c68a72..ad534f0d96b5 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -116,6 +116,7 @@ public:
ANDROID_API void drawRenderNode(RenderNode* node);
ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
ANDROID_API void setFrameCallback(std::function<void(int64_t)>&& callback);
+ ANDROID_API void setFrameCompleteCallback(std::function<void(int64_t)>&& callback);
ANDROID_API void addFrameMetricsObserver(FrameMetricsObserver* observer);
ANDROID_API void removeFrameMetricsObserver(FrameMetricsObserver* observer);
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 03afdb659f21..4a55a99d0d93 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -25,7 +25,7 @@
<item msgid="8934131797783724664">"Trwa skanowanie..."</item>
<item msgid="8513729475867537913">"Trwa łączenie..."</item>
<item msgid="515055375277271756">"Trwa uwierzytelnianie..."</item>
- <item msgid="1943354004029184381">"Uzyskiwanie adresu IP..."</item>
+ <item msgid="1943354004029184381">"Uzyskuję adres IP..."</item>
<item msgid="4221763391123233270">"Połączono"</item>
<item msgid="624838831631122137">"Zawieszona"</item>
<item msgid="7979680559596111948">"Trwa rozłączanie..."</item>
@@ -39,7 +39,7 @@
<item msgid="8878186979715711006">"Trwa skanowanie..."</item>
<item msgid="355508996603873860">"Trwa łączenie z siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
<item msgid="554971459996405634">"Trwa uwierzytelnianie w sieci <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
- <item msgid="7928343808033020343">"Uzyskiwanie adresu IP z sieci <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
+ <item msgid="7928343808033020343">"Uzyskuję adres IP z sieci <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
<item msgid="8937994881315223448">"Połączono z siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item>
<item msgid="1330262655415760617">"Zawieszona"</item>
<item msgid="7698638434317271902">"Trwa rozłączanie z siecią <xliff:g id="NETWORK_NAME">%1$s</xliff:g>..."</item>
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 92ce28c30b74..f157cc4bffd3 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1405,6 +1405,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
newIntents.add(intent);
}
+ final boolean isSleeping() {
+ final ActivityStack stack = getStack();
+ return stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked();
+ }
+
/**
* Deliver a new Intent to an existing activity, so that its onNewIntent()
* method will be called at the proper time.
@@ -1415,9 +1420,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
intent, getUriPermissionsLocked(), userId);
final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
boolean unsent = true;
- final ActivityStack stack = getStack();
- final boolean isTopActivityWhileSleeping = isTopRunningActivity()
- && (stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked());
+ final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
// We want to immediately deliver the intent to the activity if:
// - It is currently resumed or paused. i.e. it is currently visible to the user and we want
@@ -1645,7 +1648,10 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
parent.onActivityStateChanged(this, state, reason);
}
- if (state == STOPPING) {
+ // The WindowManager interprets the app stopping signal as
+ // an indication that the Surface will eventually be destroyed.
+ // This however isn't necessarily true if we are going to sleep.
+ if (state == STOPPING && !isSleeping()) {
mWindowContainerController.notifyAppStopping();
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3ad461f9b1b0..748eae951379 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -134,7 +134,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.Trace;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.ArraySet;
@@ -4789,6 +4788,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
+ void onPipAnimationEndResize() {
+ mWindowContainerController.onPipAnimationEndResize();
+ }
+
/**
* Adjust bounds to stay within stack bounds.
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 257d79d2c153..76cc3425d060 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2968,6 +2968,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
insetBounds.right = tempPinnedTaskBounds.width();
insetBounds.bottom = tempPinnedTaskBounds.height();
}
+ if (pinnedBounds != null && tempPinnedTaskBounds == null) {
+ // We have finished the animation into PiP, and are resizing the tasks to match the
+ // stack bounds, while layouts are deferred, update any task state as a part of
+ // transitioning it from fullscreen into a floating state.
+ stack.onPipAnimationEndResize();
+ }
stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds);
stack.ensureVisibleActivitiesConfigurationLocked(r, false);
} finally {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 9a5b1a60219e..d3ac7cb15824 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1606,6 +1606,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
boolean topActivity = true;
for (--activityNdx; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = mActivities.get(activityNdx);
+ if (r.mTaskOverlay) {
+ continue;
+ }
if (r.taskDescription != null) {
if (label == null) {
label = r.taskDescription.getLabel();
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index 5ed14a07cb6c..6371d777aeb7 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -185,7 +185,12 @@ public class TetherInterfaceStateMachine extends StateMachine {
private boolean startIPv4() { return configureIPv4(true); }
- private void stopIPv4() { configureIPv4(false); }
+ private void stopIPv4() {
+ configureIPv4(false);
+ // NOTE: All of configureIPv4() will be refactored out of existence
+ // into calls to InterfaceController, shared with startIPv4().
+ mInterfaceCtrl.clearIPv4Address();
+ }
// TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7b7bc41e4bbb..605644eb4d39 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7997,6 +7997,13 @@ public class PackageManagerService extends IPackageManager.Stub
flags = updateFlagsForApplication(flags, userId, null);
final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
+ mPermissionManager.enforceCrossUserPermission(
+ callingUid,
+ userId,
+ false /* requireFullPermission */,
+ false /* checkShell */,
+ "get installed application info");
+
// writer
synchronized (mPackages) {
ArrayList<ApplicationInfo> list;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7ffd5ed07a31..03e34d3070ab 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -549,7 +549,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mGoingToSleep;
volatile boolean mRequestedOrGoingToSleep;
volatile boolean mRecentsVisible;
- volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled;
+ volatile boolean mNavBarVirtualKeyHapticFeedbackEnabled = true;
volatile boolean mPictureInPictureVisible;
// Written by vr manager thread, only read in this class.
volatile private boolean mPersistentVrModeEnabled;
@@ -5761,11 +5761,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mStatusBarController.updateVisibilityLw(false /*transientAllowed*/,
mLastSystemUiFlags, mLastSystemUiFlags);
}
- if (statusBarExpanded && mNavigationBar != null) {
- if (mNavigationBarController.setBarShowingLw(true)) {
- changes |= FINISH_LAYOUT_REDO_LAYOUT;
- }
- }
} else if (mTopFullscreenOpaqueWindowState != null) {
topIsFullscreen = topAppHidesStatusBar;
// The subtle difference between the window for mTopFullscreenOpaqueWindowState
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 653850aa288f..1fd2c0fd19c5 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -192,6 +192,12 @@ public class StackWindowController
}
}
+ public void onPipAnimationEndResize() {
+ synchronized (mService.mWindowMap) {
+ mContainer.onPipAnimationEndResize();
+ }
+ }
+
/**
* @see TaskStack.getStackDockedModeBoundsLocked(Rect, Rect, Rect, boolean)
*/
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 2fbb84604598..c59540b3d088 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1667,16 +1667,6 @@ public class TaskStack extends WindowContainer<Task> implements
@Override // AnimatesBounds
public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
boolean moveToFullscreen) {
- // Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mService.mWindowMap) {
- mBoundsAnimating = false;
- for (int i = 0; i < mChildren.size(); i++) {
- final Task t = mChildren.get(i);
- t.clearPreserveNonFloatingState();
- }
- mService.requestTraversal();
- }
-
if (inPinnedWindowingMode()) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1706,6 +1696,18 @@ public class TaskStack extends WindowContainer<Task> implements
}
}
+ /**
+ * Called immediately prior to resizing the tasks at the end of the pinned stack animation.
+ */
+ public void onPipAnimationEndResize() {
+ mBoundsAnimating = false;
+ for (int i = 0; i < mChildren.size(); i++) {
+ final Task t = mChildren.get(i);
+ t.clearPreserveNonFloatingState();
+ }
+ mService.requestTraversal();
+ }
+
@Override
public boolean shouldDeferStartOnMoveToFullscreen() {
// Workaround for the recents animation -- normally we need to wait for the new activity to
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index b5c018a452a4..da4da79a39df 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -664,9 +664,6 @@ public class MbmsDownloadSession implements AutoCloseable {
* If the operation encountered an error, the error code will be delivered via
* {@link MbmsDownloadSessionCallback#onError}.
*
- * Repeated calls to this method for the same {@link DownloadRequest} will replace the
- * previously registered listener.
- *
* @param request The {@link DownloadRequest} provided during registration
* @param listener The listener provided during registration.
*/
@@ -726,6 +723,9 @@ public class MbmsDownloadSession implements AutoCloseable {
* If the operation encountered an error, the error code will be delivered via
* {@link MbmsDownloadSessionCallback#onError}.
*
+ * Repeated calls to this method for the same {@link DownloadRequest} will replace the
+ * previously registered listener.
+ *
* @param request The {@link DownloadRequest} that you want updates on.
* @param executor The {@link Executor} on which calls to {@code listener} should be executed.
* @param listener The listener that should be called when the middleware has information to
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index d643c69c0e44..f0f3f2c748a0 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -775,11 +775,12 @@ public class TetheringTest {
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
- // We verify get/set called twice here: once for setup and once during
+ // We verify get/set called thrice here: once for setup and twice during
// teardown because all events happen over the course of the single
- // dispatchAll() above.
+ // dispatchAll() above. Note that once the TISM IPv4 address config
+ // code is refactored the two calls during shutdown will revert to one.
verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
- verify(mNMService, times(2))
+ verify(mNMService, times(3))
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
verify(mWifiManager).updateInterfaceIpState(
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
index 7c77cf59524d..19d3a2e11904 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
@@ -173,6 +173,7 @@ public class TetherInterfaceStateMachineTest {
dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
inOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mTetherHelper).updateLinkProperties(
@@ -270,6 +271,7 @@ public class TetherInterfaceStateMachineTest {
inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
+ inOrder.verify(mNMService).setInterfaceConfig(eq(IFACE_NAME), any());
inOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mTetherHelper).updateLinkProperties(