Bug 1753700 - Add priorityHint to allow apps to increase process priority for background tabs r=geckoview-reviewers,mccr8,agi

Prior behavior for active tabs in an inactive app would have the process priority oom score of 15. Now it's set to a higher priority oom score of 11. This will increase priority for recently used tabs on apps and prevent Android from unloading them.

Differential Revision: https://phabricator.services.mozilla.com/D142386
This commit is contained in:
Cathy Lu 2022-04-04 17:41:37 +00:00
parent 8dca7903a8
commit b5b91ffc69
8 changed files with 110 additions and 5 deletions

View File

@ -25,6 +25,12 @@ interface nsIRemoteTab : nsISupports
*/
readonly attribute boolean hasLayers;
/**
* When set to true, this priority hint indicates that the content
* processes of this tab should be set to a higher process priority.
*/
attribute boolean priorityHint;
/**
* Adjusts the tab's active state in the process priority manager,
* allowing its process to be given a lower priority.

View File

@ -119,8 +119,11 @@ BrowserHost::SetRenderLayers(bool aRenderLayers) {
if (!mRoot) {
return NS_OK;
}
bool priorityHint;
GetPriorityHint(&priorityHint);
ProcessPriorityManager::BrowserPriorityChanged(
GetBrowsingContext()->Canonical(), aRenderLayers);
GetBrowsingContext()->Canonical(), priorityHint || aRenderLayers);
mRoot->SetRenderLayers(aRenderLayers);
return NS_OK;
}
@ -136,6 +139,30 @@ BrowserHost::GetHasLayers(bool* aHasLayers) {
return NS_OK;
}
/* attribute boolean priorityHint; */
NS_IMETHODIMP
BrowserHost::SetPriorityHint(bool aPriorityHint) {
if (!mRoot) {
return NS_OK;
}
bool renderLayers;
GetRenderLayers(&renderLayers);
ProcessPriorityManager::BrowserPriorityChanged(
GetBrowsingContext()->Canonical(), aPriorityHint || renderLayers);
mRoot->SetPriorityHint(aPriorityHint);
return NS_OK;
}
NS_IMETHODIMP
BrowserHost::GetPriorityHint(bool* aPriorityHint) {
if (!mRoot) {
*aPriorityHint = false;
return NS_OK;
}
*aPriorityHint = mRoot->GetPriorityHint();
return NS_OK;
}
/* void resolutionChanged (); */
NS_IMETHODIMP
BrowserHost::NotifyResolutionChanged(void) {

View File

@ -231,6 +231,7 @@ BrowserParent::BrowserParent(ContentParent* aManager, const TabId& aTabId,
mRemoteTargetSetsCursor(false),
mIsPreservingLayers(false),
mRenderLayers(true),
mPriorityHint(false),
mHasLayers(false),
mHasPresented(false),
mIsReadyToHandleInputEvents(false),
@ -3477,6 +3478,12 @@ void BrowserParent::SetRenderLayersInternal(bool aEnabled) {
}
}
bool BrowserParent::GetPriorityHint() { return mPriorityHint; }
void BrowserParent::SetPriorityHint(bool aPriorityHint) {
mPriorityHint = aPriorityHint;
}
void BrowserParent::PreserveLayers(bool aPreserveLayers) {
if (mIsPreservingLayers == aPreserveLayers) {
return;

View File

@ -706,6 +706,8 @@ class BrowserParent final : public PBrowserParent,
bool GetHasLayers();
bool GetRenderLayers();
void SetRenderLayers(bool aRenderLayers);
bool GetPriorityHint();
void SetPriorityHint(bool aPriorityHint);
void PreserveLayers(bool aPreserveLayers);
void NotifyResolutionChanged();
@ -963,6 +965,9 @@ class BrowserParent final : public PBrowserParent,
// and have uploaded - for that, use mHasLayers.
bool mRenderLayers : 1;
// True if process should be set to a higher priority.
bool mPriorityHint : 1;
// True if the compositor has reported that the BrowserChild has uploaded
// layers.
bool mHasLayers : 1;

View File

@ -336,7 +336,7 @@ class ParticularProcessPriorityManager final : public WakeLockObserver,
nsCOMPtr<nsITimer> mResetPriorityTimer;
// This hashtable contains the list of active TabId for this process.
// This hashtable contains the list of high priority TabIds for this process.
nsTHashSet<uint64_t> mHighPriorityBrowserParents;
};

View File

@ -73,7 +73,7 @@ class ProcessPriorityManager final {
/**
* Updates the contents of mHighPriorityBrowserParents to keep track of
* the list of TabIds for this process that are active.
* the list of TabIds for this process that are high priority.
*/
static void BrowserPriorityChanged(dom::CanonicalBrowsingContext* aBC,
bool aPriority);

View File

@ -286,8 +286,9 @@ async function assertPriorityChangeOnBackground({
/**
* Test that if a normal tab goes into the background,
* it has its process priority lowered to
* PROCESS_PRIORITY_BACKGROUND.
* it has its process priority lowered to PROCESS_PRIORITY_BACKGROUND.
* Additionally, test priorityHint flag sets the process priority
* appropriately to PROCESS_PRIORITY_BACKGROUND and PROCESS_PRIORITY_FOREGROUND.
*/
add_task(async function test_normal_background_tab() {
let originalTab = gBrowser.selectedTab;
@ -307,6 +308,62 @@ add_task(async function test_normal_background_tab() {
toTab: tab,
fromTabExpectedPriority: PROCESS_PRIORITY_BACKGROUND,
});
let origtabID = browsingContextChildID(
originalTab.linkedBrowser.browsingContext
);
Assert.equal(
originalTab.linkedBrowser.frameLoader.remoteTab.priorityHint,
false,
"PriorityHint of the original tab should be false on default"
);
// Test when priorityHint is true, the original tab priority
// becomes PROCESS_PRIORITY_FOREGROUND.
originalTab.linkedBrowser.frameLoader.remoteTab.priorityHint = true;
Assert.equal(
gTabPriorityWatcher.currentPriority(origtabID),
PROCESS_PRIORITY_FOREGROUND,
"Setting priorityHint to true should set the original tab to foreground priority"
);
// Test when priorityHint is false, the original tab priority
// becomes PROCESS_PRIORITY_BACKGROUND.
originalTab.linkedBrowser.frameLoader.remoteTab.priorityHint = false;
await new Promise(resolve =>
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
setTimeout(resolve, WAIT_FOR_CHANGE_TIME_MS)
);
Assert.equal(
gTabPriorityWatcher.currentPriority(origtabID),
PROCESS_PRIORITY_BACKGROUND,
"Setting priorityHint to false should set the original tab to background priority"
);
let tabID = browsingContextChildID(tab.linkedBrowser.browsingContext);
Assert.equal(
tab.linkedBrowser.frameLoader.remoteTab.priorityHint,
false,
"PriorityHint of the active tab should be false on default"
);
// Test when priorityHint is true, the process priority of the
// active tab remains PROCESS_PRIORITY_FOREGROUND.
tab.linkedBrowser.frameLoader.remoteTab.priorityHint = true;
Assert.equal(
gTabPriorityWatcher.currentPriority(tabID),
PROCESS_PRIORITY_FOREGROUND,
"Setting priorityHint to true should maintain the new tab priority as foreground"
);
// Test when priorityHint is false, the process priority of the
// active tab remains PROCESS_PRIORITY_FOREGROUND.
tab.linkedBrowser.frameLoader.remoteTab.priorityHint = false;
Assert.equal(
gTabPriorityWatcher.currentPriority(tabID),
PROCESS_PRIORITY_FOREGROUND,
"Setting priorityHint to false should maintain the new tab priority as foreground"
);
}
);
});

View File

@ -544,6 +544,9 @@ class MobileWindowTracker extends EventEmitter {
setTabActive(aWindow, aActive) {
const { browser, tab, docShell } = aWindow;
tab.active = aActive;
if (browser.frameLoader.remoteTab) {
browser.frameLoader.remoteTab.priorityHint = aActive;
}
if (aActive) {
this._topWindow = Cu.getWeakReference(aWindow);