Merge "Correct context for TB on disabled tiles"
diff --git a/Android.bp b/Android.bp
index 88b2473..25e738c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -731,8 +731,10 @@
"netd_aidl_interface-java",
],
- // Loaded with System.loadLibrary by android.view.textclassifier
required: [
+ // TODO: remove gps_debug when the build system propagates "required" properly.
+ "gps_debug.conf",
+ // Loaded with System.loadLibrary by android.view.textclassifier
"libmedia2_jni",
],
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 5936ee4..e731138 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,7 +5,9 @@
strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT}
-hidden_api_txt_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
+hidden_api_txt_checksorted_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
+
+hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
diff --git a/api/current.txt b/api/current.txt
index 115c1c1..9d46863 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3803,6 +3803,7 @@
method public void overridePendingTransition(int, int);
method public void postponeEnterTransition();
method public void recreate();
+ method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
method public void registerForContextMenu(android.view.View);
method public boolean releaseInstance();
method public final deprecated void removeDialog(int);
@@ -3880,6 +3881,7 @@
method public deprecated void stopManagingCursor(android.database.Cursor);
method public void takeKeyEvents(boolean);
method public void triggerSearch(java.lang.String, android.os.Bundle);
+ method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
method public void unregisterForContextMenu(android.view.View);
field public static final int DEFAULT_KEYS_DIALER = 1; // 0x1
field public static final int DEFAULT_KEYS_DISABLE = 0; // 0x0
@@ -6511,6 +6513,7 @@
}
public class DevicePolicyManager {
+ method public void addCrossProfileCalendarPackage(android.content.ComponentName, java.lang.String);
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
method public int addOverrideApn(android.content.ComponentName, android.telephony.data.ApnSetting);
@@ -6540,6 +6543,7 @@
method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
method public boolean getCameraDisabled(android.content.ComponentName);
method public deprecated java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
+ method public java.util.Set<java.lang.String> getCrossProfileCalendarPackages(android.content.ComponentName);
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
@@ -6628,6 +6632,7 @@
method public int logoutUser(android.content.ComponentName);
method public void reboot(android.content.ComponentName);
method public void removeActiveAdmin(android.content.ComponentName);
+ method public boolean removeCrossProfileCalendarPackage(android.content.ComponentName, java.lang.String);
method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
method public boolean removeKeyPair(android.content.ComponentName, java.lang.String);
method public boolean removeOverrideApn(android.content.ComponentName, int);
@@ -13940,6 +13945,7 @@
}
public final class Insets {
+ method public static android.graphics.Insets add(android.graphics.Insets, android.graphics.Insets);
method public static android.graphics.Insets of(int, int, int, int);
method public static android.graphics.Insets of(android.graphics.Rect);
field public static final android.graphics.Insets NONE;
@@ -23461,6 +23467,7 @@
}
public class ExifInterface {
+ ctor public ExifInterface(java.io.File) throws java.io.IOException;
ctor public ExifInterface(java.lang.String) throws java.io.IOException;
ctor public ExifInterface(java.io.FileDescriptor) throws java.io.IOException;
ctor public ExifInterface(java.io.InputStream) throws java.io.IOException;
@@ -23468,11 +23475,13 @@
method public java.lang.String getAttribute(java.lang.String);
method public double getAttributeDouble(java.lang.String, double);
method public int getAttributeInt(java.lang.String, int);
+ method public long[] getAttributeRange(java.lang.String);
method public boolean getLatLong(float[]);
method public byte[] getThumbnail();
method public android.graphics.Bitmap getThumbnailBitmap();
method public byte[] getThumbnailBytes();
method public long[] getThumbnailRange();
+ method public boolean hasAttribute(java.lang.String);
method public boolean hasThumbnail();
method public boolean isThumbnailCompressed();
method public void saveAttributes() throws java.io.IOException;
@@ -29483,7 +29492,10 @@
method public void removeLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
+ method public void requestDiscoveryState(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.DiscoveryStateListener);
method public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
+ method public void requestNetworkInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.NetworkInfoListener);
+ method public void requestP2pState(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.P2pStateListener);
method public void requestPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.PeerListListener);
method public void setDnsSdResponseListeners(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener, android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener);
method public void setServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ServiceResponseListener);
@@ -29528,6 +29540,10 @@
method public abstract void onConnectionInfoAvailable(android.net.wifi.p2p.WifiP2pInfo);
}
+ public static abstract interface WifiP2pManager.DiscoveryStateListener {
+ method public abstract void onDiscoveryStateAvailable(int);
+ }
+
public static abstract interface WifiP2pManager.DnsSdServiceResponseListener {
method public abstract void onDnsSdServiceAvailable(java.lang.String, java.lang.String, android.net.wifi.p2p.WifiP2pDevice);
}
@@ -29540,6 +29556,14 @@
method public abstract void onGroupInfoAvailable(android.net.wifi.p2p.WifiP2pGroup);
}
+ public static abstract interface WifiP2pManager.NetworkInfoListener {
+ method public abstract void onNetworkInfoAvailable(android.net.NetworkInfo);
+ }
+
+ public static abstract interface WifiP2pManager.P2pStateListener {
+ method public abstract void onP2pStateAvailable(int);
+ }
+
public static abstract interface WifiP2pManager.PeerListListener {
method public abstract void onPeersAvailable(android.net.wifi.p2p.WifiP2pDeviceList);
}
@@ -37391,6 +37415,17 @@
field public static final java.lang.String ENTRY_CONTENT_TYPE = "vnd.android.cursor.item/radio";
}
+ public static abstract interface MediaStore.DownloadColumns implements android.provider.MediaStore.MediaColumns {
+ field public static final java.lang.String DOWNLOAD_URI = "download_uri";
+ field public static final java.lang.String REFERER_URI = "referer_uri";
+ }
+
+ public static final class MediaStore.Downloads implements android.provider.MediaStore.DownloadColumns {
+ method public static android.net.Uri getContentUri(java.lang.String);
+ field public static final android.net.Uri EXTERNAL_CONTENT_URI;
+ field public static final android.net.Uri INTERNAL_CONTENT_URI;
+ }
+
public static final class MediaStore.Files {
ctor public MediaStore.Files();
method public static android.net.Uri getContentUri(java.lang.String);
@@ -37482,7 +37517,9 @@
public static class MediaStore.PendingParams {
ctor public MediaStore.PendingParams(android.net.Uri, java.lang.String, java.lang.String);
+ method public void setDownloadUri(android.net.Uri);
method public void setPrimaryDirectory(java.lang.String);
+ method public void setRefererUri(android.net.Uri);
method public void setSecondaryDirectory(java.lang.String);
}
@@ -49246,6 +49283,7 @@
method public void setLayoutDirection(int);
method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
method public final void setLeft(int);
+ method public void setLeftTopRightBottom(int, int, int, int);
method public void setLongClickable(boolean);
method protected final void setMeasuredDimension(int, int);
method public void setMinimumHeight(int);
@@ -55489,6 +55527,7 @@
method public java.lang.CharSequence getText();
method public android.view.textclassifier.TextClassifier getTextClassifier();
method public final android.content.res.ColorStateList getTextColors();
+ method public android.text.TextDirectionHeuristic getTextDirectionHeuristic();
method public java.util.Locale getTextLocale();
method public android.os.LocaleList getTextLocales();
method public android.text.PrecomputedText.Params getTextMetricsParams();
diff --git a/api/system-current.txt b/api/system-current.txt
index a53ab3e..257b4f6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -158,6 +158,7 @@
field public static final java.lang.String REAL_GET_TASKS = "android.permission.REAL_GET_TASKS";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
field public static final java.lang.String RECEIVE_DATA_ACTIVITY_CHANGE = "android.permission.RECEIVE_DATA_ACTIVITY_CHANGE";
+ field public static final java.lang.String RECEIVE_DEVICE_CUSTOMIZATION_READY = "android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY";
field public static final java.lang.String RECEIVE_EMERGENCY_BROADCAST = "android.permission.RECEIVE_EMERGENCY_BROADCAST";
field public static final java.lang.String RECEIVE_WIFI_CREDENTIAL_CHANGE = "android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE";
field public static final java.lang.String RECOVERY = "android.permission.RECOVERY";
@@ -171,6 +172,7 @@
field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
+ field public static final java.lang.String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
field public static final java.lang.String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final java.lang.String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
@@ -1055,6 +1057,7 @@
field public static final java.lang.String ACTION_BATTERY_LEVEL_CHANGED = "android.intent.action.BATTERY_LEVEL_CHANGED";
field public static final java.lang.String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
field public static final java.lang.String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
+ field public static final java.lang.String ACTION_DEVICE_CUSTOMIZATION_READY = "android.intent.action.DEVICE_CUSTOMIZATION_READY";
field public static final java.lang.String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";
field public static final java.lang.String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
@@ -1234,6 +1237,7 @@
method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public void replacePreferredActivity(android.content.IntentFilter, int, java.util.List<android.content.ComponentName>, android.content.ComponentName);
method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
+ method public void sendDeviceCustomizationReadyBroadcast();
method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
method public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence);
method public deprecated java.lang.String[] setPackagesSuspended(java.lang.String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, java.lang.String);
@@ -1820,9 +1824,19 @@
field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
}
+ public class ContextHubIntentEvent {
+ method public static android.hardware.location.ContextHubIntentEvent fromIntent(android.content.Intent);
+ method public android.hardware.location.ContextHubInfo getContextHubInfo();
+ method public int getEventType();
+ method public int getNanoAppAbortCode();
+ method public long getNanoAppId();
+ method public android.hardware.location.NanoAppMessage getNanoAppMessage();
+ }
+
public final class ContextHubManager {
method public android.hardware.location.ContextHubClient createClient(android.hardware.location.ContextHubInfo, android.hardware.location.ContextHubClientCallback, java.util.concurrent.Executor);
method public android.hardware.location.ContextHubClient createClient(android.hardware.location.ContextHubInfo, android.hardware.location.ContextHubClientCallback);
+ method public android.hardware.location.ContextHubClient createClient(android.hardware.location.ContextHubInfo, android.app.PendingIntent, long);
method public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(android.hardware.location.ContextHubInfo, long);
method public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(android.hardware.location.ContextHubInfo, long);
method public deprecated int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
@@ -1839,6 +1853,18 @@
method public deprecated int unloadNanoApp(int);
method public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(android.hardware.location.ContextHubInfo, long);
method public deprecated int unregisterCallback(android.hardware.location.ContextHubManager.Callback);
+ field public static final int EVENT_HUB_RESET = 6; // 0x6
+ field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4
+ field public static final int EVENT_NANOAPP_DISABLED = 3; // 0x3
+ field public static final int EVENT_NANOAPP_ENABLED = 2; // 0x2
+ field public static final int EVENT_NANOAPP_LOADED = 0; // 0x0
+ field public static final int EVENT_NANOAPP_MESSAGE = 5; // 0x5
+ field public static final int EVENT_NANOAPP_UNLOADED = 1; // 0x1
+ field public static final java.lang.String EXTRA_CONTEXT_HUB_INFO = "android.hardware.location.extra.CONTEXT_HUB_INFO";
+ field public static final java.lang.String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE";
+ field public static final java.lang.String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE";
+ field public static final java.lang.String EXTRA_NANOAPP_ABORT_CODE = "android.hardware.location.extra.NANOAPP_ABORT_CODE";
+ field public static final java.lang.String EXTRA_NANOAPP_ID = "android.hardware.location.extra.NANOAPP_ID";
}
public static abstract deprecated class ContextHubManager.Callback {
@@ -5074,6 +5100,7 @@
ctor public NotificationAssistantService();
method public final void adjustNotification(android.service.notification.Adjustment);
method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+ method public void onActionClicked(java.lang.String, android.app.Notification.Action, int);
method public final android.os.IBinder onBind(android.content.Intent);
method public void onNotificationDirectReply(java.lang.String);
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
diff --git a/api/test-current.txt b/api/test-current.txt
index 738caec..c0f7ab6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -61,6 +61,7 @@
}
public class ActivityTaskManager {
+ method public void clearLaunchParamsForPackages(java.util.List<java.lang.String>);
method public java.lang.String listAllStacks();
method public void moveTaskToStack(int, int, boolean);
method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
@@ -81,6 +82,10 @@
field public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; // 0x0
}
+ public class AppDetailsActivity extends android.app.Activity {
+ ctor public AppDetailsActivity();
+ }
+
public class AppOpsManager {
method public java.util.List<android.app.AppOpsManager.HistoricalPackageOps> getAllHistoricPackagesOps(java.lang.String[], long, long);
method public android.app.AppOpsManager.HistoricalPackageOps getHistoricalPackagesOps(int, java.lang.String, java.lang.String[], long, long);
@@ -1155,6 +1160,7 @@
ctor public NotificationAssistantService();
method public final void adjustNotification(android.service.notification.Adjustment);
method public final void adjustNotifications(java.util.List<android.service.notification.Adjustment>);
+ method public void onActionClicked(java.lang.String, android.app.Notification.Action, int);
method public final android.os.IBinder onBind(android.content.Intent);
method public void onNotificationDirectReply(java.lang.String);
method public android.service.notification.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2fc7e03..c8405a2 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1338,8 +1338,9 @@
* Log bucketed battery charge cycles.
*
* Each bucket represents cycles of the battery past
- * a given charge point. For example, bucket 1 is the
- * lowest 1/8th of the battery, and bucket 8 is 100%.
+ * a given charge point. For example, if 10 cycle buckets are
+ * initialized, bucket 1 is the lowest 1/10th of the battery,
+ * and bucket 10 is 100%.
*
* Logged from:
* /sys/class/power_supply/bms/cycle_count, via Vendor.
@@ -1353,6 +1354,8 @@
optional int32 cycle_bucket_6 = 6;
optional int32 cycle_bucket_7 = 7;
optional int32 cycle_bucket_8 = 8;
+ optional int32 cycle_bucket_9 = 9;
+ optional int32 cycle_bucket_10 = 10;
}
/**
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index 3eb05a9..4e4b8f3 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -59,7 +59,7 @@
}
data->clear();
for (const StatsLogEventWrapper& it : returned_value) {
- data->push_back(make_shared<LogEvent>(it));
+ LogEvent::createLogEvents(it, *data);
}
VLOG("StatsCompanionServicePuller::pull succeeded for %d", mTagId);
return true;
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index e3f251a..f501574 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -32,9 +32,10 @@
sp<UidMap> StatsPuller::mUidMap = nullptr;
void StatsPuller::SetUidMap(const sp<UidMap>& uidMap) { mUidMap = uidMap; }
-// ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
StatsPuller::StatsPuller(const int tagId)
: mTagId(tagId) {
+ // Pullers can cause significant impact to system health and battery.
+ // So that we don't pull too frequently.
mCoolDownNs = StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.coolDownNs;
VLOG("Puller for tag %d created. Cooldown set to %lld", mTagId, (long long)mCoolDownNs);
}
@@ -64,8 +65,8 @@
data->setLogdWallClockTimestampNs(wallClockTimeNs);
}
if (ret && mCachedData.size() > 0) {
- mergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
- (*data) = mCachedData;
+ mapAndMergeIsolatedUidsToHostUid(mCachedData, mUidMap, mTagId);
+ (*data) = mCachedData;
}
StatsdStats::getInstance().notePullDelay(mTagId, getElapsedRealtimeNs() - elapsedTimeNs);
return ret;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 87a065b..f9b7982 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -54,52 +54,42 @@
// wifi_bytes_transfer
{android::util::WIFI_BYTES_TRANSFER,
{{2, 3, 4, 5},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER)}},
// wifi_bytes_transfer_by_fg_bg
{android::util::WIFI_BYTES_TRANSFER_BY_FG_BG,
{{3, 4, 5, 6},
- {2},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::WIFI_BYTES_TRANSFER_BY_FG_BG)}},
// mobile_bytes_transfer
{android::util::MOBILE_BYTES_TRANSFER,
{{2, 3, 4, 5},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER)}},
// mobile_bytes_transfer_by_fg_bg
{android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG,
{{3, 4, 5, 6},
- {2},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::MOBILE_BYTES_TRANSFER_BY_FG_BG)}},
// bluetooth_bytes_transfer
{android::util::BLUETOOTH_BYTES_TRANSFER,
{{2, 3},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::BLUETOOTH_BYTES_TRANSFER)}},
// kernel_wakelock
{android::util::KERNEL_WAKELOCK,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::KERNEL_WAKELOCK)}},
// subsystem_sleep_state
{android::util::SUBSYSTEM_SLEEP_STATE,
- {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+ {{}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
// on_device_power_measurement
- {android::util::ON_DEVICE_POWER_MEASUREMENT,
- {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
+ {android::util::ON_DEVICE_POWER_MEASUREMENT, {{}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
// cpu_time_per_freq
{android::util::CPU_TIME_PER_FREQ,
- {{3},
- {2},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
+ {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_TIME_PER_FREQ)}},
// cpu_time_per_uid
{android::util::CPU_TIME_PER_UID,
{{2, 3},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID)}},
// cpu_time_per_uid_freq
@@ -107,169 +97,140 @@
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
{android::util::CPU_TIME_PER_UID_FREQ,
{{4},
- {2, 3},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_UID_FREQ)}},
// cpu_active_time
// the throttling is 3sec, handled in
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
{android::util::CPU_ACTIVE_TIME,
- {{2},
- {},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
+ {{2}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_ACTIVE_TIME)}},
// cpu_cluster_time
// the throttling is 3sec, handled in
// frameworks/base/core/java/com/android/internal/os/KernelCpuProcReader
{android::util::CPU_CLUSTER_TIME,
- {{3},
- {2},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
+ {{3}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CPU_CLUSTER_TIME)}},
// wifi_activity_energy_info
{android::util::WIFI_ACTIVITY_INFO,
- {{},
- {},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::WIFI_ACTIVITY_INFO)}},
// modem_activity_info
{android::util::MODEM_ACTIVITY_INFO,
- {{},
- {},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::MODEM_ACTIVITY_INFO)}},
// bluetooth_activity_info
{android::util::BLUETOOTH_ACTIVITY_INFO,
{{},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::BLUETOOTH_ACTIVITY_INFO)}},
// system_elapsed_realtime
{android::util::SYSTEM_ELAPSED_REALTIME,
{{},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::SYSTEM_ELAPSED_REALTIME)}},
// system_uptime
{android::util::SYSTEM_UPTIME,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::SYSTEM_UPTIME)}},
// remaining_battery_capacity
{android::util::REMAINING_BATTERY_CAPACITY,
{{},
- {},
1 * NS_PER_SEC,
new ResourceHealthManagerPuller(android::util::REMAINING_BATTERY_CAPACITY)}},
// full_battery_capacity
{android::util::FULL_BATTERY_CAPACITY,
{{},
- {},
1 * NS_PER_SEC,
new ResourceHealthManagerPuller(android::util::FULL_BATTERY_CAPACITY)}},
// battery_voltage
{android::util::BATTERY_VOLTAGE,
- {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
- // battery_voltage
+ {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_VOLTAGE)}},
+ // battery_level
{android::util::BATTERY_LEVEL,
- {{}, {}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
+ {{}, 1 * NS_PER_SEC, new ResourceHealthManagerPuller(android::util::BATTERY_LEVEL)}},
// process_memory_state
{android::util::PROCESS_MEMORY_STATE,
{{4, 5, 6, 7, 8, 9},
- {2, 3, 10},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
// native_process_memory_state
{android::util::NATIVE_PROCESS_MEMORY_STATE,
{{3, 4, 5, 6},
- {2, 7},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}},
{android::util::PROCESS_MEMORY_HIGH_WATER_MARK,
{{3},
- {2},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
// temperature
- {android::util::TEMPERATURE, {{}, {}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}},
+ {android::util::TEMPERATURE, {{}, 1 * NS_PER_SEC, new ResourceThermalManagerPuller()}},
// binder_calls
{android::util::BINDER_CALLS,
{{4, 5, 6, 8, 12},
- {2, 3, 7, 9, 10, 11, 13},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::BINDER_CALLS)}},
// binder_calls_exceptions
{android::util::BINDER_CALLS_EXCEPTIONS,
{{},
- {},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
// looper_stats
{android::util::LOOPER_STATS,
{{5, 6, 7, 8, 9},
- {2, 3, 4, 10},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::LOOPER_STATS)}},
// Disk Stats
{android::util::DISK_STATS,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DISK_STATS)}},
// Directory usage
{android::util::DIRECTORY_USAGE,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::DIRECTORY_USAGE)}},
// Size of app's code, data, and cache
{android::util::APP_SIZE,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::APP_SIZE)}},
// Size of specific categories of files. Eg. Music.
{android::util::CATEGORY_SIZE,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}},
// Number of fingerprints registered to each user.
{android::util::NUM_FINGERPRINTS,
- {{},
- {},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}},
// ProcStats.
{android::util::PROC_STATS,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS)}},
// ProcStatsPkgProc.
{android::util::PROC_STATS_PKG_PROC,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::PROC_STATS_PKG_PROC)}},
// Disk I/O stats per uid.
{android::util::DISK_IO,
- {{2,3,4,5,6,7,8,9,10,11},
- {},
+ {{2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
3 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::DISK_IO)}},
// PowerProfile constants for power model calculations.
{android::util::POWER_PROFILE,
- {{}, {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
// Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
{android::util::PROCESS_CPU_TIME,
- {{} /* additive fields */, {} /* non additive fields */,
- 5 * NS_PER_SEC /* min cool-down in seconds*/,
- new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
+ {{} /* additive fields */,
+ 5 * NS_PER_SEC /* min cool-down in seconds*/,
+ new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
{android::util::CPU_TIME_PER_THREAD_FREQ,
{{7},
- {2, 3, 4, 5, 6},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
// DeviceCalculatedPowerUse.
{android::util::DEVICE_CALCULATED_POWER_USE,
- {{}, {}, 1 * NS_PER_SEC,
+ {{},
+ 1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
// DeviceCalculatedPowerBlameUid.
{android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
- {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
+ {{}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
// DeviceCalculatedPowerBlameOther.
{android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
- {{}, {},
+ {{},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
// BuildInformation.
{android::util::BUILD_INFORMATION,
- {{}, {},
- 1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
+ {{}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::BUILD_INFORMATION)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index bbf5d9d..3350736 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -36,9 +36,6 @@
// The field numbers of the fields that need to be summed when merging
// isolated uid with host uid.
std::vector<int> additiveFields;
- // The field numbers of the fields that can't be merged when merging
- // data belong to isolated uid and host uid.
- std::vector<int> nonAdditiveFields;
// How long should the puller wait before doing an actual pull again. Default
// 1 sec. Set this to 0 if this is handled elsewhere.
int64_t coolDownNs = 1 * NS_PER_SEC;
diff --git a/cmds/statsd/src/external/puller_util.cpp b/cmds/statsd/src/external/puller_util.cpp
index ea7fa97..0b9b6ab 100644
--- a/cmds/statsd/src/external/puller_util.cpp
+++ b/cmds/statsd/src/external/puller_util.cpp
@@ -25,67 +25,13 @@
namespace os {
namespace statsd {
+using std::list;
using std::map;
+using std::set;
using std::shared_ptr;
+using std::sort;
using std::vector;
-namespace {
-bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
- const vector<int>& nonAdditiveFields) {
- const auto& l_values = lhs->getValues();
- const auto& r_values = rhs->getValues();
-
- for (size_t i : nonAdditiveFields) {
- // We store everything starting from index 0, so we need to use i-1
- if (!(l_values.size() > i - 1 && r_values.size() > i - 1 &&
- l_values[i - 1].mValue == r_values[i - 1].mValue)) {
- return false;
- }
- }
- return true;
-}
-
-// merge rhs to lhs
-// when calling this function, all sanity check should be done already.
-// e.g., index boundary, nonAdditiveFields matching etc.
-bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
- const vector<int>& additiveFields) {
- vector<FieldValue>* host_values = lhs->getMutableValues();
- const auto& child_values = rhs->getValues();
- for (int i : additiveFields) {
- Value& host = (*host_values)[i - 1].mValue;
- const Value& child = (child_values[i - 1]).mValue;
- if (child.getType() != host.getType()) {
- return false;
- }
- switch (child.getType()) {
- case INT:
- host.setInt(host.int_value + child.int_value);
- break;
- case LONG:
- host.setLong(host.long_value + child.long_value);
- break;
- default:
- ALOGE("Tried to merge 2 fields with unsupported type");
- return false;
- }
- }
- return true;
-}
-
-bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos,
- const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) {
- for (const auto& pos : host_pos) {
- if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) &&
- mergeEvent(data[pos], data[child_pos], additiveFields)) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
/**
* Process all data and merge isolated with host if necessary.
* For example:
@@ -95,7 +41,7 @@
* int byte_send = 3;
* int byte_recv = 4;
* }
- * additive fields are {3, 4}, non-additive field is {2}
+ * additive fields are {3, 4}
* If we pulled the following events (uid1_child is an isolated uid which maps to uid1):
* [uid1, fg, 100, 200]
* [uid1_child, fg, 100, 200]
@@ -104,65 +50,119 @@
* We want to merge them and results should be:
* [uid1, fg, 200, 400]
* [uid1, bg, 100, 200]
+ *
+ * All atoms should be of the same tagId. All fields should be present.
*/
-void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
- int tagId) {
+void mapAndMergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
+ int tagId) {
if (StatsPullerManager::kAllPullAtomInfo.find(tagId) ==
StatsPullerManager::kAllPullAtomInfo.end()) {
VLOG("Unknown pull atom id %d", tagId);
return;
}
- int uidField;
- auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId);
- if (it == android::util::AtomsInfo::kAtomsWithUidField.end()) {
- VLOG("No uid to merge for atom %d", tagId);
+ if ((android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) ==
+ android::util::AtomsInfo::kAtomsWithAttributionChain.end()) &&
+ (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
+ android::util::AtomsInfo::kAtomsWithUidField.end())) {
+ VLOG("No uid or attribution chain to merge, atom %d", tagId);
return;
- } else {
- uidField = it->second; // uidField is the field number in proto,
}
- const vector<int>& additiveFields =
- StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields;
- const vector<int>& nonAdditiveFields =
- StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields;
- // map of host uid to their position in the original vector
- map<int, vector<int>> hostPosition;
- vector<bool> toRemove = vector<bool>(data.size(), false);
-
- for (size_t i = 0; i < data.size(); i++) {
- vector<FieldValue>* valueList = data[i]->getMutableValues();
-
- int uid;
- if (uidField > 0 && (int)data[i]->getValues().size() >= uidField &&
- (data[i]->getValues())[uidField - 1].mValue.getType() == INT) {
- uid = (*data[i]->getMutableValues())[uidField - 1].mValue.int_value;
- } else {
- ALOGE("Malformed log, uid not found. %s", data[i]->ToString().c_str());
- continue;
+ // 1. Map all isolated uid in-place to host uid
+ for (shared_ptr<LogEvent>& event : data) {
+ if (event->GetTagId() != tagId) {
+ ALOGE("Wrong atom. Expecting %d, got %d", tagId, event->GetTagId());
+ return;
}
-
- const int hostUid = uidMap->getHostUidOrSelf(uid);
-
- if (hostUid != uid) {
- (*valueList)[0].mValue.setInt(hostUid);
- }
- if (hostPosition.find(hostUid) == hostPosition.end()) {
- hostPosition[hostUid].push_back(i);
+ if (android::util::AtomsInfo::kAtomsWithAttributionChain.find(tagId) !=
+ android::util::AtomsInfo::kAtomsWithAttributionChain.end()) {
+ for (auto& value : *(event->getMutableValues())) {
+ if (value.mField.getPosAtDepth(0) > kAttributionField) {
+ break;
+ }
+ if (isAttributionUidField(value)) {
+ const int hostUid = uidMap->getHostUidOrSelf(value.mValue.int_value);
+ value.mValue.setInt(hostUid);
+ }
+ }
} else {
- if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) {
- toRemove[i] = true;
- } else {
- hostPosition[hostUid].push_back(i);
+ auto it = android::util::AtomsInfo::kAtomsWithUidField.find(tagId);
+ if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
+ int uidField = it->second; // uidField is the field number in proto,
+ // starting from 1
+ if (uidField > 0 && (int)event->getValues().size() >= uidField &&
+ (event->getValues())[uidField - 1].mValue.getType() == INT) {
+ Value& value = (*event->getMutableValues())[uidField - 1].mValue;
+ const int hostUid = uidMap->getHostUidOrSelf(value.int_value);
+ value.setInt(hostUid);
+ } else {
+ ALOGE("Malformed log, uid not found. %s", event->ToString().c_str());
+ return;
+ }
}
}
}
+ // 2. sort the data, bit-wise
+ sort(data.begin(), data.end(),
+ [](const shared_ptr<LogEvent>& lhs, const shared_ptr<LogEvent>& rhs) {
+ if (lhs->size() != rhs->size()) {
+ return lhs->size() < rhs->size();
+ }
+ const std::vector<FieldValue>& lhsValues = lhs->getValues();
+ const std::vector<FieldValue>& rhsValues = rhs->getValues();
+ for (int i = 0; i < (int)lhs->size(); i++) {
+ if (lhsValues[i] != rhsValues[i]) {
+ return lhsValues[i] < rhsValues[i];
+ }
+ }
+ return false;
+ });
+
vector<shared_ptr<LogEvent>> mergedData;
- for (size_t i = 0; i < toRemove.size(); i++) {
- if (!toRemove[i]) {
+ const vector<int>& additiveFieldsVec =
+ StatsPullerManager::kAllPullAtomInfo.find(tagId)->second.additiveFields;
+ const set<int> additiveFields(additiveFieldsVec.begin(), additiveFieldsVec.end());
+ bool needMerge = true;
+
+ // 3. do the merge.
+ // The loop invariant is this: for every event, check if it differs on
+ // non-additive fields, or have different attribution chain length.
+ // If so, no need to merge, add itself to the result.
+ // Otherwise, merge the value onto the one immediately next to it.
+ for (int i = 0; i < (int)data.size() - 1; i++) {
+ // Size different, must be different chains.
+ if (data[i]->size() != data[i + 1]->size()) {
mergedData.push_back(data[i]);
+ continue;
+ }
+ vector<FieldValue>* lhsValues = data[i]->getMutableValues();
+ vector<FieldValue>* rhsValues = data[i + 1]->getMutableValues();
+ needMerge = true;
+ for (int p = 0; p < (int)lhsValues->size(); p++) {
+ if ((*lhsValues)[p] != (*rhsValues)[p]) {
+ int pos = (*lhsValues)[p].mField.getPosAtDepth(0);
+ // Differ on non-additive field, abort.
+ if (additiveFields.find(pos) == additiveFields.end()) {
+ needMerge = false;
+ break;
+ }
+ }
+ }
+ if (!needMerge) {
+ mergedData.push_back(data[i]);
+ continue;
+ }
+ // This should be infrequent operation.
+ for (int p = 0; p < (int)lhsValues->size(); p++) {
+ int pos = (*lhsValues)[p].mField.getPosAtDepth(0);
+ if (additiveFields.find(pos) != additiveFields.end()) {
+ (*rhsValues)[p].mValue += (*lhsValues)[p].mValue;
+ }
}
}
+ mergedData.push_back(data.back());
+
data.clear();
data = mergedData;
}
diff --git a/cmds/statsd/src/external/puller_util.h b/cmds/statsd/src/external/puller_util.h
index fd4a4a2..f703e6c 100644
--- a/cmds/statsd/src/external/puller_util.h
+++ b/cmds/statsd/src/external/puller_util.h
@@ -25,8 +25,8 @@
namespace os {
namespace statsd {
-void mergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
- const sp<UidMap>& uidMap, int tagId);
+void mapAndMergeIsolatedUidsToHostUid(std::vector<std::shared_ptr<LogEvent>>& data,
+ const sp<UidMap>& uidMap, int tagId);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 625294c..b9732a5 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -41,13 +41,28 @@
}
}
-LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper) {
+LogEvent::LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex) {
mTagId = statsLogEventWrapper.getTagId();
mLogdTimestampNs = statsLogEventWrapper.getWallClockTimeNs();
mElapsedTimestampNs = statsLogEventWrapper.getElapsedRealTimeNs();
mLogUid = 0;
+ int workChainPosOffset = 0;
+ if (workChainIndex != -1) {
+ const WorkChain& wc = statsLogEventWrapper.getWorkChains()[workChainIndex];
+ // chains are at field 1, level 2
+ int depth = 2;
+ for (int i = 0; i < (int)wc.uids.size(); i++) {
+ int pos[] = {1, i + 1, 1};
+ mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.uids[i])));
+ pos[2]++;
+ mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(wc.tags[i])));
+ mValues.back().mField.decorateLastPos(2);
+ }
+ mValues.back().mField.decorateLastPos(1);
+ workChainPosOffset = 1;
+ }
for (int i = 0; i < (int)statsLogEventWrapper.getElements().size(); i++) {
- Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1));
+ Field field(statsLogEventWrapper.getTagId(), getSimpleField(i + 1 + workChainPosOffset));
switch (statsLogEventWrapper.getElements()[i].type) {
case android::os::StatsLogValue::STATS_LOG_VALUE_TYPE::INT:
mValues.push_back(
@@ -79,6 +94,17 @@
}
}
+void LogEvent::createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
+ std::vector<std::shared_ptr<LogEvent>>& logEvents) {
+ if (statsLogEventWrapper.getWorkChains().size() == 0) {
+ logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, -1));
+ } else {
+ for (size_t i = 0; i < statsLogEventWrapper.getWorkChains().size(); i++) {
+ logEvents.push_back(std::make_shared<LogEvent>(statsLogEventWrapper, i));
+ }
+ }
+}
+
LogEvent::LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs) {
mLogdTimestampNs = wallClockTimestampNs;
mTagId = tagId;
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 3d5b2ab..5408d17 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -65,7 +65,16 @@
*/
explicit LogEvent(log_msg& msg);
- explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper);
+ /**
+ * Creates LogEvent from StatsLogEventWrapper.
+ */
+ static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
+ std::vector<std::shared_ptr<LogEvent>>& logEvents);
+
+ /**
+ * Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
+ */
+ explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
/**
* Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index c3912ee..9fe84dc 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -165,7 +165,7 @@
const bool mSkipZeroDiffOutput;
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
+ FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 4ac55b5..b317361 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -454,6 +454,16 @@
ALOGW("cannot find \"what\" in ValueMetric \"%lld\"", (long long)metric.id());
return false;
}
+ if (!metric.has_value_field()) {
+ ALOGW("cannot find \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
+ return false;
+ }
+ std::vector<Matcher> fieldMatchers;
+ translateFieldMatcher(metric.value_field(), &fieldMatchers);
+ if (fieldMatchers.size() < 1) {
+ ALOGW("incorrect \"value_field\" in ValueMetric \"%lld\"", (long long)metric.id());
+ return false;
+ }
int metricIndex = allMetricProducers.size();
metricMap.insert({metric.id(), metricIndex});
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 6384757..90dfa87 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -394,6 +394,167 @@
EXPECT_EQ(1.1f, item16.mValue.float_value);
}
+TEST(LogEventTest, TestStatsLogEventWrapperNoChain) {
+ Parcel parcel;
+ // tag id
+ parcel.writeInt32(1);
+ // elapsed realtime
+ parcel.writeInt64(1111L);
+ // wallclock time
+ parcel.writeInt64(2222L);
+ // no chain
+ parcel.writeInt32(0);
+ // 2 data
+ parcel.writeInt32(2);
+ // int 6
+ parcel.writeInt32(1);
+ parcel.writeInt32(6);
+ // long 10
+ parcel.writeInt32(2);
+ parcel.writeInt64(10);
+ parcel.setDataPosition(0);
+
+ StatsLogEventWrapper statsLogEventWrapper;
+ EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
+ EXPECT_EQ(1, statsLogEventWrapper.getTagId());
+ EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
+ EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
+ EXPECT_EQ(0, statsLogEventWrapper.getWorkChains().size());
+ EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
+ EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
+ EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
+ LogEvent event(statsLogEventWrapper, -1);
+ EXPECT_EQ(1, event.GetTagId());
+ EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
+ EXPECT_EQ(2222L, event.GetLogdTimestampNs());
+ EXPECT_EQ(2, event.size());
+ EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
+ EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
+}
+
+TEST(LogEventTest, TestStatsLogEventWrapperWithChain) {
+ Parcel parcel;
+ // tag id
+ parcel.writeInt32(1);
+ // elapsed realtime
+ parcel.writeInt64(1111L);
+ // wallclock time
+ parcel.writeInt64(2222L);
+ // 3 chains
+ parcel.writeInt32(3);
+ // chain1, 2 nodes (1, "tag1") (2, "tag2")
+ parcel.writeInt32(2);
+ parcel.writeInt32(1);
+ parcel.writeString16(String16("tag1"));
+ parcel.writeInt32(2);
+ parcel.writeString16(String16("tag2"));
+ // chain2, 1 node (3, "tag3")
+ parcel.writeInt32(1);
+ parcel.writeInt32(3);
+ parcel.writeString16(String16("tag3"));
+ // chain3, 2 nodes (4, "") (5, "")
+ parcel.writeInt32(2);
+ parcel.writeInt32(4);
+ parcel.writeString16(String16(""));
+ parcel.writeInt32(5);
+ parcel.writeString16(String16(""));
+ // 2 data
+ parcel.writeInt32(2);
+ // int 6
+ parcel.writeInt32(1);
+ parcel.writeInt32(6);
+ // long 10
+ parcel.writeInt32(2);
+ parcel.writeInt64(10);
+ parcel.setDataPosition(0);
+
+ StatsLogEventWrapper statsLogEventWrapper;
+ EXPECT_EQ(NO_ERROR, statsLogEventWrapper.readFromParcel(&parcel));
+ EXPECT_EQ(1, statsLogEventWrapper.getTagId());
+ EXPECT_EQ(1111L, statsLogEventWrapper.getElapsedRealTimeNs());
+ EXPECT_EQ(2222L, statsLogEventWrapper.getWallClockTimeNs());
+ EXPECT_EQ(3, statsLogEventWrapper.getWorkChains().size());
+ EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids.size());
+ EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[0].uids[0]);
+ EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].uids[1]);
+ EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[0].tags.size());
+ EXPECT_EQ("tag1", statsLogEventWrapper.getWorkChains()[0].tags[0]);
+ EXPECT_EQ("tag2", statsLogEventWrapper.getWorkChains()[0].tags[1]);
+ EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].uids.size());
+ EXPECT_EQ(3, statsLogEventWrapper.getWorkChains()[1].uids[0]);
+ EXPECT_EQ(1, statsLogEventWrapper.getWorkChains()[1].tags.size());
+ EXPECT_EQ("tag3", statsLogEventWrapper.getWorkChains()[1].tags[0]);
+ EXPECT_EQ(2, statsLogEventWrapper.getElements().size());
+ EXPECT_EQ(6, statsLogEventWrapper.getElements()[0].int_value);
+ EXPECT_EQ(10L, statsLogEventWrapper.getElements()[1].long_value);
+ EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].uids.size());
+ EXPECT_EQ(4, statsLogEventWrapper.getWorkChains()[2].uids[0]);
+ EXPECT_EQ(5, statsLogEventWrapper.getWorkChains()[2].uids[1]);
+ EXPECT_EQ(2, statsLogEventWrapper.getWorkChains()[2].tags.size());
+ EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[0]);
+ EXPECT_EQ("", statsLogEventWrapper.getWorkChains()[2].tags[1]);
+
+ LogEvent event(statsLogEventWrapper, -1);
+ EXPECT_EQ(1, event.GetTagId());
+ EXPECT_EQ(1111L, event.GetElapsedTimestampNs());
+ EXPECT_EQ(2222L, event.GetLogdTimestampNs());
+ EXPECT_EQ(2, event.size());
+ EXPECT_EQ(6, event.getValues()[0].mValue.int_value);
+ EXPECT_EQ(10, event.getValues()[1].mValue.long_value);
+
+ LogEvent event1(statsLogEventWrapper, 0);
+
+ EXPECT_EQ(1, event1.GetTagId());
+ EXPECT_EQ(1111L, event1.GetElapsedTimestampNs());
+ EXPECT_EQ(2222L, event1.GetLogdTimestampNs());
+ EXPECT_EQ(6, event1.size());
+ EXPECT_EQ(1, event1.getValues()[0].mValue.int_value);
+ EXPECT_EQ(0x2010101, event1.getValues()[0].mField.getField());
+ EXPECT_EQ("tag1", event1.getValues()[1].mValue.str_value);
+ EXPECT_EQ(0x2010182, event1.getValues()[1].mField.getField());
+ EXPECT_EQ(2, event1.getValues()[2].mValue.int_value);
+ EXPECT_EQ(0x2010201, event1.getValues()[2].mField.getField());
+ EXPECT_EQ("tag2", event1.getValues()[3].mValue.str_value);
+ EXPECT_EQ(0x2018282, event1.getValues()[3].mField.getField());
+ EXPECT_EQ(6, event1.getValues()[4].mValue.int_value);
+ EXPECT_EQ(0x20000, event1.getValues()[4].mField.getField());
+ EXPECT_EQ(10, event1.getValues()[5].mValue.long_value);
+ EXPECT_EQ(0x30000, event1.getValues()[5].mField.getField());
+
+ LogEvent event2(statsLogEventWrapper, 1);
+
+ EXPECT_EQ(1, event2.GetTagId());
+ EXPECT_EQ(1111L, event2.GetElapsedTimestampNs());
+ EXPECT_EQ(2222L, event2.GetLogdTimestampNs());
+ EXPECT_EQ(4, event2.size());
+ EXPECT_EQ(3, event2.getValues()[0].mValue.int_value);
+ EXPECT_EQ(0x2010101, event2.getValues()[0].mField.getField());
+ EXPECT_EQ("tag3", event2.getValues()[1].mValue.str_value);
+ EXPECT_EQ(0x2018182, event2.getValues()[1].mField.getField());
+ EXPECT_EQ(6, event2.getValues()[2].mValue.int_value);
+ EXPECT_EQ(0x20000, event2.getValues()[2].mField.getField());
+ EXPECT_EQ(10, event2.getValues()[3].mValue.long_value);
+ EXPECT_EQ(0x30000, event2.getValues()[3].mField.getField());
+
+ LogEvent event3(statsLogEventWrapper, 2);
+
+ EXPECT_EQ(1, event3.GetTagId());
+ EXPECT_EQ(1111L, event3.GetElapsedTimestampNs());
+ EXPECT_EQ(2222L, event3.GetLogdTimestampNs());
+ EXPECT_EQ(6, event3.size());
+ EXPECT_EQ(4, event3.getValues()[0].mValue.int_value);
+ EXPECT_EQ(0x2010101, event3.getValues()[0].mField.getField());
+ EXPECT_EQ("", event3.getValues()[1].mValue.str_value);
+ EXPECT_EQ(0x2010182, event3.getValues()[1].mField.getField());
+ EXPECT_EQ(5, event3.getValues()[2].mValue.int_value);
+ EXPECT_EQ(0x2010201, event3.getValues()[2].mField.getField());
+ EXPECT_EQ("", event3.getValues()[3].mValue.str_value);
+ EXPECT_EQ(0x2018282, event3.getValues()[3].mField.getField());
+ EXPECT_EQ(6, event3.getValues()[4].mValue.int_value);
+ EXPECT_EQ(0x20000, event3.getValues()[4].mField.getField());
+ EXPECT_EQ(10, event3.getValues()[5].mValue.long_value);
+ EXPECT_EQ(0x30000, event3.getValues()[5].mField.getField());
+}
TEST(LogEventTest, TestBinaryFieldAtom) {
Atom launcherAtom;
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index fc6e420..266ea35 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -80,7 +80,7 @@
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
- mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
@@ -120,7 +120,7 @@
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
- mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
@@ -154,7 +154,7 @@
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
- mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
// 20->32->31
// 20->22->21
@@ -190,7 +190,7 @@
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
- mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
// 20->32->31
// 20->22->21
@@ -231,7 +231,7 @@
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
- mergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
@@ -256,7 +256,7 @@
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
- mergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
+ mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId);
EXPECT_EQ(2, (int)inputData.size());
}
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 3374226..c2e441b 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -24296,7 +24296,8 @@
HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$RangeOption;ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
HSPLandroid/icu/util/CodePointMap;->iterator()Ljava/util/Iterator;
-HSPLandroid/icu/util/CodePointMap;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;HSPLandroid/icu/util/Currency$1;-><init>()V
+HSPLandroid/icu/util/CodePointMap;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;
+HSPLandroid/icu/util/Currency$1;-><init>()V
HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/String;Ljava/lang/Void;)Landroid/icu/util/Currency;
HSPLandroid/icu/util/Currency$CurrencyUsage;-><init>(Ljava/lang/String;I)V
@@ -51954,6 +51955,22 @@
HSPLlibcore/timezone/TimeZoneFinder;->parseTimeZoneMappings(Lorg/xmlpull/v1/XmlPullParser;)Ljava/util/List;
HSPLlibcore/timezone/TimeZoneFinder;->processCountryZones(Lorg/xmlpull/v1/XmlPullParser;Llibcore/timezone/TimeZoneFinder$TimeZonesProcessor;)Z
HSPLlibcore/timezone/TimeZoneFinder;->processXml(Llibcore/timezone/TimeZoneFinder$TimeZonesProcessor;)V
+HSPLlibcore/timezone/ZoneInfoDB$TzData$1;->create(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLlibcore/timezone/ZoneInfoDB$TzData$1;->create(Ljava/lang/String;)Llibcore/util/ZoneInfo;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->close()V
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->finalize()V
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->getAvailableIDs()[Ljava/lang/String;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->getBufferIterator(Ljava/lang/String;)Llibcore/io/BufferIterator;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->hasTimeZone(Ljava/lang/String;)Z
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->loadData(Ljava/lang/String;)Z
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->loadTzDataWithFallback([Ljava/lang/String;)Llibcore/timezone/ZoneInfoDB$TzData;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->makeTimeZone(Ljava/lang/String;)Llibcore/util/ZoneInfo;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->makeTimeZoneUncached(Ljava/lang/String;)Llibcore/util/ZoneInfo;
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->readHeader()V
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->readIndex(Llibcore/io/BufferIterator;II)V
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->readZoneTab(Llibcore/io/BufferIterator;II)V
+HSPLlibcore/timezone/ZoneInfoDB$TzData;->validateOffset(II)V
+HSPLlibcore/timezone/ZoneInfoDB;->getInstance()Llibcore/timezone/ZoneInfoDB$TzData;
HSPLlibcore/util/BasicLruCache;-><init>(I)V
HSPLlibcore/util/BasicLruCache;->create(Ljava/lang/Object;)Ljava/lang/Object;
HSPLlibcore/util/BasicLruCache;->entryEvicted(Ljava/lang/Object;Ljava/lang/Object;)V
@@ -52007,22 +52024,6 @@
HSPLlibcore/util/ZoneInfo;->hashCode()I
HSPLlibcore/util/ZoneInfo;->inDaylightTime(Ljava/util/Date;)Z
HSPLlibcore/util/ZoneInfo;->readTimeZone(Ljava/lang/String;Llibcore/io/BufferIterator;J)Llibcore/util/ZoneInfo;
-HSPLlibcore/util/ZoneInfoDB$TzData$1;->create(Ljava/lang/Object;)Ljava/lang/Object;
-HSPLlibcore/util/ZoneInfoDB$TzData$1;->create(Ljava/lang/String;)Llibcore/util/ZoneInfo;
-HSPLlibcore/util/ZoneInfoDB$TzData;->close()V
-HSPLlibcore/util/ZoneInfoDB$TzData;->finalize()V
-HSPLlibcore/util/ZoneInfoDB$TzData;->getAvailableIDs()[Ljava/lang/String;
-HSPLlibcore/util/ZoneInfoDB$TzData;->getBufferIterator(Ljava/lang/String;)Llibcore/io/BufferIterator;
-HSPLlibcore/util/ZoneInfoDB$TzData;->hasTimeZone(Ljava/lang/String;)Z
-HSPLlibcore/util/ZoneInfoDB$TzData;->loadData(Ljava/lang/String;)Z
-HSPLlibcore/util/ZoneInfoDB$TzData;->loadTzDataWithFallback([Ljava/lang/String;)Llibcore/util/ZoneInfoDB$TzData;
-HSPLlibcore/util/ZoneInfoDB$TzData;->makeTimeZone(Ljava/lang/String;)Llibcore/util/ZoneInfo;
-HSPLlibcore/util/ZoneInfoDB$TzData;->makeTimeZoneUncached(Ljava/lang/String;)Llibcore/util/ZoneInfo;
-HSPLlibcore/util/ZoneInfoDB$TzData;->readHeader()V
-HSPLlibcore/util/ZoneInfoDB$TzData;->readIndex(Llibcore/io/BufferIterator;II)V
-HSPLlibcore/util/ZoneInfoDB$TzData;->readZoneTab(Llibcore/io/BufferIterator;II)V
-HSPLlibcore/util/ZoneInfoDB$TzData;->validateOffset(II)V
-HSPLlibcore/util/ZoneInfoDB;->getInstance()Llibcore/util/ZoneInfoDB$TzData;
HSPLorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(ILjava/nio/ByteBuffer;)V
HSPLorg/apache/harmony/dalvik/ddmc/ChunkHandler;->putString(Ljava/nio/ByteBuffer;Ljava/lang/String;)V
HSPLorg/apache/harmony/dalvik/ddmc/ChunkHandler;->type(Ljava/lang/String;)I
@@ -63464,6 +63465,9 @@
Llibcore/timezone/TimeZoneFinder$SelectiveCountryTimeZonesExtractor;
Llibcore/timezone/TimeZoneFinder$TimeZonesProcessor;
Llibcore/timezone/TimeZoneFinder;
+Llibcore/timezone/ZoneInfoDB$TzData$1;
+Llibcore/timezone/ZoneInfoDB$TzData;
+Llibcore/timezone/ZoneInfoDB;
Llibcore/util/BasicLruCache;
Llibcore/util/CharsetUtils;
Llibcore/util/CollectionUtils;
@@ -63478,9 +63482,6 @@
Llibcore/util/ZoneInfo$OffsetInterval;
Llibcore/util/ZoneInfo$WallTime;
Llibcore/util/ZoneInfo;
-Llibcore/util/ZoneInfoDB$TzData$1;
-Llibcore/util/ZoneInfoDB$TzData;
-Llibcore/util/ZoneInfoDB;
Lorg/apache/harmony/dalvik/NativeTestTarget;
Lorg/apache/harmony/dalvik/ddmc/Chunk;
Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 69d3cff..25bd033 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1461,7 +1461,6 @@
Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
Landroid/view/IWindowManager;->showStrictModeViolation(Z)V
Landroid/view/IWindowManager;->thawRotation()V
-Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/view/IWindowSession;
Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V
Landroid/view/IWindowSession;->getInTouchMode()Z
@@ -2615,7 +2614,6 @@
Lcom/android/internal/telephony/dataconnection/DataConnection;->log(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->mActivatingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActivatingState;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mActiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActiveState;
-Lcom/android/internal/telephony/dataconnection/DataConnection;->mApnContexts:Ljava/util/HashMap;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mConnectionParams:Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDataRegState:I
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDcFailCause:Lcom/android/internal/telephony/dataconnection/DcFailCause;
@@ -4368,7 +4366,6 @@
Lcom/google/android/util/AbstractMessageParser$Token$Type;->SMILEY:Lcom/google/android/util/AbstractMessageParser$Token$Type;
Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
Lcom/google/android/util/AbstractMessageParser$Token$Type;->YOUTUBE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
-Lcom/sun/nio/file/ExtendedWatchEventModifier;->FILE_TREE:Lcom/sun/nio/file/ExtendedWatchEventModifier;
Lgov/nist/core/Debug;->printStackTrace(Ljava/lang/Exception;)V
Lgov/nist/core/GenericObject;-><init>()V
Lgov/nist/core/GenericObject;->dbgPrint()V
@@ -4508,178 +4505,9 @@
Lgov/nist/javax/sip/address/SipUri;->setUserParam(Ljava/lang/String;)V
Lgov/nist/javax/sip/parser/URLParser;-><init>(Ljava/lang/String;)V
Lgov/nist/javax/sip/parser/URLParser;->sipURL(Z)Lgov/nist/javax/sip/address/SipUri;
-Ljava/lang/DexCache;->dexFile:J
-Ljava/lang/invoke/SerializedLambda;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
-Ljava/lang/invoke/SerializedLambda;->getCapturedArg(I)Ljava/lang/Object;
-Ljava/lang/invoke/SerializedLambda;->getCapturedArgCount()I
-Ljava/lang/invoke/SerializedLambda;->getCapturingClass()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceClass()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodName()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodSignature()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getImplClass()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getImplMethodKind()I
-Ljava/lang/invoke/SerializedLambda;->getImplMethodName()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getImplMethodSignature()Ljava/lang/String;
-Ljava/lang/invoke/SerializedLambda;->getInstantiatedMethodType()Ljava/lang/String;
-Ljava/lang/UNIXProcess;->pid:I
-Ljava/net/AddressCache$AddressCacheEntry;-><init>(Ljava/lang/Object;)V
-Ljava/net/AddressCache$AddressCacheEntry;->expiryNanos:J
-Ljava/net/AddressCache$AddressCacheEntry;->value:Ljava/lang/Object;
-Ljava/net/AddressCache$AddressCacheKey;->mHostname:Ljava/lang/String;
-Ljava/net/AddressCache;->cache:Llibcore/util/BasicLruCache;
-Ljava/net/Inet6AddressImpl;->addressCache:Ljava/net/AddressCache;
-Ljava/net/PlainSocketImpl;-><init>()V
-Ljava/nio/DirectByteBuffer;->cleaner()Lsun/misc/Cleaner;
-Ljava/nio/file/FileTreeWalker;->followLinks:Z
-Ljava/nio/file/FileTreeWalker;->linkOptions:[Ljava/nio/file/LinkOption;
-Ljava/nio/file/FileTreeWalker;->maxDepth:I
-Ljava/util/zip/ZipFile$ZipEntryIterator;->nextElement()Ljava/util/zip/ZipEntry;
Ljunit/framework/TestCase;->fName:Ljava/lang/String;
Ljunit/framework/TestSuite;->isPublicTestMethod(Ljava/lang/reflect/Method;)Z
Ljunit/framework/TestSuite;->isTestMethod(Ljava/lang/reflect/Method;)Z
-Llibcore/icu/DateIntervalFormat;->formatDateRange(JJILjava/lang/String;)Ljava/lang/String;
-Llibcore/icu/ICU;->CACHED_PATTERNS:Llibcore/util/BasicLruCache;
-Llibcore/icu/ICU;->getBestDateTimePattern(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
-Llibcore/icu/ICU;->getBestDateTimePatternNative(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Llibcore/icu/ICU;->getDateFormatOrder(Ljava/lang/String;)[C
-Llibcore/icu/LocaleData;->firstDayOfWeek:Ljava/lang/Integer;
-Llibcore/icu/LocaleData;->get(Ljava/util/Locale;)Llibcore/icu/LocaleData;
-Llibcore/icu/LocaleData;->longStandAloneWeekdayNames:[Ljava/lang/String;
-Llibcore/icu/LocaleData;->mapInvalidAndNullLocales(Ljava/util/Locale;)Ljava/util/Locale;
-Llibcore/icu/LocaleData;->minimalDaysInFirstWeek:Ljava/lang/Integer;
-Llibcore/icu/LocaleData;->shortMonthNames:[Ljava/lang/String;
-Llibcore/icu/LocaleData;->shortStandAloneMonthNames:[Ljava/lang/String;
-Llibcore/icu/LocaleData;->shortStandAloneWeekdayNames:[Ljava/lang/String;
-Llibcore/icu/LocaleData;->timeFormat_Hm:Ljava/lang/String;
-Llibcore/icu/LocaleData;->timeFormat_hm:Ljava/lang/String;
-Llibcore/icu/LocaleData;->today:Ljava/lang/String;
-Llibcore/icu/LocaleData;->tomorrow:Ljava/lang/String;
-Llibcore/icu/LocaleData;->zeroDigit:C
-Llibcore/icu/TimeZoneNames;->forLocale(Ljava/util/Locale;)[Ljava/lang/String;
-Llibcore/io/AsynchronousCloseMonitor;->signalBlockedThreads(Ljava/io/FileDescriptor;)V
-Llibcore/io/BlockGuardOs;-><init>(Llibcore/io/Os;)V
-Llibcore/io/BlockGuardOs;->chmod(Ljava/lang/String;I)V
-Llibcore/io/BlockGuardOs;->chown(Ljava/lang/String;II)V
-Llibcore/io/BlockGuardOs;->close(Ljava/io/FileDescriptor;)V
-Llibcore/io/BlockGuardOs;->fchmod(Ljava/io/FileDescriptor;I)V
-Llibcore/io/BlockGuardOs;->fchown(Ljava/io/FileDescriptor;II)V
-Llibcore/io/BlockGuardOs;->fdatasync(Ljava/io/FileDescriptor;)V
-Llibcore/io/BlockGuardOs;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;
-Llibcore/io/BlockGuardOs;->fstatvfs(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;
-Llibcore/io/BlockGuardOs;->lchown(Ljava/lang/String;II)V
-Llibcore/io/BlockGuardOs;->link(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/BlockGuardOs;->lseek(Ljava/io/FileDescriptor;JI)J
-Llibcore/io/BlockGuardOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
-Llibcore/io/BlockGuardOs;->mkdir(Ljava/lang/String;I)V
-Llibcore/io/BlockGuardOs;->mkfifo(Ljava/lang/String;I)V
-Llibcore/io/BlockGuardOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
-Llibcore/io/BlockGuardOs;->posix_fallocate(Ljava/io/FileDescriptor;JJ)V
-Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
-Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;[BIIJ)I
-Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
-Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;[BIIJ)I
-Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
-Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;[BII)I
-Llibcore/io/BlockGuardOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/io/BlockGuardOs;->readv(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
-Llibcore/io/BlockGuardOs;->realpath(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/io/BlockGuardOs;->remove(Ljava/lang/String;)V
-Llibcore/io/BlockGuardOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/BlockGuardOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
-Llibcore/io/BlockGuardOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
-Llibcore/io/BlockGuardOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
-Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;[BII)I
-Llibcore/io/BlockGuardOs;->writev(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
-Llibcore/io/BufferIterator;->readByte()B
-Llibcore/io/BufferIterator;->readByteArray([BII)V
-Llibcore/io/BufferIterator;->readInt()I
-Llibcore/io/BufferIterator;->readIntArray([III)V
-Llibcore/io/BufferIterator;->seek(I)V
-Llibcore/io/BufferIterator;->skip(I)V
-Llibcore/io/DropBox;->addText(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;-><init>(Llibcore/io/Os;)V
-Llibcore/io/ForwardingOs;->access(Ljava/lang/String;I)Z
-Llibcore/io/ForwardingOs;->chmod(Ljava/lang/String;I)V
-Llibcore/io/ForwardingOs;->chown(Ljava/lang/String;II)V
-Llibcore/io/ForwardingOs;->getenv(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/io/ForwardingOs;->lchown(Ljava/lang/String;II)V
-Llibcore/io/ForwardingOs;->link(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
-Llibcore/io/ForwardingOs;->mkdir(Ljava/lang/String;I)V
-Llibcore/io/ForwardingOs;->mkfifo(Ljava/lang/String;I)V
-Llibcore/io/ForwardingOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
-Llibcore/io/ForwardingOs;->os:Llibcore/io/Os;
-Llibcore/io/ForwardingOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/io/ForwardingOs;->remove(Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;->removexattr(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
-Llibcore/io/ForwardingOs;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
-Llibcore/io/ForwardingOs;->setxattr(Ljava/lang/String;Ljava/lang/String;[BI)V
-Llibcore/io/ForwardingOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
-Llibcore/io/ForwardingOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
-Llibcore/io/ForwardingOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
-Llibcore/io/ForwardingOs;->sysconf(I)J
-Llibcore/io/ForwardingOs;->unlink(Ljava/lang/String;)V
-Llibcore/io/IoBridge;->isConnected(Ljava/io/FileDescriptor;Ljava/net/InetAddress;III)Z
-Llibcore/io/IoUtils;->closeQuietly(Ljava/io/FileDescriptor;)V
-Llibcore/io/IoUtils;->closeQuietly(Ljava/lang/AutoCloseable;)V
-Llibcore/io/IoUtils;->closeQuietly(Ljava/net/Socket;)V
-Llibcore/io/IoUtils;->readFileAsByteArray(Ljava/lang/String;)[B
-Llibcore/io/IoUtils;->readFileAsString(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V
-Llibcore/io/MemoryMappedFile;->bigEndianIterator()Llibcore/io/BufferIterator;
-Llibcore/io/MemoryMappedFile;->mmapRO(Ljava/lang/String;)Llibcore/io/MemoryMappedFile;
-Llibcore/io/Os;->chmod(Ljava/lang/String;I)V
-Llibcore/io/Os;->close(Ljava/io/FileDescriptor;)V
-Llibcore/io/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V
-Llibcore/io/Os;->gai_strerror(I)Ljava/lang/String;
-Llibcore/io/Os;->remove(Ljava/lang/String;)V
-Llibcore/io/Os;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
-Llibcore/io/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
-Llibcore/io/Os;->stat(Ljava/lang/String;)Landroid/system/StructStat;
-Llibcore/io/Os;->strerror(I)Ljava/lang/String;
-Llibcore/io/Os;->sysconf(I)J
-Llibcore/io/Streams;->readAsciiLine(Ljava/io/InputStream;)Ljava/lang/String;
-Llibcore/io/Streams;->readFully(Ljava/io/InputStream;)[B
-Llibcore/io/Streams;->readFully(Ljava/io/InputStream;[B)V
-Llibcore/io/Streams;->readSingleByte(Ljava/io/InputStream;)I
-Llibcore/io/Streams;->skipAll(Ljava/io/InputStream;)V
-Llibcore/io/Streams;->writeSingleByte(Ljava/io/OutputStream;I)V
-Llibcore/net/event/NetworkEventDispatcher;->addListener(Llibcore/net/event/NetworkEventListener;)V
-Llibcore/net/event/NetworkEventDispatcher;->getInstance()Llibcore/net/event/NetworkEventDispatcher;
-Llibcore/net/event/NetworkEventListener;-><init>()V
-Llibcore/net/http/HttpDate;->format(Ljava/util/Date;)Ljava/lang/String;
-Llibcore/net/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;
-Llibcore/net/MimeUtils;->guessExtensionFromMimeType(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/net/MimeUtils;->guessMimeTypeFromExtension(Ljava/lang/String;)Ljava/lang/String;
-Llibcore/net/NetworkSecurityPolicy;->isCleartextTrafficPermitted()Z
-Llibcore/util/BasicLruCache;-><init>(I)V
-Llibcore/util/BasicLruCache;->evictAll()V
-Llibcore/util/BasicLruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
-Llibcore/util/BasicLruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-Llibcore/util/EmptyArray;->BYTE:[B
-Llibcore/util/EmptyArray;->INT:[I
-Llibcore/util/EmptyArray;->OBJECT:[Ljava/lang/Object;
-Llibcore/util/ZoneInfoDB$TzData;-><init>()V
-Lorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(ILjava/nio/ByteBuffer;)V
-Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;->CHUNK_ORDER:Ljava/nio/ByteOrder;
-Lorg/apache/harmony/dalvik/ddmc/DdmServer;->broadcast(I)V
-Lorg/apache/harmony/dalvik/ddmc/DdmServer;->sendChunk(Lorg/apache/harmony/dalvik/ddmc/Chunk;)V
-Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;->getThreadStats()[B
-Lorg/apache/harmony/xml/dom/ElementImpl;->localName:Ljava/lang/String;
-Lorg/apache/harmony/xml/ExpatAttributes;-><init>()V
-Lorg/apache/harmony/xml/ExpatParser$EntityParser;->depth:I
-Lorg/apache/harmony/xml/ExpatParser;-><init>(Ljava/lang/String;Lorg/apache/harmony/xml/ExpatReader;ZLjava/lang/String;Ljava/lang/String;)V
-Lorg/apache/harmony/xml/ExpatParser;->append([BII)V
-Lorg/apache/harmony/xml/ExpatParser;->append([CII)V
-Lorg/apache/harmony/xml/ExpatParser;->attributes:Lorg/apache/harmony/xml/ExpatAttributes;
-Lorg/apache/harmony/xml/ExpatParser;->cloneAttributes()Lorg/xml/sax/Attributes;
-Lorg/apache/harmony/xml/ExpatParser;->finish()V
-Lorg/apache/harmony/xml/ExpatParser;->xmlReader:Lorg/apache/harmony/xml/ExpatReader;
-Lorg/apache/harmony/xml/ExpatReader;-><init>()V
-Lorg/apache/harmony/xml/ExpatReader;->contentHandler:Lorg/xml/sax/ContentHandler;
Lorg/apache/xalan/extensions/ExpressionContext;->getContextNode()Lorg/w3c/dom/Node;
Lorg/apache/xalan/extensions/ExpressionContext;->getErrorListener()Ljavax/xml/transform/ErrorListener;
Lorg/apache/xalan/extensions/ExpressionContext;->getVariableOrParam(Lorg/apache/xml/utils/QName;)Lorg/apache/xpath/objects/XObject;
@@ -5358,431 +5186,3 @@
Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutput(Ljava/io/Writer;)V
Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutputProperty(Ljava/lang/String;Ljava/lang/String;)V
Lorg/ccil/cowan/tagsoup/XMLWriter;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
-Lorg/xml/sax/helpers/NamespaceSupport$Context;-><init>(Lorg/xml/sax/helpers/NamespaceSupport;)V
-Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;-><init>(Lorg/xml/sax/helpers/ParserAdapter;)V
-Lsun/misc/ASCIICaseInsensitiveComparator;->CASE_INSENSITIVE_ORDER:Ljava/util/Comparator;
-Lsun/misc/ASCIICaseInsensitiveComparator;->lowerCaseHashCode(Ljava/lang/String;)I
-Lsun/misc/BASE64Decoder;-><init>()V
-Lsun/misc/BASE64Decoder;->pem_convert_array:[B
-Lsun/misc/BASE64Encoder;-><init>()V
-Lsun/misc/BASE64Encoder;->pem_array:[C
-Lsun/misc/CEFormatException;-><init>(Ljava/lang/String;)V
-Lsun/misc/CEStreamExhausted;-><init>()V
-Lsun/misc/CharacterDecoder;-><init>()V
-Lsun/misc/CharacterEncoder;-><init>()V
-Lsun/misc/CharacterEncoder;->encodeBuffer([B)Ljava/lang/String;
-Lsun/misc/CharacterEncoder;->encodeBufferPrefix(Ljava/io/OutputStream;)V
-Lsun/misc/CharacterEncoder;->pStream:Ljava/io/PrintStream;
-Lsun/misc/Cleaner;->create(Ljava/lang/Object;Ljava/lang/Runnable;)Lsun/misc/Cleaner;
-Lsun/misc/FloatingDecimal;->$assertionsDisabled:Z
-Lsun/misc/FloatingDecimal;->getHexDigit(Ljava/lang/String;I)I
-Lsun/misc/FloatingDecimal;->stripLeadingZeros(Ljava/lang/String;)Ljava/lang/String;
-Lsun/misc/FormattedFloatingDecimal$Form;->COMPATIBLE:Lsun/misc/FormattedFloatingDecimal$Form;
-Lsun/misc/FormattedFloatingDecimal$Form;->DECIMAL_FLOAT:Lsun/misc/FormattedFloatingDecimal$Form;
-Lsun/misc/FormattedFloatingDecimal$Form;->SCIENTIFIC:Lsun/misc/FormattedFloatingDecimal$Form;
-Lsun/misc/FormattedFloatingDecimal;->$assertionsDisabled:Z
-Lsun/misc/FpUtils;->$assertionsDisabled:Z
-Lsun/misc/FpUtils;->rawCopySign(DD)D
-Lsun/misc/HexDumpEncoder;-><init>()V
-Lsun/misc/HexDumpEncoder;->currentByte:I
-Lsun/misc/HexDumpEncoder;->offset:I
-Lsun/misc/HexDumpEncoder;->thisLine:[B
-Lsun/misc/HexDumpEncoder;->thisLineLength:I
-Lsun/misc/IOUtils;->readFully(Ljava/io/InputStream;IZ)[B
-Lsun/misc/JarIndex;-><init>([Ljava/lang/String;)V
-Lsun/misc/JarIndex;->write(Ljava/io/OutputStream;)V
-Lsun/misc/MessageUtils;-><init>()V
-Lsun/misc/MetaIndex;->forJar(Ljava/io/File;)Lsun/misc/MetaIndex;
-Lsun/misc/MetaIndex;->registerDirectory(Ljava/io/File;)V
-Lsun/misc/VM;->maxDirectMemory()J
-Lsun/net/ftp/FtpClient;-><init>()V
-Lsun/net/util/IPAddressUtil;->isIPv4LiteralAddress(Ljava/lang/String;)Z
-Lsun/net/util/IPAddressUtil;->isIPv6LiteralAddress(Ljava/lang/String;)Z
-Lsun/net/www/MessageHeader;-><init>()V
-Lsun/net/www/MessageHeader;-><init>(Ljava/io/InputStream;)V
-Lsun/net/www/MessageHeader;->add(Ljava/lang/String;Ljava/lang/String;)V
-Lsun/net/www/MessageHeader;->findValue(Ljava/lang/String;)Ljava/lang/String;
-Lsun/net/www/MessageHeader;->prepend(Ljava/lang/String;Ljava/lang/String;)V
-Lsun/net/www/MessageHeader;->print(Ljava/io/PrintStream;)V
-Lsun/net/www/MessageHeader;->set(Ljava/lang/String;Ljava/lang/String;)V
-Lsun/net/www/ParseUtil;->decode(Ljava/lang/String;)Ljava/lang/String;
-Lsun/net/www/ParseUtil;->encodePath(Ljava/lang/String;Z)Ljava/lang/String;
-Lsun/net/www/ParseUtil;->fileToEncodedURL(Ljava/io/File;)Ljava/net/URL;
-Lsun/net/www/URLConnection;-><init>(Ljava/net/URL;)V
-Lsun/net/www/URLConnection;->setProperties(Lsun/net/www/MessageHeader;)V
-Lsun/nio/ch/DirectBuffer;->address()J
-Lsun/nio/ch/FileChannelImpl;->unmap0(JJ)I
-Lsun/nio/ch/SelectorImpl;->publicSelectedKeys:Ljava/util/Set;
-Lsun/nio/ch/SelectorImpl;->selectedKeys:Ljava/util/Set;
-Lsun/nio/cs/HistoricallyNamedCharset;->historicalName()Ljava/lang/String;
-Lsun/nio/cs/ThreadLocalCoders;->decoderFor(Ljava/lang/Object;)Ljava/nio/charset/CharsetDecoder;
-Lsun/nio/fs/BasicFileAttributesHolder;->get()Ljava/nio/file/attribute/BasicFileAttributes;
-Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/Class;)V
-Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/String;)V
-Lsun/reflect/misc/ReflectUtil;->isPackageAccessible(Ljava/lang/Class;)Z
-Lsun/reflect/misc/ReflectUtil;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
-Lsun/reflect/Reflection;->ensureMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V
-Lsun/reflect/Reflection;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
-Lsun/security/action/GetBooleanAction;-><init>(Ljava/lang/String;)V
-Lsun/security/action/GetIntegerAction;-><init>(Ljava/lang/String;I)V
-Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;)V
-Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lsun/security/jca/GetInstance$Instance;->impl:Ljava/lang/Object;
-Lsun/security/jca/GetInstance$Instance;->provider:Ljava/security/Provider;
-Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Lsun/security/jca/GetInstance$Instance;
-Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;)Lsun/security/jca/GetInstance$Instance;
-Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/security/Provider;)Lsun/security/jca/GetInstance$Instance;
-Lsun/security/jca/JCAUtil;->getSecureRandom()Ljava/security/SecureRandom;
-Lsun/security/jca/ProviderConfig;->argument:Ljava/lang/String;
-Lsun/security/jca/ProviderConfig;->CL_STRING:[Ljava/lang/Class;
-Lsun/security/jca/ProviderConfig;->disableLoad()V
-Lsun/security/jca/ProviderConfig;->hasArgument()Z
-Lsun/security/jca/ProviderList;->getService(Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;
-Lsun/security/jca/Providers;->getProviderList()Lsun/security/jca/ProviderList;
-Lsun/security/jca/Providers;->startJarVerification()Ljava/lang/Object;
-Lsun/security/jca/Providers;->stopJarVerification(Ljava/lang/Object;)V
-Lsun/security/pkcs/ContentInfo;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
-Lsun/security/pkcs/ContentInfo;-><init>([B)V
-Lsun/security/pkcs/ContentInfo;->DATA_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/ContentInfo;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/pkcs/ContentInfo;->getData()[B
-Lsun/security/pkcs/ParsingException;-><init>(Ljava/lang/String;)V
-Lsun/security/pkcs/PKCS7;-><init>([B)V
-Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Ljava/security/cert/X509CRL;[Lsun/security/pkcs/SignerInfo;)V
-Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Lsun/security/pkcs/SignerInfo;)V
-Lsun/security/pkcs/PKCS7;->encodeSignedData(Ljava/io/OutputStream;)V
-Lsun/security/pkcs/PKCS7;->getCertificates()[Ljava/security/cert/X509Certificate;
-Lsun/security/pkcs/PKCS7;->getContentInfo()Lsun/security/pkcs/ContentInfo;
-Lsun/security/pkcs/PKCS7;->getSignerInfos()[Lsun/security/pkcs/SignerInfo;
-Lsun/security/pkcs/PKCS7;->verify(Lsun/security/pkcs/SignerInfo;[B)Lsun/security/pkcs/SignerInfo;
-Lsun/security/pkcs/PKCS7;->verify([B)[Lsun/security/pkcs/SignerInfo;
-Lsun/security/pkcs/PKCS8Key;-><init>()V
-Lsun/security/pkcs/PKCS8Key;->algid:Lsun/security/x509/AlgorithmId;
-Lsun/security/pkcs/PKCS8Key;->encodedKey:[B
-Lsun/security/pkcs/PKCS8Key;->key:[B
-Lsun/security/pkcs/PKCS9Attribute;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
-Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/lang/Object;)V
-Lsun/security/pkcs/PKCS9Attribute;->CONTENT_TYPE_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/PKCS9Attribute;->derEncode(Ljava/io/OutputStream;)V
-Lsun/security/pkcs/PKCS9Attribute;->EMAIL_ADDRESS_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/PKCS9Attribute;->getOID()Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/PKCS9Attribute;->getValue()Ljava/lang/Object;
-Lsun/security/pkcs/PKCS9Attribute;->MESSAGE_DIGEST_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/PKCS9Attribute;->SIGNING_TIME_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;)V
-Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;Z)V
-Lsun/security/pkcs/PKCS9Attributes;-><init>([Lsun/security/pkcs/PKCS9Attribute;)V
-Lsun/security/pkcs/PKCS9Attributes;->encode(BLjava/io/OutputStream;)V
-Lsun/security/pkcs/PKCS9Attributes;->getAttribute(Ljava/lang/String;)Lsun/security/pkcs/PKCS9Attribute;
-Lsun/security/pkcs/PKCS9Attributes;->getAttributeValue(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Object;
-Lsun/security/pkcs/PKCS9Attributes;->getDerEncoding()[B
-Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/PKCS9Attributes;Lsun/security/x509/AlgorithmId;[BLsun/security/pkcs/PKCS9Attributes;)V
-Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;[B)V
-Lsun/security/pkcs/SignerInfo;->getCertificate(Lsun/security/pkcs/PKCS7;)Ljava/security/cert/X509Certificate;
-Lsun/security/pkcs/SignerInfo;->getCertificateChain(Lsun/security/pkcs/PKCS7;)Ljava/util/ArrayList;
-Lsun/security/pkcs/SignerInfo;->getDigestAlgorithmId()Lsun/security/x509/AlgorithmId;
-Lsun/security/pkcs/SignerInfo;->getDigestEncryptionAlgorithmId()Lsun/security/x509/AlgorithmId;
-Lsun/security/pkcs/SignerInfo;->getEncryptedDigest()[B
-Lsun/security/provider/certpath/X509CertificatePair;->clearCache()V
-Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;)V
-Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;Ljava/lang/String;)V
-Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/util/List;)V
-Lsun/security/provider/certpath/X509CertPath;->certs:Ljava/util/List;
-Lsun/security/provider/certpath/X509CertPath;->getEncodingsStatic()Ljava/util/Iterator;
-Lsun/security/provider/X509Factory;->addToCache(Lsun/security/util/Cache;[BLjava/lang/Object;)V
-Lsun/security/provider/X509Factory;->certCache:Lsun/security/util/Cache;
-Lsun/security/provider/X509Factory;->crlCache:Lsun/security/util/Cache;
-Lsun/security/provider/X509Factory;->getFromCache(Lsun/security/util/Cache;[B)Ljava/lang/Object;
-Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509Certificate;)Lsun/security/x509/X509CertImpl;
-Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509CRL;)Lsun/security/x509/X509CRLImpl;
-Lsun/security/timestamp/TimestampToken;-><init>([B)V
-Lsun/security/timestamp/TimestampToken;->getDate()Ljava/util/Date;
-Lsun/security/timestamp/TimestampToken;->getHashAlgorithm()Lsun/security/x509/AlgorithmId;
-Lsun/security/timestamp/TimestampToken;->getHashedMessage()[B
-Lsun/security/timestamp/TimestampToken;->getNonce()Ljava/math/BigInteger;
-Lsun/security/util/BitArray;-><init>(I[B)V
-Lsun/security/util/BitArray;->toByteArray()[B
-Lsun/security/util/Cache;-><init>()V
-Lsun/security/util/Cache;->clear()V
-Lsun/security/util/Cache;->get(Ljava/lang/Object;)Ljava/lang/Object;
-Lsun/security/util/Cache;->newHardMemoryCache(I)Lsun/security/util/Cache;
-Lsun/security/util/Cache;->put(Ljava/lang/Object;Ljava/lang/Object;)V
-Lsun/security/util/Debug;->getInstance(Ljava/lang/String;)Lsun/security/util/Debug;
-Lsun/security/util/Debug;->println()V
-Lsun/security/util/Debug;->println(Ljava/lang/String;)V
-Lsun/security/util/Debug;->toHexString(Ljava/math/BigInteger;)Ljava/lang/String;
-Lsun/security/util/DerIndefLenConverter;-><init>()V
-Lsun/security/util/DerIndefLenConverter;->convert([B)[B
-Lsun/security/util/DerIndefLenConverter;->data:[B
-Lsun/security/util/DerIndefLenConverter;->dataPos:I
-Lsun/security/util/DerIndefLenConverter;->dataSize:I
-Lsun/security/util/DerIndefLenConverter;->isIndefinite(I)Z
-Lsun/security/util/DerIndefLenConverter;->newData:[B
-Lsun/security/util/DerIndefLenConverter;->numOfTotalLenBytes:I
-Lsun/security/util/DerIndefLenConverter;->parseLength()I
-Lsun/security/util/DerIndefLenConverter;->parseTag()V
-Lsun/security/util/DerIndefLenConverter;->parseValue(I)V
-Lsun/security/util/DerIndefLenConverter;->writeLengthAndValue()V
-Lsun/security/util/DerIndefLenConverter;->writeTag()V
-Lsun/security/util/DerInputStream;-><init>([B)V
-Lsun/security/util/DerInputStream;->available()I
-Lsun/security/util/DerInputStream;->getBigInteger()Ljava/math/BigInteger;
-Lsun/security/util/DerInputStream;->getBitString()[B
-Lsun/security/util/DerInputStream;->getDerValue()Lsun/security/util/DerValue;
-Lsun/security/util/DerInputStream;->getInteger()I
-Lsun/security/util/DerInputStream;->getOctetString()[B
-Lsun/security/util/DerInputStream;->getOID()Lsun/security/util/ObjectIdentifier;
-Lsun/security/util/DerInputStream;->getSequence(I)[Lsun/security/util/DerValue;
-Lsun/security/util/DerInputStream;->getSet(I)[Lsun/security/util/DerValue;
-Lsun/security/util/DerInputStream;->getSet(IZ)[Lsun/security/util/DerValue;
-Lsun/security/util/DerInputStream;->getUTCTime()Ljava/util/Date;
-Lsun/security/util/DerInputStream;->getUTF8String()Ljava/lang/String;
-Lsun/security/util/DerInputStream;->mark(I)V
-Lsun/security/util/DerInputStream;->peekByte()I
-Lsun/security/util/DerInputStream;->reset()V
-Lsun/security/util/DerInputStream;->subStream(IZ)Lsun/security/util/DerInputStream;
-Lsun/security/util/DerInputStream;->tag:B
-Lsun/security/util/DerOutputStream;-><init>()V
-Lsun/security/util/DerOutputStream;-><init>(I)V
-Lsun/security/util/DerOutputStream;->putBitString([B)V
-Lsun/security/util/DerOutputStream;->putBoolean(Z)V
-Lsun/security/util/DerOutputStream;->putDerValue(Lsun/security/util/DerValue;)V
-Lsun/security/util/DerOutputStream;->putIA5String(Ljava/lang/String;)V
-Lsun/security/util/DerOutputStream;->putInteger(I)V
-Lsun/security/util/DerOutputStream;->putInteger(Ljava/math/BigInteger;)V
-Lsun/security/util/DerOutputStream;->putNull()V
-Lsun/security/util/DerOutputStream;->putOctetString([B)V
-Lsun/security/util/DerOutputStream;->putOID(Lsun/security/util/ObjectIdentifier;)V
-Lsun/security/util/DerOutputStream;->putOrderedSetOf(B[Lsun/security/util/DerEncoder;)V
-Lsun/security/util/DerOutputStream;->putPrintableString(Ljava/lang/String;)V
-Lsun/security/util/DerOutputStream;->putSequence([Lsun/security/util/DerValue;)V
-Lsun/security/util/DerOutputStream;->putUTCTime(Ljava/util/Date;)V
-Lsun/security/util/DerOutputStream;->putUTF8String(Ljava/lang/String;)V
-Lsun/security/util/DerOutputStream;->write(BLsun/security/util/DerOutputStream;)V
-Lsun/security/util/DerOutputStream;->write(B[B)V
-Lsun/security/util/DerValue;-><init>(B[B)V
-Lsun/security/util/DerValue;-><init>(Ljava/io/InputStream;)V
-Lsun/security/util/DerValue;-><init>(Ljava/lang/String;)V
-Lsun/security/util/DerValue;-><init>([B)V
-Lsun/security/util/DerValue;-><init>([BII)V
-Lsun/security/util/DerValue;->buffer:Lsun/security/util/DerInputBuffer;
-Lsun/security/util/DerValue;->createTag(BZB)B
-Lsun/security/util/DerValue;->data:Lsun/security/util/DerInputStream;
-Lsun/security/util/DerValue;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/util/DerValue;->getAsString()Ljava/lang/String;
-Lsun/security/util/DerValue;->getBigInteger()Ljava/math/BigInteger;
-Lsun/security/util/DerValue;->getBitString()[B
-Lsun/security/util/DerValue;->getData()Lsun/security/util/DerInputStream;
-Lsun/security/util/DerValue;->getDataBytes()[B
-Lsun/security/util/DerValue;->getOctetString()[B
-Lsun/security/util/DerValue;->getOID()Lsun/security/util/ObjectIdentifier;
-Lsun/security/util/DerValue;->getPositiveBigInteger()Ljava/math/BigInteger;
-Lsun/security/util/DerValue;->getUnalignedBitString()Lsun/security/util/BitArray;
-Lsun/security/util/DerValue;->isConstructed()Z
-Lsun/security/util/DerValue;->isContextSpecific()Z
-Lsun/security/util/DerValue;->isContextSpecific(B)Z
-Lsun/security/util/DerValue;->isPrintableStringChar(C)Z
-Lsun/security/util/DerValue;->resetTag(B)V
-Lsun/security/util/DerValue;->tag:B
-Lsun/security/util/DerValue;->toByteArray()[B
-Lsun/security/util/DerValue;->toDerInputStream()Lsun/security/util/DerInputStream;
-Lsun/security/util/ManifestDigester$Entry;->digest(Ljava/security/MessageDigest;)[B
-Lsun/security/util/ManifestDigester$Entry;->digestWorkaround(Ljava/security/MessageDigest;)[B
-Lsun/security/util/ManifestDigester;-><init>([B)V
-Lsun/security/util/ManifestDigester;->get(Ljava/lang/String;Z)Lsun/security/util/ManifestDigester$Entry;
-Lsun/security/util/ManifestDigester;->manifestDigest(Ljava/security/MessageDigest;)[B
-Lsun/security/util/MemoryCache$HardCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;J)V
-Lsun/security/util/MemoryCache$SoftCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;JLjava/lang/ref/ReferenceQueue;)V
-Lsun/security/util/ObjectIdentifier;-><init>(Ljava/lang/String;)V
-Lsun/security/util/ObjectIdentifier;-><init>([I)V
-Lsun/security/util/ObjectIdentifier;->equals(Lsun/security/util/ObjectIdentifier;)Z
-Lsun/security/util/ObjectIdentifier;->newInternal([I)Lsun/security/util/ObjectIdentifier;
-Lsun/security/util/PropertyExpander;->expand(Ljava/lang/String;)Ljava/lang/String;
-Lsun/security/util/ResourcesMgr;->getString(Ljava/lang/String;)Ljava/lang/String;
-Lsun/security/util/SecurityConstants;->CREATE_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
-Lsun/security/util/SecurityConstants;->GET_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
-Lsun/security/util/SecurityConstants;->MODIFY_THREADGROUP_PERMISSION:Ljava/lang/RuntimePermission;
-Lsun/security/util/SecurityConstants;->MODIFY_THREAD_PERMISSION:Ljava/lang/RuntimePermission;
-Lsun/security/util/SignatureFileVerifier;->isBlockOrSF(Ljava/lang/String;)Z
-Lsun/security/x509/AccessDescription;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/AccessDescription;->getAccessLocation()Lsun/security/x509/GeneralName;
-Lsun/security/x509/AccessDescription;->getAccessMethod()Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;-><init>()V
-Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;)V
-Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/security/AlgorithmParameters;)V
-Lsun/security/x509/AlgorithmId;->derEncode(Ljava/io/OutputStream;)V
-Lsun/security/x509/AlgorithmId;->DSA_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->EC_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->encode()[B
-Lsun/security/x509/AlgorithmId;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/x509/AlgorithmId;->equals(Lsun/security/x509/AlgorithmId;)Z
-Lsun/security/x509/AlgorithmId;->getAlgorithmId(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;
-Lsun/security/x509/AlgorithmId;->getDigAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
-Lsun/security/x509/AlgorithmId;->getEncAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
-Lsun/security/x509/AlgorithmId;->getEncodedParams()[B
-Lsun/security/x509/AlgorithmId;->getOID()Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->getParameters()Ljava/security/AlgorithmParameters;
-Lsun/security/x509/AlgorithmId;->MD2_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->MD5_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->params:Lsun/security/util/DerValue;
-Lsun/security/x509/AlgorithmId;->parse(Lsun/security/util/DerValue;)Lsun/security/x509/AlgorithmId;
-Lsun/security/x509/AlgorithmId;->RSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->sha1WithRSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->SHA256_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->SHA384_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->SHA512_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AlgorithmId;->SHA_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AttributeNameEnumeration;-><init>()V
-Lsun/security/x509/AVA;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
-Lsun/security/x509/AVA;->getDerValue()Lsun/security/util/DerValue;
-Lsun/security/x509/AVA;->getObjectIdentifier()Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AVA;->getValueString()Ljava/lang/String;
-Lsun/security/x509/AVA;->toRFC2253CanonicalString()Ljava/lang/String;
-Lsun/security/x509/AVAComparator;->INSTANCE:Ljava/util/Comparator;
-Lsun/security/x509/AVAKeyword;->getOID(Ljava/lang/String;ILjava/util/Map;)Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AVAKeyword;->isCompliant(I)Z
-Lsun/security/x509/AVAKeyword;->keyword:Ljava/lang/String;
-Lsun/security/x509/AVAKeyword;->keywordMap:Ljava/util/Map;
-Lsun/security/x509/AVAKeyword;->oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/AVAKeyword;->oidMap:Ljava/util/Map;
-Lsun/security/x509/CertificateAlgorithmId;-><init>(Lsun/security/x509/AlgorithmId;)V
-Lsun/security/x509/CertificateExtensions;-><init>()V
-Lsun/security/x509/CertificateExtensions;-><init>(Lsun/security/util/DerInputStream;)V
-Lsun/security/x509/CertificateExtensions;->encode(Ljava/io/OutputStream;Z)V
-Lsun/security/x509/CertificateExtensions;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/CertificateExtensions;->set(Ljava/lang/String;Ljava/lang/Object;)V
-Lsun/security/x509/CertificateIssuerName;-><init>(Lsun/security/x509/X500Name;)V
-Lsun/security/x509/CertificateSerialNumber;-><init>(I)V
-Lsun/security/x509/CertificateSerialNumber;-><init>(Ljava/math/BigInteger;)V
-Lsun/security/x509/CertificateSubjectName;-><init>(Lsun/security/x509/X500Name;)V
-Lsun/security/x509/CertificateSubjectName;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/CertificateValidity;-><init>(Ljava/util/Date;Ljava/util/Date;)V
-Lsun/security/x509/CertificateVersion;-><init>(I)V
-Lsun/security/x509/CertificateX509Key;-><init>(Ljava/security/PublicKey;)V
-Lsun/security/x509/CRLDistributionPointsExtension;->encodeThis()V
-Lsun/security/x509/CRLNumberExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V
-Lsun/security/x509/CRLNumberExtension;->encodeThis()V
-Lsun/security/x509/CRLNumberExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/Extension;-><init>(Lsun/security/x509/Extension;)V
-Lsun/security/x509/Extension;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/x509/Extension;->getExtensionId()Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/GeneralName;-><init>(Lsun/security/x509/GeneralNameInterface;)V
-Lsun/security/x509/GeneralName;->getName()Lsun/security/x509/GeneralNameInterface;
-Lsun/security/x509/GeneralName;->getType()I
-Lsun/security/x509/GeneralNames;-><init>()V
-Lsun/security/x509/GeneralNames;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/GeneralNames;->add(Lsun/security/x509/GeneralName;)Lsun/security/x509/GeneralNames;
-Lsun/security/x509/GeneralNames;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/x509/GeneralNames;->isEmpty()Z
-Lsun/security/x509/KeyIdentifier;-><init>(Ljava/security/PublicKey;)V
-Lsun/security/x509/KeyIdentifier;->getIdentifier()[B
-Lsun/security/x509/KeyIdentifier;->octetString:[B
-Lsun/security/x509/KeyUsageExtension;-><init>([Z)V
-Lsun/security/x509/KeyUsageExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/NetscapeCertTypeExtension;-><init>([B)V
-Lsun/security/x509/NetscapeCertTypeExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/OIDMap$OIDInfo;->clazz:Ljava/lang/Class;
-Lsun/security/x509/OIDMap;->getClass(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Class;
-Lsun/security/x509/OIDMap;->nameMap:Ljava/util/Map;
-Lsun/security/x509/OIDMap;->oidMap:Ljava/util/Map;
-Lsun/security/x509/PKIXExtensions;->CertificateIssuer_Id:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/SerialNumber;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/SubjectAlternativeNameExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/SubjectKeyIdentifierExtension;-><init>([B)V
-Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerInputStream;)V
-Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/UniqueIdentity;->encode(Lsun/security/util/DerOutputStream;B)V
-Lsun/security/x509/URIName;->getName()Ljava/lang/String;
-Lsun/security/x509/URIName;->getScheme()Ljava/lang/String;
-Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;)V
-Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerInputStream;)V
-Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/X500Name;-><init>([B)V
-Lsun/security/x509/X500Name;->allAvas()Ljava/util/List;
-Lsun/security/x509/X500Name;->asX500Name(Ljavax/security/auth/x500/X500Principal;)Lsun/security/x509/X500Name;
-Lsun/security/x509/X500Name;->asX500Principal()Ljavax/security/auth/x500/X500Principal;
-Lsun/security/x509/X500Name;->commonName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->countryName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->DNQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->DOMAIN_COMPONENT_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->encode(Lsun/security/util/DerOutputStream;)V
-Lsun/security/x509/X500Name;->GENERATIONQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->getCommonName()Ljava/lang/String;
-Lsun/security/x509/X500Name;->GIVENNAME_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->INITIALS_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->ipAddress_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->isEmpty()Z
-Lsun/security/x509/X500Name;->localityName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->orgName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->orgUnitName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->SERIALNUMBER_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->stateName_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->streetAddress_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->SURNAME_OID:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->title_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X500Name;->userid_oid:Lsun/security/util/ObjectIdentifier;
-Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/x509/X509CertInfo;)V
-Lsun/security/x509/X509CertImpl;-><init>([B)V
-Lsun/security/x509/X509CertImpl;->algId:Lsun/security/x509/AlgorithmId;
-Lsun/security/x509/X509CertImpl;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/X509CertImpl;->getEncodedInternal()[B
-Lsun/security/x509/X509CertImpl;->parse(Lsun/security/util/DerValue;)V
-Lsun/security/x509/X509CertImpl;->readOnly:Z
-Lsun/security/x509/X509CertImpl;->sign(Ljava/security/PrivateKey;Ljava/lang/String;)V
-Lsun/security/x509/X509CertImpl;->signature:[B
-Lsun/security/x509/X509CertImpl;->signedCert:[B
-Lsun/security/x509/X509CertInfo;-><init>()V
-Lsun/security/x509/X509CertInfo;-><init>([B)V
-Lsun/security/x509/X509CertInfo;->get(Ljava/lang/String;)Ljava/lang/Object;
-Lsun/security/x509/X509CertInfo;->set(Ljava/lang/String;Ljava/lang/Object;)V
-Lsun/security/x509/X509CRLEntryImpl;->getExtension(Lsun/security/util/ObjectIdentifier;)Lsun/security/x509/Extension;
-Lsun/security/x509/X509CRLImpl;-><init>(Ljava/io/InputStream;)V
-Lsun/security/x509/X509CRLImpl;-><init>(Lsun/security/util/DerValue;)V
-Lsun/security/x509/X509CRLImpl;-><init>([B)V
-Lsun/security/x509/X509CRLImpl;->getEncodedInternal()[B
-Lsun/security/x509/X509Key;-><init>()V
-Lsun/security/x509/X509Key;->algid:Lsun/security/x509/AlgorithmId;
-Lsun/security/x509/X509Key;->encodedKey:[B
-Lsun/security/x509/X509Key;->key:[B
-Lsun/security/x509/X509Key;->parse(Lsun/security/util/DerValue;)Ljava/security/PublicKey;
-Lsun/security/x509/X509Key;->unusedBits:I
-Lsun/util/calendar/AbstractCalendar;->getDayOfWeekDateOnOrBefore(JI)J
-Lsun/util/calendar/AbstractCalendar;->getTimeOfDayValue(Lsun/util/calendar/CalendarDate;)J
-Lsun/util/calendar/BaseCalendar$Date;->getNormalizedYear()I
-Lsun/util/calendar/BaseCalendar$Date;->setNormalizedYear(I)V
-Lsun/util/calendar/CalendarDate;->getDayOfMonth()I
-Lsun/util/calendar/CalendarDate;->getMonth()I
-Lsun/util/calendar/CalendarDate;->getTimeOfDay()J
-Lsun/util/calendar/CalendarDate;->getYear()I
-Lsun/util/calendar/CalendarDate;->setDate(III)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarDate;->setDayOfMonth(I)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarDate;->setHours(I)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarDate;->setMillis(I)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarDate;->setMinutes(I)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarDate;->setSeconds(I)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarSystem;->forName(Ljava/lang/String;)Lsun/util/calendar/CalendarSystem;
-Lsun/util/calendar/CalendarSystem;->getGregorianCalendar()Lsun/util/calendar/Gregorian;
-Lsun/util/calendar/CalendarSystem;->getTime(Lsun/util/calendar/CalendarDate;)J
-Lsun/util/calendar/CalendarSystem;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/CalendarSystem;->validate(Lsun/util/calendar/CalendarDate;)Z
-Lsun/util/calendar/CalendarUtils;->floorDivide(II)I
-Lsun/util/calendar/CalendarUtils;->floorDivide(JJ)J
-Lsun/util/calendar/CalendarUtils;->mod(II)I
-Lsun/util/calendar/CalendarUtils;->mod(JJ)J
-Lsun/util/calendar/Era;-><init>(Ljava/lang/String;Ljava/lang/String;JZ)V
-Lsun/util/calendar/Era;->getAbbreviation()Ljava/lang/String;
-Lsun/util/calendar/Era;->getName()Ljava/lang/String;
-Lsun/util/calendar/Era;->getSinceDate()Lsun/util/calendar/CalendarDate;
-Lsun/util/calendar/ImmutableGregorianDate;->unsupported()V
-Lsun/util/calendar/LocalGregorianCalendar$Date;->getNormalizedYear()I
-Lsun/util/calendar/LocalGregorianCalendar$Date;->setEra(Lsun/util/calendar/Era;)Lsun/util/calendar/LocalGregorianCalendar$Date;
-Lsun/util/calendar/LocalGregorianCalendar$Date;->setNormalizedYear(I)V
-Lsun/util/calendar/LocalGregorianCalendar$Date;->setYear(I)Lsun/util/calendar/LocalGregorianCalendar$Date;
-Lsun/util/calendar/LocalGregorianCalendar;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/LocalGregorianCalendar$Date;
-Lsun/util/calendar/LocalGregorianCalendar;->normalize(Lsun/util/calendar/CalendarDate;)Z
-Lsun/util/calendar/LocalGregorianCalendar;->validate(Lsun/util/calendar/CalendarDate;)Z
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 550e795..5940c45 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6172,6 +6172,9 @@
libcore.reflect.Types
libcore.reflect.WildcardTypeImpl
libcore.timezone.TimeZoneDataFiles
+libcore.timezone.ZoneInfoDB
+libcore.timezone.ZoneInfoDB$TzData
+libcore.timezone.ZoneInfoDB$TzData$1
libcore.util.BasicLruCache
libcore.util.CharsetUtils
libcore.util.CollectionUtils
@@ -6184,9 +6187,6 @@
libcore.util.ZoneInfo
libcore.util.ZoneInfo$CheckedArithmeticException
libcore.util.ZoneInfo$WallTime
-libcore.util.ZoneInfoDB
-libcore.util.ZoneInfoDB$TzData
-libcore.util.ZoneInfoDB$TzData$1
org.apache.harmony.dalvik.NativeTestTarget
org.apache.harmony.dalvik.ddmc.Chunk
org.apache.harmony.dalvik.ddmc.ChunkHandler
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 83fab7e..05bb9a1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -827,6 +827,8 @@
/** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */
@Nullable private IntelligenceManager mIntelligenceManager;
+ private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
+ new ArrayList<Application.ActivityLifecycleCallbacks>();
static final class NonConfigurationInstances {
Object activity;
@@ -1065,6 +1067,288 @@
}
/**
+ * Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
+ * lifecycle callbacks for only this Activity.
+ * <p>
+ * In relation to any
+ * {@link Application#registerActivityLifecycleCallbacks Application registered callbacks},
+ * the callbacks registered here will always occur nested within those callbacks. This means:
+ * <ul>
+ * <li>Pre events will first be sent to Application registered callbacks, then to callbacks
+ * registered here.</li>
+ * <li>{@link Application.ActivityLifecycleCallbacks#onActivityCreated(Activity, Bundle)},
+ * {@link Application.ActivityLifecycleCallbacks#onActivityStarted(Activity)}, and
+ * {@link Application.ActivityLifecycleCallbacks#onActivityResumed(Activity)} will
+ * be sent first to Application registered callbacks, then to callbacks registered here.
+ * For all other events, callbacks registered here will be sent first.</li>
+ * <li>Post events will first be sent to callbacks registered here, then to
+ * Application registered callbacks.</li>
+ * </ul>
+ * <p>
+ * If multiple callbacks are registered here, they receive events in a first in (up through
+ * {@link Application.ActivityLifecycleCallbacks#onActivityPostResumed}, last out
+ * ordering.
+ * <p>
+ * It is strongly recommended to register this in the constructor of your Activity to ensure
+ * you get all available callbacks. As this callback is associated with only this Activity,
+ * it is not usually necessary to {@link #unregisterActivityLifecycleCallbacks unregister} it
+ * unless you specifically do not want to receive further lifecycle callbacks.
+ *
+ * @param callback The callback instance to register
+ */
+ public void registerActivityLifecycleCallbacks(
+ @NonNull Application.ActivityLifecycleCallbacks callback) {
+ synchronized (mActivityLifecycleCallbacks) {
+ mActivityLifecycleCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Unregister an {@link Application.ActivityLifecycleCallbacks} previously registered
+ * with {@link #registerActivityLifecycleCallbacks}. It will not receive any further
+ * callbacks.
+ *
+ * @param callback The callback instance to unregister
+ * @see #registerActivityLifecycleCallbacks
+ */
+ public void unregisterActivityLifecycleCallbacks(
+ @NonNull Application.ActivityLifecycleCallbacks callback) {
+ synchronized (mActivityLifecycleCallbacks) {
+ mActivityLifecycleCallbacks.remove(callback);
+ }
+ }
+
+ private void dispatchActivityPreCreated(@Nullable Bundle savedInstanceState) {
+ getApplication().dispatchActivityPreCreated(this, savedInstanceState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(this,
+ savedInstanceState);
+ }
+ }
+ }
+
+ private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) {
+ getApplication().dispatchActivityCreated(this, savedInstanceState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(this,
+ savedInstanceState);
+ }
+ }
+ }
+
+ private void dispatchActivityPostCreated(@Nullable Bundle savedInstanceState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(this,
+ savedInstanceState);
+ }
+ }
+ getApplication().dispatchActivityPostCreated(this, savedInstanceState);
+ }
+
+ private void dispatchActivityPreStarted() {
+ getApplication().dispatchActivityPreStarted(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(this);
+ }
+ }
+ }
+
+ private void dispatchActivityStarted() {
+ getApplication().dispatchActivityStarted(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPostStarted() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostStarted(this);
+ }
+ }
+ getApplication().dispatchActivityPostStarted(this);
+ }
+
+ private void dispatchActivityPreResumed() {
+ getApplication().dispatchActivityPreResumed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityResumed() {
+ getApplication().dispatchActivityResumed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityResumed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPostResumed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = 0; i < callbacks.length; i++) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(this);
+ }
+ }
+ getApplication().dispatchActivityPostResumed(this);
+ }
+
+ private void dispatchActivityPrePaused() {
+ getApplication().dispatchActivityPrePaused(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(this);
+ }
+ }
+ }
+
+ private void dispatchActivityPaused() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPaused(this);
+ }
+ }
+ getApplication().dispatchActivityPaused(this);
+ }
+
+ private void dispatchActivityPostPaused() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(this);
+ }
+ }
+ getApplication().dispatchActivityPostPaused(this);
+ }
+
+ private void dispatchActivityPreStopped() {
+ getApplication().dispatchActivityPreStopped(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(this);
+ }
+ }
+ }
+
+ private void dispatchActivityStopped() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStopped(this);
+ }
+ }
+ getApplication().dispatchActivityStopped(this);
+ }
+
+ private void dispatchActivityPostStopped() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostStopped(this);
+ }
+ }
+ getApplication().dispatchActivityPostStopped(this);
+ }
+
+ private void dispatchActivityPreSaveInstanceState(@NonNull Bundle outState) {
+ getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPreSaveInstanceState(this, outState);
+ }
+ }
+ }
+
+ private void dispatchActivitySaveInstanceState(@NonNull Bundle outState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivitySaveInstanceState(this, outState);
+ }
+ }
+ getApplication().dispatchActivitySaveInstanceState(this, outState);
+ }
+
+ private void dispatchActivityPostSaveInstanceState(@NonNull Bundle outState) {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostSaveInstanceState(this, outState);
+ }
+ }
+ getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ }
+
+ private void dispatchActivityPreDestroyed() {
+ getApplication().dispatchActivityPreDestroyed(this);
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPreDestroyed(this);
+ }
+ }
+ }
+
+ private void dispatchActivityDestroyed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityDestroyed(this);
+ }
+ }
+ getApplication().dispatchActivityDestroyed(this);
+ }
+
+ private void dispatchActivityPostDestroyed() {
+ Object[] callbacks = collectActivityLifecycleCallbacks();
+ if (callbacks != null) {
+ for (int i = callbacks.length - 1; i >= 0; i--) {
+ ((Application.ActivityLifecycleCallbacks) callbacks[i])
+ .onActivityPostDestroyed(this);
+ }
+ }
+ getApplication().dispatchActivityPostDestroyed(this);
+ }
+
+ private Object[] collectActivityLifecycleCallbacks() {
+ Object[] callbacks = null;
+ synchronized (mActivityLifecycleCallbacks) {
+ if (mActivityLifecycleCallbacks.size() > 0) {
+ callbacks = mActivityLifecycleCallbacks.toArray();
+ }
+ }
+ return callbacks;
+ }
+
+ /**
* Called when the activity is starting. This is where most initialization
* should go: calling {@link #setContentView(int)} to inflate the
* activity's UI, using {@link #findViewById} to programmatically interact
@@ -1119,7 +1403,7 @@
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
- getApplication().dispatchActivityCreated(this, savedInstanceState);
+ dispatchActivityCreated(savedInstanceState);
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
@@ -1355,7 +1639,7 @@
mFragments.doLoaderStart();
- getApplication().dispatchActivityStarted(this);
+ dispatchActivityStarted();
if (mAutoFillResetNeeded) {
getAutofillManager().onVisibleForAutofill();
@@ -1426,7 +1710,7 @@
@CallSuper
protected void onResume() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
- getApplication().dispatchActivityResumed(this);
+ dispatchActivityResumed();
mActivityTransitionState.onResume(this, isTopOfTask());
enableAutofillCompatibilityIfNeeded();
if (mAutoFillResetNeeded) {
@@ -1642,13 +1926,13 @@
* @param outState The bundle to save the state to.
*/
final void performSaveInstanceState(@NonNull Bundle outState) {
- getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ dispatchActivityPreSaveInstanceState(outState);
onSaveInstanceState(outState);
saveManagedDialogs(outState);
mActivityTransitionState.saveState(outState);
storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
- getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ dispatchActivityPostSaveInstanceState(outState);
}
/**
@@ -1662,13 +1946,13 @@
*/
final void performSaveInstanceState(@NonNull Bundle outState,
@NonNull PersistableBundle outPersistentState) {
- getApplication().dispatchActivityPreSaveInstanceState(this, outState);
+ dispatchActivityPreSaveInstanceState(outState);
onSaveInstanceState(outState, outPersistentState);
saveManagedDialogs(outState);
storeHasCurrentPermissionRequest(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
", " + outPersistentState);
- getApplication().dispatchActivityPostSaveInstanceState(this, outState);
+ dispatchActivityPostSaveInstanceState(outState);
}
/**
@@ -1731,7 +2015,7 @@
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
- getApplication().dispatchActivitySaveInstanceState(this, outState);
+ dispatchActivitySaveInstanceState(outState);
}
/**
@@ -1831,7 +2115,7 @@
@CallSuper
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
- getApplication().dispatchActivityPaused(this);
+ dispatchActivityPaused();
if (mAutoFillResetNeeded) {
if (!mAutoFillIgnoreFirstResumePause) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "autofill notifyViewExited " + this);
@@ -2015,7 +2299,7 @@
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
mActivityTransitionState.onStop();
- getApplication().dispatchActivityStopped(this);
+ dispatchActivityStopped();
mTranslucentCallback = null;
mCalled = true;
@@ -2104,7 +2388,7 @@
mActionBar.onDestroy();
}
- getApplication().dispatchActivityDestroyed(this);
+ dispatchActivityDestroyed();
notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
@@ -7284,7 +7568,7 @@
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
- getApplication().dispatchActivityPreCreated(this, icicle);
+ dispatchActivityPreCreated(icicle);
mCanEnterPictureInPicture = true;
restoreHasCurrentPermissionRequest(icicle);
if (persistentState != null) {
@@ -7299,7 +7583,7 @@
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
- getApplication().dispatchActivityPostCreated(this, icicle);
+ dispatchActivityPostCreated(icicle);
}
final void performNewIntent(@NonNull Intent intent) {
@@ -7308,7 +7592,7 @@
}
final void performStart(String reason) {
- getApplication().dispatchActivityPreStarted(this);
+ dispatchActivityPreStarted();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
mFragments.noteStateNotSaved();
mCalled = false;
@@ -7351,7 +7635,7 @@
}
mActivityTransitionState.enterReady(this);
- getApplication().dispatchActivityPostStarted(this);
+ dispatchActivityPostStarted();
}
/**
@@ -7406,7 +7690,7 @@
}
final void performResume(boolean followedByPause, String reason) {
- getApplication().dispatchActivityPreResumed(this);
+ dispatchActivityPreResumed();
performRestart(true /* start */, reason);
mFragments.execPendingActions();
@@ -7456,11 +7740,11 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onPostResume()");
}
- getApplication().dispatchActivityPostResumed(this);
+ dispatchActivityPostResumed();
}
final void performPause() {
- getApplication().dispatchActivityPrePaused(this);
+ dispatchActivityPrePaused();
mDoReportFullyDrawn = false;
mFragments.dispatchPause();
mCalled = false;
@@ -7473,7 +7757,7 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onPause()");
}
- getApplication().dispatchActivityPostPaused(this);
+ dispatchActivityPostPaused();
}
final void performUserLeaving() {
@@ -7489,7 +7773,7 @@
mCanEnterPictureInPicture = false;
if (!mStopped) {
- getApplication().dispatchActivityPreStopped(this);
+ dispatchActivityPreStopped();
if (mWindow != null) {
mWindow.closeAllPanels();
}
@@ -7524,13 +7808,13 @@
}
mStopped = true;
- getApplication().dispatchActivityPostStopped(this);
+ dispatchActivityPostStopped();
}
mResumed = false;
}
final void performDestroy() {
- getApplication().dispatchActivityPreDestroyed(this);
+ dispatchActivityPreDestroyed();
mDestroyed = true;
mWindow.destroy();
mFragments.dispatchDestroy();
@@ -7540,7 +7824,7 @@
if (mVoiceInteractor != null) {
mVoiceInteractor.detachActivity();
}
- getApplication().dispatchActivityPostDestroyed(this);
+ dispatchActivityPostDestroyed();
}
final void dispatchMultiWindowModeChanged(boolean isInMultiWindowMode,
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 1edd7f5..af3da0c 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -243,6 +243,8 @@
public abstract void ensureBootCompleted();
public abstract void updateOomLevelsForDisplay(int displayId);
public abstract boolean isActivityStartsLoggingEnabled();
+ /** Returns true if the background activity starts is enabled. */
+ public abstract boolean isBackgroundActivityStartsEnabled();
public abstract void reportCurKeyguardUsageEvent(boolean keyguardShowing);
/** Input dispatch timeout to a window, start the ANR process. */
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 56ccf6f..6fdf7c8 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -433,4 +433,18 @@
}
return sb.toString();
}
+
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ try {
+ getService().clearLaunchParamsForPackages(packageNames);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 9b13420..2f0f14aa 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -35,7 +35,7 @@
import android.util.Log;
import android.util.proto.ProtoOutputStream;
-import libcore.util.ZoneInfoDB;
+import libcore.timezone.ZoneInfoDB;
import java.io.IOException;
import java.lang.annotation.Retention;
diff --git a/core/java/android/app/AppDetailsActivity.java b/core/java/android/app/AppDetailsActivity.java
index cd36e63..b71af88 100644
--- a/core/java/android/app/AppDetailsActivity.java
+++ b/core/java/android/app/AppDetailsActivity.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.TestApi;
import android.content.Intent;
import android.os.Bundle;
@@ -24,7 +25,9 @@
*
* @hide
*/
+@TestApi
public class AppDetailsActivity extends Activity {
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 8a797dc..7312b2c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2981,4 +2981,13 @@
throw e.rethrowAsRuntimeException();
}
}
+
+ @Override
+ public void sendDeviceCustomizationReadyBroadcast() {
+ try {
+ mPM.sendDeviceCustomizationReadyBroadcast();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 09b77d5..777a494 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -445,4 +445,9 @@
void setPackageScreenCompatMode(in String packageName, int mode);
boolean getPackageAskScreenCompat(in String packageName);
void setPackageAskScreenCompat(in String packageName, boolean ask);
+
+ /**
+ * Clears launch params for given packages.
+ */
+ void clearLaunchParamsForPackages(in List<String> packageNames);
}
diff --git a/core/java/android/app/Notification.aidl b/core/java/android/app/Notification.aidl
index 9d8129c..8a7156e 100644
--- a/core/java/android/app/Notification.aidl
+++ b/core/java/android/app/Notification.aidl
@@ -17,3 +17,4 @@
package android.app;
parcelable Notification;
+parcelable Notification.Action;
\ No newline at end of file
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 75b56f3..5002a81 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4436,15 +4436,15 @@
return bitmap;
}
- private void bindProfileBadge(RemoteViews contentView) {
+ private void bindProfileBadge(RemoteViews contentView, StandardTemplateParams p) {
Bitmap profileBadge = getProfileBadge();
if (profileBadge != null) {
contentView.setImageViewBitmap(R.id.profile_badge, profileBadge);
contentView.setViewVisibility(R.id.profile_badge, View.VISIBLE);
- if (isColorized()) {
+ if (isColorized(p)) {
contentView.setDrawableTint(R.id.profile_badge, false,
- getPrimaryTextColor(), PorterDuff.Mode.SRC_ATOP);
+ getPrimaryTextColor(p), PorterDuff.Mode.SRC_ATOP);
}
}
}
@@ -4507,16 +4507,6 @@
result);
}
- /**
- * @param hasProgress whether the progress bar should be shown and set
- * @param result
- */
- private RemoteViews applyStandardTemplate(int resId, boolean hasProgress,
- TemplateBindResult result) {
- return applyStandardTemplate(resId, mParams.reset().hasProgress(hasProgress)
- .fillTextsFrom(this), result);
- }
-
private RemoteViews applyStandardTemplate(int resId, StandardTemplateParams p,
TemplateBindResult result) {
RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
@@ -4524,15 +4514,15 @@
resetStandardTemplate(contentView);
final Bundle ex = mN.extras;
- updateBackgroundColor(contentView);
- bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
+ updateBackgroundColor(contentView, p);
+ bindNotificationHeader(contentView, p);
bindLargeIconAndReply(contentView, p, result);
- boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
+ boolean showProgress = handleProgressBar(contentView, ex, p);
if (p.title != null) {
contentView.setViewVisibility(R.id.title, View.VISIBLE);
contentView.setTextViewText(R.id.title, processTextSpans(p.title));
if (!p.ambient) {
- setTextViewColorPrimary(contentView, R.id.title);
+ setTextViewColorPrimary(contentView, R.id.title, p);
}
contentView.setViewLayoutWidth(R.id.title, showProgress
? ViewGroup.LayoutParams.WRAP_CONTENT
@@ -4543,7 +4533,7 @@
: com.android.internal.R.id.text;
contentView.setTextViewText(textId, processTextSpans(p.text));
if (!p.ambient) {
- setTextViewColorSecondary(contentView, textId);
+ setTextViewColorSecondary(contentView, textId, p);
}
contentView.setViewVisibility(textId, View.VISIBLE);
}
@@ -4560,8 +4550,9 @@
return text;
}
- private void setTextViewColorPrimary(RemoteViews contentView, int id) {
- ensureColors();
+ private void setTextViewColorPrimary(RemoteViews contentView, int id,
+ StandardTemplateParams p) {
+ ensureColors(p);
contentView.setTextColor(id, mPrimaryTextColor);
}
@@ -4570,42 +4561,63 @@
}
/**
- * @return the primary text color
+ * Return the primary text color using the existing template params
* @hide
*/
@VisibleForTesting
public int getPrimaryTextColor() {
- ensureColors();
+ return getPrimaryTextColor(mParams);
+ }
+
+ /**
+ * @param p the template params to inflate this with
+ * @return the primary text color
+ * @hide
+ */
+ @VisibleForTesting
+ public int getPrimaryTextColor(StandardTemplateParams p) {
+ ensureColors(p);
return mPrimaryTextColor;
}
/**
- * @return the secondary text color
+ * Return the secondary text color using the existing template params
* @hide
*/
@VisibleForTesting
public int getSecondaryTextColor() {
- ensureColors();
+ return getSecondaryTextColor(mParams);
+ }
+
+ /**
+ * @param p the template params to inflate this with
+ * @return the secondary text color
+ * @hide
+ */
+ @VisibleForTesting
+ public int getSecondaryTextColor(StandardTemplateParams p) {
+ ensureColors(p);
return mSecondaryTextColor;
}
- private void setTextViewColorSecondary(RemoteViews contentView, int id) {
- ensureColors();
+ private void setTextViewColorSecondary(RemoteViews contentView, int id,
+ StandardTemplateParams p) {
+ ensureColors(p);
contentView.setTextColor(id, mSecondaryTextColor);
}
- private void ensureColors() {
- int backgroundColor = getBackgroundColor();
+ private void ensureColors(StandardTemplateParams p) {
+ int backgroundColor = getBackgroundColor(p);
if (mPrimaryTextColor == COLOR_INVALID
|| mSecondaryTextColor == COLOR_INVALID
|| mTextColorsAreForBackground != backgroundColor) {
mTextColorsAreForBackground = backgroundColor;
- if (!hasForegroundColor() || !isColorized()) {
+ if (!hasForegroundColor() || !isColorized(p)) {
mPrimaryTextColor = ContrastColorUtil.resolvePrimaryColor(mContext,
backgroundColor, mInNightMode);
mSecondaryTextColor = ContrastColorUtil.resolveSecondaryColor(mContext,
backgroundColor, mInNightMode);
- if (backgroundColor != COLOR_DEFAULT && isColorized()) {
+ if (backgroundColor != COLOR_DEFAULT && isColorized(p)) {
mPrimaryTextColor = ContrastColorUtil.findAlphaToMeetContrast(
mPrimaryTextColor, backgroundColor, 4.5);
mSecondaryTextColor = ContrastColorUtil.findAlphaToMeetContrast(
@@ -4673,10 +4685,11 @@
}
}
- private void updateBackgroundColor(RemoteViews contentView) {
- if (isColorized()) {
+ private void updateBackgroundColor(RemoteViews contentView,
+ StandardTemplateParams p) {
+ if (isColorized(p)) {
contentView.setInt(R.id.status_bar_latest_event_content, "setBackgroundColor",
- getBackgroundColor());
+ getBackgroundColor(p));
} else {
// Clear it!
contentView.setInt(R.id.status_bar_latest_event_content, "setBackgroundResource",
@@ -4699,19 +4712,20 @@
remoteView.setInt(R.id.notification_main_column, "setMinimumHeight", minHeight);
}
- private boolean handleProgressBar(boolean hasProgress, RemoteViews contentView, Bundle ex) {
+ private boolean handleProgressBar(RemoteViews contentView, Bundle ex,
+ StandardTemplateParams p) {
final int max = ex.getInt(EXTRA_PROGRESS_MAX, 0);
final int progress = ex.getInt(EXTRA_PROGRESS, 0);
final boolean ind = ex.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
- if (hasProgress && (max != 0 || ind)) {
+ if (p.hasProgress && (max != 0 || ind)) {
contentView.setViewVisibility(com.android.internal.R.id.progress, View.VISIBLE);
contentView.setProgressBar(
R.id.progress, max, progress, ind);
contentView.setProgressBackgroundTintList(
R.id.progress, ColorStateList.valueOf(mContext.getColor(
R.color.notification_progress_background_color)));
- if (mN.color != COLOR_DEFAULT) {
- ColorStateList colorStateList = ColorStateList.valueOf(resolveContrastColor());
+ if (getRawColor(p) != COLOR_DEFAULT) {
+ ColorStateList colorStateList = ColorStateList.valueOf(resolveContrastColor(p));
contentView.setProgressTintList(R.id.progress, colorStateList);
contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList);
}
@@ -4724,8 +4738,8 @@
private void bindLargeIconAndReply(RemoteViews contentView, StandardTemplateParams p,
TemplateBindResult result) {
- boolean largeIconShown = bindLargeIcon(contentView, p.hideLargeIcon || p.ambient);
- boolean replyIconShown = bindReplyIcon(contentView, p.hideReplyIcon || p.ambient);
+ boolean largeIconShown = bindLargeIcon(contentView, p);
+ boolean replyIconShown = bindReplyIcon(contentView, p);
contentView.setViewVisibility(R.id.right_icon_container,
largeIconShown || replyIconShown ? View.VISIBLE : View.GONE);
int marginEnd = calculateMarginEnd(largeIconShown, replyIconShown);
@@ -4773,15 +4787,15 @@
* Bind the large icon.
* @return if the largeIcon is visible
*/
- private boolean bindLargeIcon(RemoteViews contentView, boolean hideLargeIcon) {
+ private boolean bindLargeIcon(RemoteViews contentView, StandardTemplateParams p) {
if (mN.mLargeIcon == null && mN.largeIcon != null) {
mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon);
}
- boolean showLargeIcon = mN.mLargeIcon != null && !hideLargeIcon;
+ boolean showLargeIcon = mN.mLargeIcon != null && !p.hideLargeIcon && !p.ambient;
if (showLargeIcon) {
contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
- processLargeLegacyIcon(mN.mLargeIcon, contentView);
+ processLargeLegacyIcon(mN.mLargeIcon, contentView, p);
}
return showLargeIcon;
}
@@ -4790,8 +4804,8 @@
* Bind the reply icon.
* @return if the reply icon is visible
*/
- private boolean bindReplyIcon(RemoteViews contentView, boolean hideReplyIcon) {
- boolean actionVisible = !hideReplyIcon;
+ private boolean bindReplyIcon(RemoteViews contentView, StandardTemplateParams p) {
+ boolean actionVisible = !p.hideReplyIcon && !p.ambient;
Action action = null;
if (actionVisible) {
action = findReplyAction();
@@ -4801,7 +4815,7 @@
contentView.setViewVisibility(R.id.reply_icon_action, View.VISIBLE);
contentView.setDrawableTint(R.id.reply_icon_action,
false /* targetBackground */,
- getNeutralColor(),
+ getNeutralColor(p),
PorterDuff.Mode.SRC_ATOP);
contentView.setOnClickPendingIntent(R.id.reply_icon_action, action.actionIntent);
contentView.setRemoteInputs(R.id.reply_icon_action, action.mRemoteInputs);
@@ -4828,41 +4842,41 @@
return null;
}
- private void bindNotificationHeader(RemoteViews contentView, boolean ambient,
- CharSequence secondaryHeaderText) {
- bindSmallIcon(contentView, ambient);
- bindHeaderAppName(contentView, ambient);
- if (!ambient) {
+ private void bindNotificationHeader(RemoteViews contentView, StandardTemplateParams p) {
+ bindSmallIcon(contentView, p);
+ bindHeaderAppName(contentView, p);
+ if (!p.ambient) {
// Ambient view does not have these
- bindHeaderText(contentView);
- bindHeaderTextSecondary(contentView, secondaryHeaderText);
- bindHeaderChronometerAndTime(contentView);
- bindProfileBadge(contentView);
+ bindHeaderText(contentView, p);
+ bindHeaderTextSecondary(contentView, p);
+ bindHeaderChronometerAndTime(contentView, p);
+ bindProfileBadge(contentView, p);
}
- bindActivePermissions(contentView, ambient);
- bindExpandButton(contentView);
+ bindActivePermissions(contentView, p);
+ bindExpandButton(contentView, p);
mN.mUsesStandardHeader = true;
}
- private void bindActivePermissions(RemoteViews contentView, boolean ambient) {
- int color = ambient ? resolveAmbientColor() : getNeutralColor();
+ private void bindActivePermissions(RemoteViews contentView, StandardTemplateParams p) {
+ int color = p.ambient ? resolveAmbientColor(p) : getNeutralColor(p);
contentView.setDrawableTint(R.id.camera, false, color, PorterDuff.Mode.SRC_ATOP);
contentView.setDrawableTint(R.id.mic, false, color, PorterDuff.Mode.SRC_ATOP);
contentView.setDrawableTint(R.id.overlay, false, color, PorterDuff.Mode.SRC_ATOP);
}
- private void bindExpandButton(RemoteViews contentView) {
- int color = isColorized() ? getPrimaryTextColor() : getSecondaryTextColor();
+ private void bindExpandButton(RemoteViews contentView, StandardTemplateParams p) {
+ int color = isColorized(p) ? getPrimaryTextColor(p) : getSecondaryTextColor(p);
contentView.setDrawableTint(R.id.expand_button, false, color,
PorterDuff.Mode.SRC_ATOP);
contentView.setInt(R.id.notification_header, "setOriginalNotificationColor",
color);
}
- private void bindHeaderChronometerAndTime(RemoteViews contentView) {
+ private void bindHeaderChronometerAndTime(RemoteViews contentView,
+ StandardTemplateParams p) {
if (showsTimeOrChronometer()) {
contentView.setViewVisibility(R.id.time_divider, View.VISIBLE);
- setTextViewColorSecondary(contentView, R.id.time_divider);
+ setTextViewColorSecondary(contentView, R.id.time_divider, p);
if (mN.extras.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
contentView.setLong(R.id.chronometer, "setBase",
@@ -4870,11 +4884,11 @@
contentView.setBoolean(R.id.chronometer, "setStarted", true);
boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN);
contentView.setChronometerCountDown(R.id.chronometer, countsDown);
- setTextViewColorSecondary(contentView, R.id.chronometer);
+ setTextViewColorSecondary(contentView, R.id.chronometer, p);
} else {
contentView.setViewVisibility(R.id.time, View.VISIBLE);
contentView.setLong(R.id.time, "setTime", mN.when);
- setTextViewColorSecondary(contentView, R.id.time);
+ setTextViewColorSecondary(contentView, R.id.time, p);
}
} else {
// We still want a time to be set but gone, such that we can show and hide it
@@ -4883,36 +4897,36 @@
}
}
- private void bindHeaderText(RemoteViews contentView) {
- CharSequence headerText = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
- if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
+ private void bindHeaderText(RemoteViews contentView, StandardTemplateParams p) {
+ CharSequence summaryText = p.summaryText;
+ if (summaryText == null && mStyle != null && mStyle.mSummaryTextSet
&& mStyle.hasSummaryInHeader()) {
- headerText = mStyle.mSummaryText;
+ summaryText = mStyle.mSummaryText;
}
- if (headerText == null
+ if (summaryText == null
&& mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
- headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+ summaryText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
}
- if (headerText != null) {
+ if (summaryText != null) {
// TODO: Remove the span entirely to only have the string with propper formating.
contentView.setTextViewText(R.id.header_text, processTextSpans(
- processLegacyText(headerText)));
- setTextViewColorSecondary(contentView, R.id.header_text);
+ processLegacyText(summaryText)));
+ setTextViewColorSecondary(contentView, R.id.header_text, p);
contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE);
- setTextViewColorSecondary(contentView, R.id.header_text_divider);
+ setTextViewColorSecondary(contentView, R.id.header_text_divider, p);
}
}
- private void bindHeaderTextSecondary(RemoteViews contentView, CharSequence secondaryText) {
- if (!TextUtils.isEmpty(secondaryText)) {
+ private void bindHeaderTextSecondary(RemoteViews contentView, StandardTemplateParams p) {
+ if (!TextUtils.isEmpty(p.headerTextSecondary)) {
contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
- processLegacyText(secondaryText)));
- setTextViewColorSecondary(contentView, R.id.header_text_secondary);
+ processLegacyText(p.headerTextSecondary)));
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary, p);
contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
contentView.setViewVisibility(R.id.header_text_secondary_divider, View.VISIBLE);
- setTextViewColorSecondary(contentView, R.id.header_text_secondary_divider);
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary_divider, p);
}
}
@@ -4950,23 +4964,27 @@
return String.valueOf(name);
}
- private void bindHeaderAppName(RemoteViews contentView, boolean ambient) {
+ private void bindHeaderAppName(RemoteViews contentView, StandardTemplateParams p) {
contentView.setTextViewText(R.id.app_name_text, loadHeaderAppName());
- if (isColorized() && !ambient) {
- setTextViewColorPrimary(contentView, R.id.app_name_text);
+ if (isColorized(p)) {
+ setTextViewColorPrimary(contentView, R.id.app_name_text, p);
} else {
contentView.setTextColor(R.id.app_name_text,
- ambient ? resolveAmbientColor() : getSecondaryTextColor());
+ p.ambient ? resolveAmbientColor(p) : getSecondaryTextColor(p));
}
}
- private void bindSmallIcon(RemoteViews contentView, boolean ambient) {
+ private boolean isColorized(StandardTemplateParams p) {
+ return p.allowColorization && !p.ambient && mN.isColorized();
+ }
+
+ private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) {
if (mN.mSmallIcon == null && mN.icon != 0) {
mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
}
contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel);
- processSmallIconColor(mN.mSmallIcon, contentView, ambient);
+ processSmallIconColor(mN.mSmallIcon, contentView, p);
}
/**
@@ -5041,8 +5059,7 @@
boolean actionHasValidInput = hasValidRemoteInput(action);
validRemoteInput |= actionHasValidInput;
- final RemoteViews button = generateActionButton(action, emphazisedMode,
- p.ambient);
+ final RemoteViews button = generateActionButton(action, emphazisedMode, p);
if (actionHasValidInput && !emphazisedMode) {
// Clear the drawable
button.setInt(R.id.action0, "setBackgroundResource", 0);
@@ -5063,20 +5080,20 @@
View.VISIBLE);
big.setTextViewText(R.id.notification_material_reply_text_1,
processTextSpans(replyText[0]));
- setTextViewColorSecondary(big, R.id.notification_material_reply_text_1);
+ setTextViewColorSecondary(big, R.id.notification_material_reply_text_1, p);
big.setViewVisibility(R.id.notification_material_reply_progress,
showSpinner ? View.VISIBLE : View.GONE);
big.setProgressIndeterminateTintList(
R.id.notification_material_reply_progress,
ColorStateList.valueOf(
- isColorized() ? getPrimaryTextColor() : resolveContrastColor()));
+ isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p)));
if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])
&& p.maxRemoteInputHistory > 1) {
big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
big.setTextViewText(R.id.notification_material_reply_text_2,
processTextSpans(replyText[1]));
- setTextViewColorSecondary(big, R.id.notification_material_reply_text_2);
+ setTextViewColorSecondary(big, R.id.notification_material_reply_text_2, p);
if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])
&& p.maxRemoteInputHistory > 2) {
@@ -5084,7 +5101,7 @@
R.id.notification_material_reply_text_3, View.VISIBLE);
big.setTextViewText(R.id.notification_material_reply_text_3,
processTextSpans(replyText[2]));
- setTextViewColorSecondary(big, R.id.notification_material_reply_text_3);
+ setTextViewColorSecondary(big, R.id.notification_material_reply_text_3, p);
}
}
}
@@ -5175,18 +5192,23 @@
* @hide
*/
public RemoteViews makeNotificationHeader(boolean ambient) {
- Boolean colorized = (Boolean) mN.extras.get(EXTRA_COLORIZED);
- mN.extras.putBoolean(EXTRA_COLORIZED, false);
+ return makeNotificationHeader(mParams.reset().ambient(ambient).fillTextsFrom(this));
+ }
+
+ /**
+ * Construct a RemoteViews for the final notification header only. This will not be
+ * colorized.
+ *
+ * @param p the template params to inflate this with
+ */
+ private RemoteViews makeNotificationHeader(StandardTemplateParams p) {
+ // Headers on their own are never colorized
+ p.disallowColorization();
RemoteViews header = new BuilderRemoteViews(mContext.getApplicationInfo(),
- ambient ? R.layout.notification_template_ambient_header
+ p.ambient ? R.layout.notification_template_ambient_header
: R.layout.notification_template_header);
resetNotificationHeader(header);
- bindNotificationHeader(header, ambient, null);
- if (colorized != null) {
- mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
- } else {
- mN.extras.remove(EXTRA_COLORIZED);
- }
+ bindNotificationHeader(header, p);
return header;
}
@@ -5329,24 +5351,15 @@
* @hide
*/
public RemoteViews makeLowPriorityContentView(boolean useRegularSubtext) {
- int color = mN.color;
- mN.color = COLOR_DEFAULT;
- CharSequence summary = mN.extras.getCharSequence(EXTRA_SUB_TEXT);
- if (!useRegularSubtext || TextUtils.isEmpty(summary)) {
- CharSequence newSummary = createSummaryText();
- if (!TextUtils.isEmpty(newSummary)) {
- mN.extras.putCharSequence(EXTRA_SUB_TEXT, newSummary);
- }
+ StandardTemplateParams p = mParams.reset()
+ .forceDefaultColor()
+ .ambient(false)
+ .fillTextsFrom(this);
+ if (!useRegularSubtext || TextUtils.isEmpty(mParams.summaryText)) {
+ p.summaryText(createSummaryText());
}
-
- RemoteViews header = makeNotificationHeader(false /* ambient */);
+ RemoteViews header = makeNotificationHeader(p);
header.setBoolean(R.id.notification_header, "setAcceptAllTouches", true);
- if (summary != null) {
- mN.extras.putCharSequence(EXTRA_SUB_TEXT, summary);
- } else {
- mN.extras.remove(EXTRA_SUB_TEXT);
- }
- mN.color = color;
return header;
}
@@ -5375,7 +5388,7 @@
}
private RemoteViews generateActionButton(Action action, boolean emphazisedMode,
- boolean ambient) {
+ StandardTemplateParams p) {
final boolean tombstone = (action.actionIntent == null);
RemoteViews button = new BuilderRemoteViews(mContext.getApplicationInfo(),
emphazisedMode ? getEmphasizedActionLayoutResource()
@@ -5392,7 +5405,7 @@
// change the background bgColor
CharSequence title = action.title;
ColorStateList[] outResultColor = null;
- int background = resolveBackgroundColor();
+ int background = resolveBackgroundColor(p);
if (isLegacy()) {
title = ContrastColorUtil.clearColorSpans(title);
} else {
@@ -5400,7 +5413,7 @@
title = ensureColorSpanContrast(title, background, outResultColor);
}
button.setTextViewText(R.id.action0, processTextSpans(title));
- setTextViewColorPrimary(button, R.id.action0);
+ setTextViewColorPrimary(button, R.id.action0, p);
int rippleColor;
boolean hasColorOverride = outResultColor != null && outResultColor[0] != null;
if (hasColorOverride) {
@@ -5411,11 +5424,12 @@
background, mInNightMode);
button.setTextColor(R.id.action0, textColor);
rippleColor = textColor;
- } else if (mN.color != COLOR_DEFAULT && !isColorized() && mTintActionButtons) {
- rippleColor = resolveContrastColor();
+ } else if (getRawColor(p) != COLOR_DEFAULT && !isColorized(p)
+ && mTintActionButtons) {
+ rippleColor = resolveContrastColor(p);
button.setTextColor(R.id.action0, rippleColor);
} else {
- rippleColor = getPrimaryTextColor();
+ rippleColor = getPrimaryTextColor(p);
}
// We only want about 20% alpha for the ripple
rippleColor = (rippleColor & 0x00ffffff) | 0x33000000;
@@ -5427,13 +5441,15 @@
} else {
button.setTextViewText(R.id.action0, processTextSpans(
processLegacyText(action.title)));
- if (isColorized() && !ambient) {
- setTextViewColorPrimary(button, R.id.action0);
- } else if (mN.color != COLOR_DEFAULT && mTintActionButtons) {
+ if (isColorized(p)) {
+ setTextViewColorPrimary(button, R.id.action0, p);
+ } else if (getRawColor(p) != COLOR_DEFAULT && mTintActionButtons) {
button.setTextColor(R.id.action0,
- ambient ? resolveAmbientColor() : resolveContrastColor());
+ p.ambient ? resolveAmbientColor(p) : resolveContrastColor(p));
}
}
+ button.setIntTag(R.id.action0, R.id.notification_action_index_tag,
+ mActions.indexOf(action));
return button;
}
@@ -5539,15 +5555,15 @@
* Apply any necessariy colors to the small icon
*/
private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
- boolean ambient) {
+ StandardTemplateParams p) {
boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
int color;
- if (ambient) {
- color = resolveAmbientColor();
- } else if (isColorized()) {
- color = getPrimaryTextColor();
+ if (p.ambient) {
+ color = resolveAmbientColor(p);
+ } else if (isColorized(p)) {
+ color = getPrimaryTextColor(p);
} else {
- color = resolveContrastColor();
+ color = resolveContrastColor(p);
}
if (colorable) {
contentView.setDrawableTint(R.id.icon, false, color,
@@ -5563,11 +5579,12 @@
* if it's grayscale).
*/
// TODO: also check bounds, transparency, that sort of thing.
- private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) {
+ private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView,
+ StandardTemplateParams p) {
if (largeIcon != null && isLegacy()
&& getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
// resolve color will fall back to the default when legacy
- contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(),
+ contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(p),
PorterDuff.Mode.SRC_ATOP);
}
}
@@ -5578,29 +5595,43 @@
}
}
- int resolveContrastColor() {
- if (mCachedContrastColorIsFor == mN.color && mCachedContrastColor != COLOR_INVALID) {
+ int resolveContrastColor(StandardTemplateParams p) {
+ int rawColor = getRawColor(p);
+ if (mCachedContrastColorIsFor == rawColor && mCachedContrastColor != COLOR_INVALID) {
return mCachedContrastColor;
}
int color;
int background = mContext.getColor(
com.android.internal.R.color.notification_material_background_color);
- if (mN.color == COLOR_DEFAULT) {
- ensureColors();
+ if (rawColor == COLOR_DEFAULT) {
+ ensureColors(p);
color = ContrastColorUtil.resolveDefaultColor(mContext, background, mInNightMode);
} else {
- color = ContrastColorUtil.resolveContrastColor(mContext, mN.color,
+ color = ContrastColorUtil.resolveContrastColor(mContext, rawColor,
background, mInNightMode);
}
if (Color.alpha(color) < 255) {
// alpha doesn't go well for color filters, so let's blend it manually
color = ContrastColorUtil.compositeColors(color, background);
}
- mCachedContrastColorIsFor = mN.color;
+ mCachedContrastColorIsFor = rawColor;
return mCachedContrastColor = color;
}
+ /**
+ * Return the raw color of this Notification, which doesn't necessarily satisfy contrast.
+ *
+ * @see #resolveContrastColor(StandardTemplateParams) for the contrasted color
+ * @param p the template params to inflate this with
+ */
+ private int getRawColor(StandardTemplateParams p) {
+ if (p.forceDefaultColor) {
+ return COLOR_DEFAULT;
+ }
+ return mN.color;
+ }
+
int resolveNeutralColor() {
if (mNeutralColor != COLOR_INVALID) {
return mNeutralColor;
@@ -5616,13 +5647,14 @@
return mNeutralColor;
}
- int resolveAmbientColor() {
- if (mCachedAmbientColorIsFor == mN.color && mCachedAmbientColorIsFor != COLOR_INVALID) {
+ int resolveAmbientColor(StandardTemplateParams p) {
+ int rawColor = getRawColor(p);
+ if (mCachedAmbientColorIsFor == rawColor && mCachedAmbientColorIsFor != COLOR_INVALID) {
return mCachedAmbientColor;
}
- final int contrasted = ContrastColorUtil.resolveAmbientColor(mContext, mN.color);
+ final int contrasted = ContrastColorUtil.resolveAmbientColor(mContext, rawColor);
- mCachedAmbientColorIsFor = mN.color;
+ mCachedAmbientColorIsFor = rawColor;
return mCachedAmbientColor = contrasted;
}
@@ -5854,9 +5886,9 @@
return R.layout.notification_material_action_tombstone;
}
- private int getBackgroundColor() {
- if (isColorized()) {
- return mBackgroundColor != COLOR_INVALID ? mBackgroundColor : mN.color;
+ private int getBackgroundColor(StandardTemplateParams p) {
+ if (isColorized(p)) {
+ return mBackgroundColor != COLOR_INVALID ? mBackgroundColor : getRawColor(p);
} else {
return COLOR_DEFAULT;
}
@@ -5864,10 +5896,11 @@
/**
* Gets a neutral color that can be used for icons or similar that should not stand out.
+ * @param p the template params to inflate this with
*/
- private int getNeutralColor() {
- if (isColorized()) {
- return getSecondaryTextColor();
+ private int getNeutralColor(StandardTemplateParams p) {
+ if (isColorized(p)) {
+ return getSecondaryTextColor(p);
} else {
return resolveNeutralColor();
}
@@ -5875,9 +5908,10 @@
/**
* Same as getBackgroundColor but also resolved the default color to the background.
+ * @param p the template params to inflate this with
*/
- private int resolveBackgroundColor() {
- int backgroundColor = getBackgroundColor();
+ private int resolveBackgroundColor(StandardTemplateParams p) {
+ int backgroundColor = getBackgroundColor(p);
if (backgroundColor == COLOR_DEFAULT) {
backgroundColor = mContext.getColor(
com.android.internal.R.color.notification_material_background_color);
@@ -5885,10 +5919,6 @@
return backgroundColor;
}
- private boolean isColorized() {
- return mN.isColorized();
- }
-
private boolean shouldTintActionButtons() {
return mTintActionButtons;
}
@@ -5914,7 +5944,7 @@
mBackgroundColor = backgroundColor;
mForegroundColor = foregroundColor;
mTextColorsAreForBackground = COLOR_INVALID;
- ensureColors();
+ ensureColors(mParams.reset().fillTextsFrom(this));
}
/**
@@ -6182,30 +6212,30 @@
}
protected RemoteViews getStandardView(int layoutId) {
- return getStandardView(layoutId, null);
+ StandardTemplateParams p = mBuilder.mParams.reset().fillTextsFrom(mBuilder);
+ return getStandardView(layoutId, p, null);
}
+
/**
* Get the standard view for this style.
*
- * @param layoutId The layout id to use
+ * @param layoutId The layout id to use.
+ * @param p the params for this inflation.
* @param result The result where template bind information is saved.
* @return A remoteView for this style.
* @hide
*/
- protected RemoteViews getStandardView(int layoutId, TemplateBindResult result) {
+ protected RemoteViews getStandardView(int layoutId, StandardTemplateParams p,
+ TemplateBindResult result) {
checkBuilder();
- // Nasty.
- CharSequence oldBuilderContentTitle =
- mBuilder.getAllExtras().getCharSequence(EXTRA_TITLE);
if (mBigContentTitle != null) {
- mBuilder.setContentTitle(mBigContentTitle);
+ p.title = mBigContentTitle;
}
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId, result);
-
- mBuilder.getAllExtras().putCharSequence(EXTRA_TITLE, oldBuilderContentTitle);
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId, p,
+ result);
if (mBigContentTitle != null && mBigContentTitle.equals("")) {
contentView.setViewVisibility(R.id.line1, View.GONE);
@@ -6500,12 +6530,13 @@
mBuilder.mN.largeIcon = null;
}
+ StandardTemplateParams p = mBuilder.mParams.reset().fillTextsFrom(mBuilder);
RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource(),
- null /* result */);
+ p, null /* result */);
if (mSummaryTextSet) {
contentView.setTextViewText(R.id.text, mBuilder.processTextSpans(
mBuilder.processLegacyText(mSummaryText)));
- mBuilder.setTextViewColorSecondary(contentView, R.id.text);
+ mBuilder.setTextViewColorSecondary(contentView, R.id.text, p);
contentView.setViewVisibility(R.id.text, View.VISIBLE);
}
mBuilder.setContentMinHeight(contentView, mBuilder.mN.hasLargeIcon());
@@ -6698,24 +6729,24 @@
* @hide
*/
public RemoteViews makeBigContentView() {
-
- // Nasty
- CharSequence text = mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT);
- mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
-
+ StandardTemplateParams p = mBuilder.mParams.reset().fillTextsFrom(mBuilder).text(null);
TemplateBindResult result = new TemplateBindResult();
- RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource(), result);
+ RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource(), p,
+ result);
contentView.setInt(R.id.big_text, "setImageEndMargin", result.getIconMarginEnd());
- mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, text);
-
CharSequence bigTextText = mBuilder.processLegacyText(mBigText);
if (TextUtils.isEmpty(bigTextText)) {
// In case the bigtext is null / empty fall back to the normal text to avoid a weird
// experience
- bigTextText = mBuilder.processLegacyText(text);
+ bigTextText = mBuilder.processLegacyText(
+ mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT));
}
- applyBigTextContentView(mBuilder, contentView, bigTextText);
+ contentView.setTextViewText(R.id.big_text, mBuilder.processTextSpans(bigTextText));
+ mBuilder.setTextViewColorSecondary(contentView, R.id.big_text, p);
+ contentView.setViewVisibility(R.id.big_text,
+ TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
+ contentView.setBoolean(R.id.big_text, "setHasImage", mBuilder.mN.hasLargeIcon());
return contentView;
}
@@ -6733,14 +6764,6 @@
return !Objects.equals(String.valueOf(getBigText()), String.valueOf(newS.getBigText()));
}
- static void applyBigTextContentView(Builder builder,
- RemoteViews contentView, CharSequence bigTextText) {
- contentView.setTextViewText(R.id.big_text, builder.processTextSpans(bigTextText));
- builder.setTextViewColorSecondary(contentView, R.id.big_text);
- contentView.setViewVisibility(R.id.big_text,
- TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
- contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.hasLargeIcon());
- }
}
/**
@@ -7224,24 +7247,26 @@
isOneToOne = !isGroupConversation();
}
TemplateBindResult bindResult = new TemplateBindResult();
+ StandardTemplateParams p = mBuilder.mParams.reset().hasProgress(false).title(
+ conversationTitle).text(null)
+ .hideLargeIcon(hideRightIcons || isOneToOne)
+ .hideReplyIcon(hideRightIcons)
+ .headerTextSecondary(conversationTitle);
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
- mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
- .hideLargeIcon(hideRightIcons || isOneToOne)
- .hideReplyIcon(hideRightIcons)
- .headerTextSecondary(conversationTitle),
+ p,
bindResult);
addExtras(mBuilder.mN.extras);
// also update the end margin if there is an image
contentView.setViewLayoutMarginEnd(R.id.notification_messaging,
bindResult.getIconMarginEnd());
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
- mBuilder.isColorized() ? mBuilder.getPrimaryTextColor()
- : mBuilder.resolveContrastColor());
+ mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p)
+ : mBuilder.resolveContrastColor(p));
contentView.setInt(R.id.status_bar_latest_event_content, "setSenderTextColor",
- mBuilder.getPrimaryTextColor());
+ mBuilder.getPrimaryTextColor(p));
contentView.setInt(R.id.status_bar_latest_event_content, "setMessageTextColor",
- mBuilder.getSecondaryTextColor());
+ mBuilder.getSecondaryTextColor(p));
contentView.setBoolean(R.id.status_bar_latest_event_content, "setDisplayImagesAtEnd",
displayImagesAtEnd);
contentView.setIcon(R.id.status_bar_latest_event_content, "setAvatarReplacement",
@@ -7705,15 +7730,9 @@
* @hide
*/
public RemoteViews makeBigContentView() {
- // Remove the content text so it disappears unless you have a summary
- // Nasty
- CharSequence oldBuilderContentText = mBuilder.mN.extras.getCharSequence(EXTRA_TEXT);
- mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, null);
-
+ StandardTemplateParams p = mBuilder.mParams.reset().fillTextsFrom(mBuilder).text(null);
TemplateBindResult result = new TemplateBindResult();
- RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource(), result);
-
- mBuilder.getAllExtras().putCharSequence(EXTRA_TEXT, oldBuilderContentText);
+ RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource(), p, result);
int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3,
R.id.inbox_text4, R.id.inbox_text5, R.id.inbox_text6};
@@ -7760,7 +7779,7 @@
contentView.setViewVisibility(rowIds[i], View.VISIBLE);
contentView.setTextViewText(rowIds[i],
mBuilder.processTextSpans(mBuilder.processLegacyText(str)));
- mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
+ mBuilder.setTextViewColorSecondary(contentView, rowIds[i], p);
contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
handleInboxImageMargin(contentView, rowIds[i], first,
result.getIconMarginEnd());
@@ -7997,7 +8016,7 @@
}
private void bindMediaActionButton(RemoteViews container, @IdRes int buttonId,
- Action action, int color) {
+ Action action, StandardTemplateParams p) {
final boolean tombstone = (action.actionIntent == null);
container.setViewVisibility(buttonId, View.VISIBLE);
container.setImageViewIcon(buttonId, action.getIcon());
@@ -8008,8 +8027,8 @@
Configuration currentConfig = resources.getConfiguration();
boolean inNightMode = (currentConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
- int tintColor = mBuilder.shouldTintActionButtons() || mBuilder.isColorized()
- ? color
+ int tintColor = mBuilder.shouldTintActionButtons() || mBuilder.isColorized(p)
+ ? getActionColor(p)
: ContrastColorUtil.resolveColor(mBuilder.mContext,
Notification.COLOR_DEFAULT, inNightMode);
@@ -8031,8 +8050,10 @@
}
private RemoteViews makeMediaContentView() {
+ StandardTemplateParams p = mBuilder.mParams.reset().hasProgress(false).fillTextsFrom(
+ mBuilder);
RemoteViews view = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_media, false, /* hasProgress */
+ R.layout.notification_template_material_media, p,
null /* result */);
final int numActions = mBuilder.mActions.size();
@@ -8047,7 +8068,7 @@
for (int i = 0; i < MAX_MEDIA_BUTTONS_IN_COMPACT; i++) {
if (i < numActionsToShow) {
final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
- bindMediaActionButton(view, MEDIA_BUTTON_IDS[i], action, getActionColor());
+ bindMediaActionButton(view, MEDIA_BUTTON_IDS[i], action, p);
} else {
view.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
}
@@ -8062,9 +8083,9 @@
return view;
}
- private int getActionColor() {
- return mBuilder.isColorized() ? mBuilder.getPrimaryTextColor()
- : mBuilder.resolveContrastColor();
+ private int getActionColor(StandardTemplateParams p) {
+ return mBuilder.isColorized(p) ? mBuilder.getPrimaryTextColor(p)
+ : mBuilder.resolveContrastColor(p);
}
private RemoteViews makeMediaBigContentView() {
@@ -8076,13 +8097,14 @@
if (!mBuilder.mN.hasLargeIcon() && actionCount <= actionsInCompact) {
return null;
}
+ StandardTemplateParams p = mBuilder.mParams.reset().hasProgress(false).fillTextsFrom(
+ mBuilder);
RemoteViews big = mBuilder.applyStandardTemplate(
- R.layout.notification_template_material_big_media, false, null /* result */);
+ R.layout.notification_template_material_big_media, p , null /* result */);
for (int i = 0; i < MAX_MEDIA_BUTTONS; i++) {
if (i < actionCount) {
- bindMediaActionButton(big, MEDIA_BUTTON_IDS[i], mBuilder.mActions.get(i),
- getActionColor());
+ bindMediaActionButton(big, MEDIA_BUTTON_IDS[i], mBuilder.mActions.get(i), p);
} else {
big.setViewVisibility(MEDIA_BUTTON_IDS[i], View.GONE);
}
@@ -8338,7 +8360,7 @@
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
customContent = customContent.clone();
- customContent.overrideTextColors(mBuilder.getPrimaryTextColor());
+ customContent.overrideTextColors(mBuilder.getPrimaryTextColor(mBuilder.mParams));
remoteViews.removeAllViews(id);
remoteViews.addView(id, customContent);
remoteViews.setReapplyDisallowed();
@@ -9881,17 +9903,23 @@
CharSequence title;
CharSequence text;
CharSequence headerTextSecondary;
+ CharSequence summaryText;
int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
boolean hideLargeIcon;
boolean hideReplyIcon;
+ boolean allowColorization = true;
+ boolean forceDefaultColor = false;
final StandardTemplateParams reset() {
hasProgress = true;
ambient = false;
title = null;
text = null;
+ summaryText = null;
headerTextSecondary = null;
maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
+ allowColorization = true;
+ forceDefaultColor = false;
return this;
}
@@ -9910,6 +9938,11 @@
return this;
}
+ final StandardTemplateParams summaryText(CharSequence text) {
+ this.summaryText = text;
+ return this;
+ }
+
final StandardTemplateParams headerTextSecondary(CharSequence text) {
this.headerTextSecondary = text;
return this;
@@ -9925,6 +9958,16 @@
return this;
}
+ final StandardTemplateParams disallowColorization() {
+ this.allowColorization = false;
+ return this;
+ }
+
+ final StandardTemplateParams forceDefaultColor() {
+ this.forceDefaultColor = true;
+ return this;
+ }
+
final StandardTemplateParams ambient(boolean ambient) {
Preconditions.checkState(title == null && text == null, "must set ambient before text");
this.ambient = ambient;
@@ -9941,6 +9984,7 @@
text = extras.getCharSequence(EXTRA_TEXT);
}
this.text = b.processLegacyText(text, ambient);
+ this.summaryText = extras.getCharSequence(EXTRA_SUB_TEXT);
return this;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 00c1863..98d2a40 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9992,4 +9992,111 @@
throw re.rethrowFromSystemServer();
}
}
+
+ /**
+ * Whitelists a package that is allowed to access cross profile calendar APIs.
+ *
+ * <p>Called by a profile owner of a managed profile.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName name of the package to be whitelisted.
+ * @throws SecurityException if {@code admin} is not a profile owner.
+ *
+ * @see #removeCrossProfileCalendarPackage(ComponentName, String)
+ * @see #getCrossProfileCalendarPackages(ComponentName)
+ */
+ public void addCrossProfileCalendarPackage(@NonNull ComponentName admin,
+ @NonNull String packageName) {
+ throwIfParentInstance("addCrossProfileCalendarPackage");
+ if (mService != null) {
+ try {
+ mService.addCrossProfileCalendarPackage(admin, packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Removes a package that was allowed to access cross profile calendar APIs
+ * from the whitelist.
+ *
+ * <p>Called by a profile owner of a managed profile.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName name of the package to be removed from the whitelist.
+ * @return {@code true} if the package is successfully removed from the whitelist,
+ * {@code false} otherwise.
+ * @throws SecurityException if {@code admin} is not a profile owner.
+ *
+ * @see #addCrossProfileCalendarPackage(ComponentName, String)
+ * @see #getCrossProfileCalendarPackages(ComponentName)
+ */
+ public boolean removeCrossProfileCalendarPackage(@NonNull ComponentName admin,
+ @NonNull String packageName) {
+ throwIfParentInstance("removeCrossProfileCalendarPackage");
+ if (mService != null) {
+ try {
+ return mService.removeCrossProfileCalendarPackage(admin, packageName);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets a set of package names that are whitelisted to access cross profile calendar APIs.
+ *
+ * <p>Called by a profile owner of a managed profile.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @return the set of names of packages that were previously whitelisted via
+ * {@link #addCrossProfileCalendarPackage(ComponentName, String)}, or an
+ * empty set if none have been whitelisted.
+ * @throws SecurityException if {@code admin} is not a profile owner.
+ *
+ * @see #addCrossProfileCalendarPackage(ComponentName, String)
+ * @see #removeCrossProfileCalendarPackage(ComponentName, String)
+ */
+ public @NonNull Set<String> getCrossProfileCalendarPackages(@NonNull ComponentName admin) {
+ throwIfParentInstance("getCrossProfileCalendarPackages");
+ if (mService != null) {
+ try {
+ return new ArraySet<>(mService.getCrossProfileCalendarPackages(admin));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ /**
+ * Returns if a package is whitelisted to access cross profile calendar APIs.
+ *
+ * <p>To query for a specific user, use
+ * {@link Context#createPackageContextAsUser(String, int, UserHandle)} to create a context for
+ * that user, and get a {@link DevicePolicyManager} from this context.
+ *
+ * @param packageName the name of the package
+ * @return {@code true} if the package is whitelisted to access cross profile calendar APIs.
+ * {@code false} otherwise.
+ *
+ * @see #addCrossProfileCalendarPackage(ComponentName, String)
+ * @see #removeCrossProfileCalendarPackage(ComponentName, String)
+ * @see #getCrossProfileCalendarPackages(ComponentName)
+ * @hide
+ */
+ public @NonNull boolean isPackageAllowedToAccessCalendar(@NonNull String packageName) {
+ throwIfParentInstance("isPackageAllowedToAccessCalendar");
+ if (mService != null) {
+ try {
+ return mService.isPackageAllowedToAccessCalendarForUser(packageName,
+ mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 60f79d6..297676d 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -422,4 +422,9 @@
void grantDeviceIdsAccessToProfileOwner(in ComponentName who, int userId);
void installUpdateFromFile(in ComponentName admin, in ParcelFileDescriptor updateFileDescriptor, in StartInstallingUpdateCallback listener);
+
+ void addCrossProfileCalendarPackage(in ComponentName admin, String packageName);
+ boolean removeCrossProfileCalendarPackage(in ComponentName admin, String packageName);
+ List<String> getCrossProfileCalendarPackages(in ComponentName admin);
+ boolean isPackageAllowedToAccessCalendarForUser(String packageName, int userHandle);
}
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 7988008..2174255 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -116,6 +116,9 @@
*/
@Nullable
public byte[] getManufacturerSpecificData(int manufacturerId) {
+ if (mManufacturerSpecificData == null) {
+ return null;
+ }
return mManufacturerSpecificData.get(manufacturerId);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index e7f0053..6fd5061 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4116,6 +4116,18 @@
*/
public static final String ACTION_DOCK_ACTIVE = "android.intent.action.DOCK_ACTIVE";
+ /**
+ * Broadcast Action: Indicates that a new device customization has been
+ * downloaded and applied (packages installed, runtime resource overlays
+ * enabled, xml files copied, ...), and that it is time for components that
+ * need to for example clear their caches to do so now.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_DEVICE_CUSTOMIZATION_READY =
+ "android.intent.action.DEVICE_CUSTOMIZATION_READY";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d0eff2e..dbea821 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -676,4 +676,6 @@
String getSystemTextClassifierPackageName();
boolean isPackageStateProtected(String packageName, int userId);
+
+ void sendDeviceCustomizationReadyBroadcast();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a4b724b..6421dc5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -6409,4 +6409,18 @@
"isPackageStateProtected not implemented in subclass");
}
+ /**
+ * Notify to the rest of the system that a new device configuration has
+ * been prepared and that it is time to refresh caches.
+ *
+ * @see android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY
+ *
+ * @hide
+ */
+ @SystemApi
+ public void sendDeviceCustomizationReadyBroadcast() {
+ throw new UnsupportedOperationException(
+ "sendDeviceCustomizationReadyBroadcast not implemented in subclass");
+ }
+
}
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 9db1f92..9d61f02 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -24,7 +24,7 @@
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
-import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
/**
* Display manager local system service interface.
@@ -126,7 +126,7 @@
* Called by the window manager to perform traversals while holding a
* surface flinger transaction.
*/
- public abstract void performTraversal(SurfaceControl.Transaction t);
+ public abstract void performTraversal(Transaction t);
/**
* Tells the display manager about properties of the display that depend on the windows on it.
@@ -383,6 +383,6 @@
* update the position of its surfaces as part of the same transaction.
*/
public interface DisplayTransactionListener {
- void onDisplayTransaction();
+ void onDisplayTransaction(Transaction t);
}
}
diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java
index 539c494..d1190ab 100644
--- a/core/java/android/hardware/location/ContextHubIntentEvent.java
+++ b/core/java/android/hardware/location/ContextHubIntentEvent.java
@@ -17,6 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Intent;
@@ -30,6 +31,7 @@
*
* @hide
*/
+@SystemApi
public class ContextHubIntentEvent {
@ContextHubManager.Event private final int mEventType;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 88fb3de..7639302 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -56,38 +56,28 @@
/**
* An extra of type {@link ContextHubInfo} describing the source of the event.
- *
- * @hide
*/
public static final String EXTRA_CONTEXT_HUB_INFO =
"android.hardware.location.extra.CONTEXT_HUB_INFO";
/**
* An extra of type {@link ContextHubManager.Event} describing the event type.
- *
- * @hide
*/
public static final String EXTRA_EVENT_TYPE = "android.hardware.location.extra.EVENT_TYPE";
/**
* An extra of type long describing the ID of the nanoapp an event is for.
- *
- * @hide
*/
public static final String EXTRA_NANOAPP_ID = "android.hardware.location.extra.NANOAPP_ID";
/**
* An extra of type int describing the nanoapp-specific abort code.
- *
- * @hide
*/
public static final String EXTRA_NANOAPP_ABORT_CODE =
"android.hardware.location.extra.NANOAPP_ABORT_CODE";
/**
* An extra of type {@link NanoAppMessage} describing contents of a message from a nanoapp.
- *
- * @hide
*/
public static final String EXTRA_MESSAGE = "android.hardware.location.extra.MESSAGE";
@@ -109,56 +99,41 @@
/**
* An event describing that a nanoapp has been loaded. Contains the EXTRA_NANOAPP_ID extra.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_LOADED = 0;
/**
* An event describing that a nanoapp has been unloaded. Contains the EXTRA_NANOAPP_ID extra.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_UNLOADED = 1;
/**
* An event describing that a nanoapp has been enabled. Contains the EXTRA_NANOAPP_ID extra.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_ENABLED = 2;
/**
* An event describing that a nanoapp has been disabled. Contains the EXTRA_NANOAPP_ID extra.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_DISABLED = 3;
/**
* An event describing that a nanoapp has aborted. Contains the EXTRA_NANOAPP_ID and
* EXTRA_NANOAPP_ABORT_CODE extras.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_ABORTED = 4;
/**
* An event containing a message sent from a nanoapp. Contains the EXTRA_NANOAPP_ID and
* EXTRA_NANOAPP_MESSAGE extras.
- *
- * @hide
*/
public static final int EVENT_NANOAPP_MESSAGE = 5;
/**
* An event describing that the Context Hub has reset.
- *
- * @hide
*/
public static final int EVENT_HUB_RESET = 6;
-
private final Looper mMainLooper;
private final IContextHubService mService;
private Callback mCallback;
@@ -797,14 +772,14 @@
* Creates a ContextHubClient that will receive notifications based on Intent events.
*
* This method should be used instead of {@link #createClient(ContextHubInfo,
- * ContextHubClientCallback)} and the equivalent API if the caller wants to preserve the
- * messaging endpoint of a ContextHubClient, even after a process exits. If the PendingIntent
- * with the provided nanoapp has already been registered at the service previously, then the
- * same ContextHubClient will be regenerated without creating a new client connection at the
- * service. Note that the PendingIntent, nanoapp, and Context Hub must all match in identifying
- * a previously registered ContextHubClient. If a client is regenerated, it can be treated as
- * the same endpoint entity from a nanoapp's perspective, and can be continued to be
- * used to send messages even if the original process has exited.
+ * ContextHubClientCallback)} or {@link #createClient(ContextHubInfo, ContextHubClientCallback,
+ * Executor)} if the caller wants to preserve the messaging endpoint of a ContextHubClient, even
+ * after a process exits. If the PendingIntent with the provided nanoapp has already been
+ * registered at the service, then the same ContextHubClient will be regenerated without
+ * creating a new client connection at the service. Note that the PendingIntent, nanoapp, and
+ * Context Hub must all match in identifying a previously registered ContextHubClient.
+ * If a client is regenerated, the host endpoint identifier attached to messages sent to the
+ * nanoapp remains consistent, even if the original process has exited.
*
* If registered successfully, intents will be delivered regarding events or messages from the
* specified nanoapp from the attached Context Hub. The intent will have an extra
@@ -815,10 +790,11 @@
* each event type, along with event-specific extra fields. The client can also use
* {@link ContextHubIntentEvent.fromIntent(Intent)} to parse the Intent generated by the event.
*
- * Intent events will be delivered until it is unregistered through
- * {@link ContextHubClient.close()}. Note that the registration of this
- * ContextHubClient at the Context Hub Service will continued to be maintained until
- * {@link ContextHubClient.close()} is called.
+ * Intent events will be delivered until {@link ContextHubClient.close()} is called. Note that
+ * the registration of this ContextHubClient at the Context Hub Service will be maintained until
+ * {@link ContextHubClient.close()} is called. If {@link PendingIntent.cancel()} is called
+ * on the provided PendingIntent, then the client will be automatically unregistered by the
+ * service.
*
* @param hubInfo the hub to attach this client to
* @param pendingIntent the PendingIntent to register to the client
@@ -828,8 +804,6 @@
* @throws IllegalArgumentException if hubInfo does not represent a valid hub
* @throws IllegalStateException if there were too many registered clients at the service
* @throws NullPointerException if pendingIntent or hubInfo is null
- *
- * @hide
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1c1db68..894015f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1008,7 +1008,8 @@
* progress, does nothing. Unlike {@link #nap(long)}, this does not put device to sleep when
* dream ends.
* </p><p>
- * Requires the {@link android.Manifest.permission#WRITE_DREAM_STATE} permission.
+ * Requires the {@link android.Manifest.permission#READ_DREAM_STATE} and
+ * {@link android.Manifest.permission#WRITE_DREAM_STATE} permissions.
* </p>
*
* @param time The time when the request to nap was issued, in the
@@ -1019,7 +1020,9 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.READ_DREAM_STATE,
+ android.Manifest.permission.WRITE_DREAM_STATE })
public void dream(long time) {
Sandman.startDreamByUserRequest(mContext);
}
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 866bd9a..acb9eac 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -43,6 +43,7 @@
int mTag;
long mElapsedTimeNs;
long mWallClockTimeNs;
+ WorkSource mWorkSource = null;
public StatsLogEventWrapper(int tag, long elapsedTimeNs, long wallClockTimeNs) {
this.mTag = tag;
@@ -71,6 +72,17 @@
};
/**
+ * Set work source if any.
+ */
+ public void setWorkSource(WorkSource ws) {
+ if (ws.getWorkChains() == null || ws.getWorkChains().size() == 0) {
+ Slog.w(TAG, "Empty worksource!");
+ return;
+ }
+ mWorkSource = ws;
+ }
+
+ /**
* Write a int value.
*/
public void writeInt(int val) {
@@ -119,11 +131,6 @@
mValues.add(val ? 1 : 0);
}
- /**
- * Writes the stored fields to a byte array. Will first write a new-line character to denote
- * END_LIST before writing contents to byte array.
- */
-
public void writeToParcel(Parcel out, int flags) {
if (DEBUG) {
Slog.d(TAG,
@@ -133,6 +140,34 @@
out.writeInt(mTag);
out.writeLong(mElapsedTimeNs);
out.writeLong(mWallClockTimeNs);
+ if (mWorkSource != null) {
+ ArrayList<android.os.WorkSource.WorkChain> workChains = mWorkSource.getWorkChains();
+ // number of chains
+ out.writeInt(workChains.size());
+ for (int i = 0; i < workChains.size(); i++) {
+ android.os.WorkSource.WorkChain wc = workChains.get(i);
+ if (wc.getSize() == 0) {
+ Slog.w(TAG, "Empty work chain.");
+ out.writeInt(0);
+ continue;
+ }
+ if (wc.getUids().length != wc.getTags().length
+ || wc.getUids().length != wc.getSize()) {
+ Slog.w(TAG, "Malformated work chain.");
+ out.writeInt(0);
+ continue;
+ }
+ // number of nodes
+ out.writeInt(wc.getSize());
+ for (int j = 0; j < wc.getSize(); j++) {
+ out.writeInt(wc.getUids()[j]);
+ out.writeString(wc.getTags()[j] == null ? "" : wc.getTags()[j]);
+ }
+ }
+ } else {
+ // no chains
+ out.writeInt(0);
+ }
out.writeInt(mTypes.size());
for (int i = 0; i < mTypes.size(); i++) {
out.writeInt(mTypes.get(i));
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 291891e..e0e4fe2 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -572,6 +572,34 @@
public void setSecondaryDirectory(@Nullable String secondaryDirectory) {
this.secondaryDirectory = secondaryDirectory;
}
+
+ /**
+ * Optionally set the Uri from where the file has been downloaded. This is used
+ * for files being added to {@link Downloads} table.
+ *
+ * @see DownloadColumns#DOWNLOAD_URI
+ */
+ public void setDownloadUri(@Nullable Uri downloadUri) {
+ if (downloadUri == null) {
+ this.insertValues.remove(DownloadColumns.DOWNLOAD_URI);
+ } else {
+ this.insertValues.put(DownloadColumns.DOWNLOAD_URI, downloadUri.toString());
+ }
+ }
+
+ /**
+ * Optionally set the Uri indicating HTTP referer of the file. This is used for
+ * files being added to {@link Downloads} table.
+ *
+ * @see DownloadColumns#REFERER_URI
+ */
+ public void setRefererUri(@Nullable Uri refererUri) {
+ if (refererUri == null) {
+ this.insertValues.remove(DownloadColumns.REFERER_URI);
+ } else {
+ this.insertValues.put(DownloadColumns.REFERER_URI, refererUri.toString());
+ }
+ }
}
/**
@@ -763,7 +791,7 @@
* Type: BOOLEAN
*
* @see MediaStore#createPending(Context, PendingParams)
- * @see MediaStore#QUERY_ARG_INCLUDE_PENDING
+ * @see MediaStore#PARAM_INCLUDE_PENDING
*/
public static final String IS_PENDING = "is_pending";
@@ -927,6 +955,12 @@
* Constant for the {@link #MEDIA_TYPE} column indicating that file is a playlist file.
*/
public static final int MEDIA_TYPE_PLAYLIST = 4;
+
+ /**
+ * Column indicating if the file is part of Downloads collection.
+ * @hide
+ */
+ public static final String IS_DOWNLOAD = "is_download";
}
}
@@ -940,6 +974,80 @@
public static final Point MICRO_SIZE = new Point(96, 96);
}
+ /** Column fields for downloaded files used in {@link Downloads} table */
+ public interface DownloadColumns extends MediaColumns {
+ /**
+ * Uri indicating where the file has been downloaded from.
+ * <p>
+ * Type: TEXT
+ */
+ String DOWNLOAD_URI = "download_uri";
+
+ /**
+ * Uri indicating HTTP referer of {@link #DOWNLOAD_URI}.
+ * <p>
+ * Type: TEXT
+ */
+ String REFERER_URI = "referer_uri";
+ }
+
+ /**
+ * Container for downloaded files.
+ *
+ * <p>
+ * Querying for downloads from this table will return files contributed via
+ * {@link PendingSession} and also ones which were downloaded using
+ * {@link android.app.DownloadManager} APIs.
+ */
+ public static final class Downloads implements DownloadColumns {
+ private Downloads() {}
+
+ /**
+ * The content:// style URI for the internal storage.
+ */
+ public static final Uri INTERNAL_CONTENT_URI =
+ getContentUri("internal");
+
+ /**
+ * The content:// style URI for the "primary" external storage
+ * volume.
+ */
+ public static final Uri EXTERNAL_CONTENT_URI =
+ getContentUri("external");
+
+ /**
+ * Get the content:// style URI for the downloads table on the
+ * given volume.
+ *
+ * @param volumeName the name of the volume to get the URI for
+ * @return the URI to the image media table on the given volume
+ */
+ public static Uri getContentUri(String volumeName) {
+ return AUTHORITY_URI.buildUpon().appendPath(volumeName)
+ .appendPath("downloads").build();
+ }
+
+ /** @hide */
+ public static Uri getContentUriForPath(@NonNull String path) {
+ return getContentUri(getVolumeNameForPath(path));
+ }
+ }
+
+ private static String getVolumeNameForPath(@NonNull String path) {
+ final StorageManager sm = AppGlobals.getInitialApplication()
+ .getSystemService(StorageManager.class);
+ final StorageVolume sv = sm.getStorageVolume(new File(path));
+ if (sv != null) {
+ if (sv.isPrimary()) {
+ return VOLUME_EXTERNAL;
+ } else {
+ return sv.getUuid();
+ }
+ } else {
+ return VOLUME_INTERNAL;
+ }
+ }
+
/**
* This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended
* to be accessed elsewhere.
@@ -1671,18 +1779,7 @@
* access this path.
*/
public static @Nullable Uri getContentUriForPath(@NonNull String path) {
- final StorageManager sm = AppGlobals.getInitialApplication()
- .getSystemService(StorageManager.class);
- final StorageVolume sv = sm.getStorageVolume(new File(path));
- if (sv != null) {
- if (sv.isPrimary()) {
- return EXTERNAL_CONTENT_URI;
- } else {
- return getContentUri(sv.getUuid());
- }
- } else {
- return INTERNAL_CONTENT_URI;
- }
+ return getContentUri(getVolumeNameForPath(path));
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 848b041..d772903 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7967,6 +7967,14 @@
"managed_profile_contact_remote_search";
/**
+ * Whether parent profile can access remote calendar data in managed profile.
+ *
+ * @hide
+ */
+ public static final String CROSS_PROFILE_CALENDAR_ENABLED =
+ "cross_profile_calendar_enabled";
+
+ /**
* Whether or not the automatic storage manager is enabled and should run on the device.
*
* @hide
@@ -11035,6 +11043,16 @@
= "activity_starts_logging_enabled";
/**
+ * Feature flag to enable or disable the background activity starts.
+ * When disabled, apps aren't allowed to start activities unless they're in the foreground.
+ * Type: int (0 for false, 1 for true)
+ * Default: 1
+ * @hide
+ */
+ public static final String BACKGROUND_ACTIVITY_STARTS_ENABLED =
+ "background_activity_starts_enabled";
+
+ /**
* @hide
* @see com.android.server.appbinding.AppBindingConstants
*/
@@ -11600,7 +11618,7 @@
/**
* Whether or not show hidden launcher icon apps feature is enabled.
* Type: int (0 for false, 1 for true)
- * Default: 0
+ * Default: 1
* @hide
*/
public static final String SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED =
@@ -13753,6 +13771,15 @@
*/
public static final String LAST_ACTIVE_USER_ID = "last_active_persistent_user_id";
+
+ /**
+ * Whether we've enabled native flags health check on this device. Takes effect on
+ * reboot. The value "1" enables native flags health check; otherwise it's disabled.
+ * @hide
+ */
+ public static final String NATIVE_FLAGS_HEALTH_CHECK_ENABLED =
+ "native_flags_health_check_enabled";
+
}
/**
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index ab94f43..1ddc099e 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.content.pm.ParceledListSlice;
@@ -50,4 +51,5 @@
void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
void onNotificationDirectReply(String key);
void onSuggestedReplySent(String key, in CharSequence reply, int source);
+ void onActionClicked(String key, in Notification.Action action, int source);
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index 68da83f..c850a4e 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -19,9 +19,11 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -189,11 +191,20 @@
* Implement this to know when a suggested reply is sent.
* @param key the notification key
* @param reply the reply that is just sent
- * @param source the source of the reply, e.g. SOURCE_FROM_APP
+ * @param source the source that provided the reply, e.g. SOURCE_FROM_APP
*/
public void onSuggestedReplySent(String key, CharSequence reply, @Source int source) {}
/**
+ * Implement this to know when an action is clicked.
+ * @param key the notification key
+ * @param action the action that is just clicked
+ * @param source the source that provided the action, e.g. SOURCE_FROM_APP
+ */
+ public void onActionClicked(String key, @Nullable Notification.Action action, int source) {
+ }
+
+ /**
* Updates a notification. N.B. this won’t cause
* an existing notification to alert, but might allow a future update to
* this notification to alert.
@@ -317,6 +328,15 @@
args.argi2 = source;
mHandler.obtainMessage(MyHandler.MSG_ON_SUGGESTED_REPLY_SENT, args).sendToTarget();
}
+
+ @Override
+ public void onActionClicked(String key, Notification.Action action, int source) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = key;
+ args.arg2 = action;
+ args.argi2 = source;
+ mHandler.obtainMessage(MyHandler.MSG_ON_ACTION_CLICKED, args).sendToTarget();
+ }
}
private final class MyHandler extends Handler {
@@ -326,6 +346,7 @@
public static final int MSG_ON_NOTIFICATION_EXPANSION_CHANGED = 4;
public static final int MSG_ON_NOTIFICATION_DIRECT_REPLY_SENT = 5;
public static final int MSG_ON_SUGGESTED_REPLY_SENT = 6;
+ public static final int MSG_ON_ACTION_CLICKED = 7;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -395,6 +416,15 @@
onSuggestedReplySent(key, reply, source);
break;
}
+ case MSG_ON_ACTION_CLICKED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ String key = (String) args.arg1;
+ Notification.Action action = (Notification.Action) args.arg2;
+ int source = args.argi2;
+ args.recycle();
+ onActionClicked(key, action, source);
+ break;
+ }
}
}
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 756a7c6..1fe97b7 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1382,6 +1382,11 @@
}
@Override
+ public void onActionClicked(String key, Notification.Action action, int source) {
+ // no-op in the listener
+ }
+
+ @Override
public void onNotificationChannelModification(String pkgName, UserHandle user,
NotificationChannel channel,
@ChannelOrGroupModificationTypes int modificationType) {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f6bb762..45d53f3 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -56,6 +56,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -184,6 +185,7 @@
final DisplayCutout.ParcelableWrapper mDisplayCutout =
new DisplayCutout.ParcelableWrapper();
DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT;
+ final InsetsState mInsetsState = new InsetsState();
final MergedConfiguration mMergedConfiguration = new MergedConfiguration();
final WindowManager.LayoutParams mLayout
@@ -803,9 +805,11 @@
mLayout.windowAnimations =
com.android.internal.R.style.Animation_Wallpaper;
mInputChannel = new InputChannel();
+
if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE,
mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets,
- mOutsets, mDisplayCutout, mInputChannel) < 0) {
+ mOutsets, mDisplayCutout, mInputChannel,
+ mInsetsState) < 0) {
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
@@ -831,7 +835,8 @@
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, -1, mWinFrame, mOverscanInsets, mContentInsets,
mVisibleInsets, mStableInsets, mOutsets, mBackdropFrame,
- mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface);
+ mDisplayCutout, mMergedConfiguration, mSurfaceHolder.mSurface,
+ mInsetsState);
if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 562ae7a..bab4bc3 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -18,8 +18,8 @@
import android.util.TimeFormatException;
+import libcore.timezone.ZoneInfoDB;
import libcore.util.ZoneInfo;
-import libcore.util.ZoneInfoDB;
import java.io.IOException;
import java.util.Locale;
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index c822832..de182da 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -32,6 +32,7 @@
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;
@@ -109,7 +110,7 @@
}
};
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private static final Property<View, PointF> BOTTOM_RIGHT_ONLY_PROPERTY =
new Property<View, PointF>(PointF.class, "bottomRight") {
@Override
@@ -144,7 +145,7 @@
}
};
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private static final Property<View, PointF> POSITION_PROPERTY =
new Property<View, PointF>(PointF.class, "position") {
@Override
diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java
index 7e499f2..b1fc17a 100644
--- a/core/java/android/transition/Scene.java
+++ b/core/java/android/transition/Scene.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.os.Build;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
@@ -38,9 +39,9 @@
private int mLayoutId = -1;
private ViewGroup mSceneRoot;
private View mLayout; // alternative to layoutId
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
Runnable mEnterAction;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
Runnable mExitAction;
/**
@@ -200,7 +201,7 @@
*
* @param sceneRoot The view on which the current scene is being set
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
static void setCurrentScene(@NonNull View sceneRoot, @Nullable Scene scene) {
sceneRoot.setTagInternal(com.android.internal.R.id.current_scene, scene);
}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 21c4252..57d55bf 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -24,7 +24,7 @@
import libcore.timezone.CountryTimeZones;
import libcore.timezone.CountryTimeZones.TimeZoneMapping;
import libcore.timezone.TimeZoneFinder;
-import libcore.util.ZoneInfoDB;
+import libcore.timezone.ZoneInfoDB;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 4b8b7f3..af41b69 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -24,6 +24,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.DisplayCutout;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
import android.util.MergedConfiguration;
@@ -53,6 +54,12 @@
in MergedConfiguration newMergedConfiguration, in Rect backDropFrame,
boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
in DisplayCutout.ParcelableWrapper displayCutout);
+
+ /**
+ * Called when the window insets configuration has changed.
+ */
+ void insetsChanged(in InsetsState insetsState);
+
void moved(int newX, int newY);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index bedfa9f..9762586 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -28,6 +28,7 @@
import android.view.IWindowId;
import android.view.MotionEvent;
import android.view.WindowManager;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -40,10 +41,11 @@
int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outFrame,
out Rect outContentInsets, out Rect outStableInsets, out Rect outOutsets,
- out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel);
+ out DisplayCutout.ParcelableWrapper displayCutout, out InputChannel outInputChannel,
+ out InsetsState insetsState);
int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs,
in int viewVisibility, in int layerStackId, out Rect outContentInsets,
- out Rect outStableInsets);
+ out Rect outStableInsets, out InsetsState insetsState);
void remove(IWindow window);
/**
@@ -86,6 +88,7 @@
* config for window, if it is now becoming visible and the merged configuration has changed
* since it was last displayed.
* @param outSurface Object in which is placed the new display surface.
+ * @param insetsState The current insets state in the system.
*
* @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
* {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -96,7 +99,8 @@
out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets,
out Rect outOutsets, out Rect outBackdropFrame,
out DisplayCutout.ParcelableWrapper displayCutout,
- out MergedConfiguration outMergedConfiguration, out Surface outSurface);
+ out MergedConfiguration outMergedConfiguration, out Surface outSurface,
+ out InsetsState insetsState);
/*
* Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/InputApplicationHandle.java b/core/java/android/view/InputApplicationHandle.java
index dc1e505..5f6bc23 100644
--- a/core/java/android/view/InputApplicationHandle.java
+++ b/core/java/android/view/InputApplicationHandle.java
@@ -16,6 +16,8 @@
package android.view;
+import android.os.IBinder;
+
/**
* Functions as a handle for an application that can receive input.
* Enables the native input dispatcher to refer indirectly to the window manager's
@@ -28,19 +30,18 @@
@SuppressWarnings("unused")
private long ptr;
- // The window manager's application window token.
- public final Object appWindowToken;
-
// Application name.
public String name;
// Dispatching timeout.
public long dispatchingTimeoutNanos;
+ public IBinder token;
+
private native void nativeDispose();
- public InputApplicationHandle(Object appWindowToken) {
- this.appWindowToken = appWindowToken;
+ public InputApplicationHandle(IBinder token) {
+ this.token = token;
}
@Override
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index 621ee89..92e0009 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Region;
+import android.os.IBinder;
import android.view.IWindow;
import android.view.InputChannel;
@@ -37,8 +38,8 @@
// The client window.
public final IWindow clientWindow;
- // The input channel associated with the window.
- public InputChannel inputChannel;
+ // The token assosciated with the window.
+ public IBinder token;
// The window name.
public String name;
@@ -56,6 +57,8 @@
public int frameRight;
public int frameBottom;
+ public int surfaceInset;
+
// Global scaling factor applied to touch events when they are dispatched
// to the window
public float scaleFactor;
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
new file mode 100644
index 0000000..7841d04
--- /dev/null
+++ b/core/java/android/view/InsetsController.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.view;
+
+import android.graphics.Rect;
+
+import java.io.PrintWriter;
+
+/**
+ * Implements {@link WindowInsetsController} on the client.
+ */
+class InsetsController {
+
+ private final InsetsState mState = new InsetsState();
+ private final Rect mFrame = new Rect();
+
+ void onFrameChanged(Rect frame) {
+ mFrame.set(frame);
+ }
+
+ public InsetsState getState() {
+ return mState;
+ }
+
+ public void setState(InsetsState state) {
+ mState.set(state);
+ }
+
+ /**
+ * @see InsetsState#calculateInsets
+ */
+ WindowInsets calculateInsets(boolean isScreenRound,
+ boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+ return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout);
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix); pw.println("InsetsController:");
+ mState.dump(prefix + " ", pw);
+ }
+}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
new file mode 100644
index 0000000..0cb8ad7
--- /dev/null
+++ b/core/java/android/view/InsetsSource.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.view;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InsetsState.InternalInsetType;
+
+import java.io.PrintWriter;
+
+/**
+ * Represents the state of a single window generating insets for clients.
+ * @hide
+ */
+public class InsetsSource implements Parcelable {
+
+ private final @InternalInsetType int mType;
+
+ /** Frame of the source in screen coordinate space */
+ private final Rect mFrame;
+ private boolean mVisible;
+
+ private final Rect mTmpFrame = new Rect();
+
+ public InsetsSource(@InternalInsetType int type) {
+ mType = type;
+ mFrame = new Rect();
+ }
+
+ public InsetsSource(InsetsSource other) {
+ mType = other.mType;
+ mFrame = new Rect(other.mFrame);
+ mVisible = other.mVisible;
+ }
+
+ public void setFrame(Rect frame) {
+ mFrame.set(frame);
+ }
+
+ public void setVisible(boolean visible) {
+ mVisible = visible;
+ }
+
+ public @InternalInsetType int getType() {
+ return mType;
+ }
+
+ public Rect getFrame() {
+ return mFrame;
+ }
+
+ /**
+ * Calculates the insets this source will cause to a client window.
+ *
+ * @param relativeFrame The frame to calculate the insets relative to.
+ * @param ignoreVisibility If true, always reports back insets even if source isn't visible.
+ * @return The resulting insets.
+ */
+ public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) {
+ if (!ignoreVisibility && !mVisible) {
+ return Insets.NONE;
+ }
+ if (!mTmpFrame.setIntersect(mFrame, relativeFrame)) {
+ return Insets.NONE;
+ }
+
+ // Intersecting at top/bottom
+ if (mTmpFrame.width() == relativeFrame.width()) {
+ if (mTmpFrame.top == relativeFrame.top) {
+ return Insets.of(0, mTmpFrame.height(), 0, 0);
+ } else {
+ return Insets.of(0, 0, 0, mTmpFrame.height());
+ }
+ }
+ // Intersecting at left/right
+ else if (mTmpFrame.height() == relativeFrame.height()) {
+ if (mTmpFrame.left == relativeFrame.left) {
+ return Insets.of(mTmpFrame.width(), 0, 0, 0);
+ } else {
+ return Insets.of(0, 0, mTmpFrame.width(), 0);
+ }
+ } else {
+ return Insets.NONE;
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix);
+ pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType));
+ pw.print(" frame="); pw.print(mFrame.toShortString());
+ pw.print(" visible="); pw.print(mVisible);
+ pw.println();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ InsetsSource that = (InsetsSource) o;
+
+ if (mType != that.mType) return false;
+ if (mVisible != that.mVisible) return false;
+ return mFrame.equals(that.mFrame);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mType;
+ result = 31 * result + mFrame.hashCode();
+ result = 31 * result + (mVisible ? 1 : 0);
+ return result;
+ }
+
+ public InsetsSource(Parcel in) {
+ mType = in.readInt();
+ mFrame = in.readParcelable(null /* loader */);
+ mVisible = in.readBoolean();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeParcelable(mFrame, 0 /* flags*/);
+ dest.writeBoolean(mVisible);
+ }
+
+ public static final Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {
+
+ public InsetsSource createFromParcel(Parcel in) {
+ return new InsetsSource(in);
+ }
+
+ public InsetsSource[] newArray(int size) {
+ return new InsetsSource[size];
+ }
+ };
+}
diff --git a/core/java/android/view/InsetsState.aidl b/core/java/android/view/InsetsState.aidl
new file mode 100644
index 0000000..d02ddd1
--- /dev/null
+++ b/core/java/android/view/InsetsState.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 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.
+ */
+
+package android.view;
+
+parcelable InsetsState;
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
new file mode 100644
index 0000000..9895adc
--- /dev/null
+++ b/core/java/android/view/InsetsState.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.view;
+
+import android.annotation.IntDef;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Holder for state of system windows that cause window insets for all other windows in the system.
+ * @hide
+ */
+public class InsetsState implements Parcelable {
+
+ /**
+ * Internal representation of inset source types. This is different from the public API in
+ * {@link WindowInsets.Type} as one type from the public API might indicate multiple windows
+ * at the same time.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "TYPE", value = {
+ TYPE_TOP_BAR,
+ TYPE_SIDE_BAR_1,
+ TYPE_SIDE_BAR_2,
+ TYPE_SIDE_BAR_3,
+ TYPE_IME
+ })
+ public @interface InternalInsetType {}
+
+ static final int FIRST_TYPE = 0;
+
+ /** Top bar. Can be status bar or caption in freeform windowing mode. */
+ public static final int TYPE_TOP_BAR = FIRST_TYPE;
+
+ /**
+ * Up to 3 side bars that appear on left/right/bottom. On phones there is only one side bar
+ * (the navigation bar, see {@link #TYPE_NAVIGATION_BAR}), but other form factors might have
+ * multiple, like Android Auto.
+ */
+ public static final int TYPE_SIDE_BAR_1 = 1;
+ public static final int TYPE_SIDE_BAR_2 = 2;
+ public static final int TYPE_SIDE_BAR_3 = 3;
+
+ /** Input method window. */
+ public static final int TYPE_IME = 4;
+ static final int LAST_TYPE = TYPE_IME;
+
+ // Derived types
+
+ /** First side bar is navigation bar. */
+ public static final int TYPE_NAVIGATION_BAR = TYPE_SIDE_BAR_1;
+
+ /** A shelf is the same as the navigation bar. */
+ public static final int TYPE_SHELF = TYPE_NAVIGATION_BAR;
+
+ private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+
+ public InsetsState() {
+ }
+
+ /**
+ * Calculates {@link WindowInsets} based on the current source configuration.
+ *
+ * @param frame The frame to calculate the insets relative to.
+ * @return The calculated insets.
+ */
+ public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
+ boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+ Insets systemInsets = Insets.NONE;
+ Insets maxInsets = Insets.NONE;
+ final Rect relativeFrame = new Rect(frame);
+ final Rect relativeFrameMax = new Rect(frame);
+ for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
+ InsetsSource source = mSources.get(type);
+ if (source == null) {
+ continue;
+ }
+ systemInsets = processSource(source, systemInsets, relativeFrame,
+ false /* ignoreVisibility */);
+
+ // IME won't be reported in max insets as the size depends on the EditorInfo of the IME
+ // target.
+ if (source.getType() != TYPE_IME) {
+ maxInsets = processSource(source, maxInsets, relativeFrameMax,
+ true /* ignoreVisibility */);
+ }
+ }
+ return new WindowInsets(new Rect(systemInsets), null, new Rect(maxInsets), isScreenRound,
+ alwaysConsumeNavBar, cutout);
+ }
+
+ private Insets processSource(InsetsSource source, Insets insets, Rect relativeFrame,
+ boolean ignoreVisibility) {
+ Insets currentInsets = source.calculateInsets(relativeFrame, ignoreVisibility);
+ insets = Insets.add(currentInsets, insets);
+ relativeFrame.inset(insets);
+ return insets;
+ }
+
+ public InsetsSource getSource(@InternalInsetType int type) {
+ return mSources.computeIfAbsent(type, InsetsSource::new);
+ }
+
+ /**
+ * Modifies the state of this class to exclude a certain type to make it ready for dispatching
+ * to the client.
+ *
+ * @param type The {@link InternalInsetType} of the source to remove
+ */
+ public void removeSource(int type) {
+ mSources.remove(type);
+ }
+
+ public void set(InsetsState other) {
+ set(other, false /* copySources */);
+ }
+
+ public void set(InsetsState other, boolean copySources) {
+ mSources.clear();
+ if (copySources) {
+ for (int i = 0; i < other.mSources.size(); i++) {
+ InsetsSource source = other.mSources.valueAt(i);
+ mSources.put(source.getType(), new InsetsSource(source));
+ }
+ } else {
+ mSources.putAll(other.mSources);
+ }
+ }
+
+ public void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "InsetsState");
+ for (int i = mSources.size() - 1; i >= 0; i--) {
+ mSources.valueAt(i).dump(prefix + " ", pw);
+ }
+ }
+
+ static String typeToString(int type) {
+ switch (type) {
+ case TYPE_TOP_BAR:
+ return "TYPE_TOP_BAR";
+ case TYPE_SIDE_BAR_1:
+ return "TYPE_SIDE_BAR_1";
+ case TYPE_SIDE_BAR_2:
+ return "TYPE_SIDE_BAR_2";
+ case TYPE_SIDE_BAR_3:
+ return "TYPE_SIDE_BAR_3";
+ case TYPE_IME:
+ return "TYPE_IME";
+ default:
+ return "TYPE_UNKNOWN";
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+
+ InsetsState state = (InsetsState) o;
+
+ if (mSources.size() != state.mSources.size()) {
+ return false;
+ }
+ for (int i = mSources.size() - 1; i >= 0; i--) {
+ InsetsSource source = mSources.valueAt(i);
+ InsetsSource otherSource = state.mSources.get(source.getType());
+ if (otherSource == null) {
+ return false;
+ }
+ if (!otherSource.equals(source)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mSources.hashCode();
+ }
+
+ public InsetsState(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSources.size());
+ for (int i = 0; i < mSources.size(); i++) {
+ dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+ }
+ }
+
+ public static final Creator<InsetsState> CREATOR = new Creator<InsetsState>() {
+
+ public InsetsState createFromParcel(Parcel in) {
+ return new InsetsState(in);
+ }
+
+ public InsetsState[] newArray(int size) {
+ return new InsetsState[size];
+ }
+ };
+
+ public void readFromParcel(Parcel in) {
+ mSources.clear();
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ final InsetsSource source = in.readParcelable(null /* loader */);
+ mSources.put(source.getType(), source);
+ }
+ }
+}
+
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index a7a5024..46f396a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -375,9 +375,13 @@
* Construct a new {@link SurfaceControl} with the set parameters.
*/
public SurfaceControl build() {
- if (mWidth <= 0 || mHeight <= 0) {
+ if (mWidth < 0 || mHeight < 0) {
throw new IllegalArgumentException(
- "width and height must be set");
+ "width and height must be positive or unset");
+ }
+ if ((mWidth > 0 || mHeight > 0) && (isColorLayerSet() || isContainerLayerSet())) {
+ throw new IllegalArgumentException(
+ "Only buffer layers can set a valid buffer size.");
}
return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat,
mFlags, mParent, mWindowType, mOwnerUid);
@@ -399,8 +403,8 @@
* @param width The buffer width in pixels.
* @param height The buffer height in pixels.
*/
- public Builder setSize(int width, int height) {
- if (width <= 0 || height <= 0) {
+ public Builder setBufferSize(int width, int height) {
+ if (width < 0 || height < 0) {
throw new IllegalArgumentException(
"width and height must be positive");
}
@@ -533,6 +537,10 @@
return this;
}
+ private boolean isColorLayerSet() {
+ return (mFlags & FX_SURFACE_DIM) == FX_SURFACE_DIM;
+ }
+
/**
* Indicates whether a 'ContainerLayer' is to be constructed.
*
@@ -550,6 +558,10 @@
return this;
}
+ private boolean isContainerLayerSet() {
+ return (mFlags & FX_SURFACE_CONTAINER) == FX_SURFACE_CONTAINER;
+ }
+
/**
* Set 'Surface creation flags' such as {@link HIDDEN}, {@link SECURE}.
*
@@ -869,10 +881,10 @@
}
}
- public void setSize(int w, int h) {
+ public void setBufferSize(int w, int h) {
checkNotReleased();
synchronized(SurfaceControl.class) {
- sGlobalTransaction.setSize(this, w, h);
+ sGlobalTransaction.setBufferSize(this, w, h);
}
}
@@ -1427,7 +1439,7 @@
}
@UnsupportedAppUsage
- public Transaction setSize(SurfaceControl sc, int w, int h) {
+ public Transaction setBufferSize(SurfaceControl sc, int w, int h) {
sc.checkNotReleased();
mResizedSurfaces.put(sc, new Point(w, h));
nativeSetSize(mNativeObject, sc.mNativeObject, w, h);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 2b68ec0..3c4ce8f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -557,7 +557,7 @@
name,
(mSurfaceFlags & SurfaceControl.OPAQUE) != 0,
new SurfaceControl.Builder(mSurfaceSession)
- .setSize(mSurfaceWidth, mSurfaceHeight)
+ .setBufferSize(mSurfaceWidth, mSurfaceHeight)
.setFormat(mFormat)
.setFlags(mSurfaceFlags));
} else if (mSurfaceControl == null) {
@@ -595,10 +595,14 @@
mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
0.0f, 0.0f,
mScreenRect.height() / (float) mSurfaceHeight);
+ // Set a window crop when creating the surface or changing its size to
+ // crop the buffer to the surface size since the buffer producer may
+ // use SCALING_MODE_SCALE and submit a larger size than the surface
+ // size.
+ mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
}
if (sizeChanged && !creating) {
- mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
- mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
+ mSurfaceControl.setBufferSize(mSurfaceWidth, mSurfaceHeight);
}
} finally {
SurfaceControl.closeTransaction();
@@ -1133,6 +1137,8 @@
mBackgroundControl = b.setName("Background for -" + name)
.setFormat(OPAQUE)
+ // Unset the buffer size of the background color layer.
+ .setBufferSize(0, 0)
.setColorLayer(true)
.build();
mOpaque = opaque;
@@ -1158,9 +1164,9 @@
}
@Override
- public void setSize(int w, int h) {
- super.setSize(w, h);
- mBackgroundControl.setSize(w, h);
+ public void setBufferSize(int w, int h) {
+ super.setBufferSize(w, h);
+ // The background surface is a color layer so we do not set a size.
}
@Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0eaef5a..2767505 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -21525,10 +21525,18 @@
}
/**
- * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
- * @hide
+ * Assign a size and position to this view.
+ *
+ * This method is meant to be used in animations only as it applies this position and size
+ * for the view only temporary and it can be changed back at any time by the layout.
+ *
+ * @param left Left position, relative to parent
+ * @param top Top position, relative to parent
+ * @param right Right position, relative to parent
+ * @param bottom Bottom position, relative to parent
+ *
+ * @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
*/
- @UnsupportedAppUsage
public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
setFrame(left, top, right, bottom);
}
@@ -24741,7 +24749,7 @@
final SurfaceSession session = new SurfaceSession(root.mSurface);
final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
.setName("drag surface")
- .setSize(shadowSize.x, shadowSize.y)
+ .setBufferSize(shadowSize.x, shadowSize.y)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
final Surface surface = new Surface();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 484c6f3..d9d52c0 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -161,6 +161,19 @@
private static final boolean MT_RENDERER_AVAILABLE = true;
/**
+ * If set to true, the view system will switch from using rectangles retrieved from window to
+ * dispatch to the view hierarchy to using {@link InsetsController}, that derives the insets
+ * directly from the full configuration, enabling richer information about the insets state, as
+ * well as new APIs to control it frame-by-frame, and synchronize animations with it.
+ * <p>
+ * Only switch this to true once the new insets system is productionized and the old APIs are
+ * fully migrated over.
+ */
+ private static final String USE_NEW_INSETS_PROPERTY = "persist.wm.new_insets";
+ private static final boolean USE_NEW_INSETS =
+ SystemProperties.getBoolean(USE_NEW_INSETS_PROPERTY, false);
+
+ /**
* Set this system property to true to force the view hierarchy to render
* at 60 Hz. This can be used to measure the potential framerate.
*/
@@ -432,6 +445,8 @@
boolean mAdded;
boolean mAddedTouchMode;
+ final Rect mTmpFrame = new Rect();
+
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -444,6 +459,7 @@
final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
boolean mPendingAlwaysConsumeNavBar;
+ private InsetsState mPendingInsets;
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -531,6 +547,8 @@
InputEventConsistencyVerifier.isInstrumentationEnabled() ?
new InputEventConsistencyVerifier(this, 0) : null;
+ private final InsetsController mInsetsController = new InsetsController();
+
static final class SystemUiVisibilityInfo {
int seq;
int globalVisibility;
@@ -797,9 +815,11 @@
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
+ getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
- mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
+ mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
+ mInsetsController.getState());
+ setFrame(mTmpFrame);
} catch (RemoteException e) {
mAdded = false;
mView = null;
@@ -826,6 +846,7 @@
mAttachInfo.mAlwaysConsumeNavBar =
(res & WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR) != 0;
mPendingAlwaysConsumeNavBar = mAttachInfo.mAlwaysConsumeNavBar;
+ mPendingInsets = mInsetsController.getState();
if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
@@ -1473,31 +1494,22 @@
mBoundsSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
.setName("Bounds for - " + getTitle().toString())
- .setSize(mWidth, mHeight)
.build();
- setBoundsSurfaceSizeAndCrop();
+ setBoundsSurfaceCrop();
mTransaction.setLayer(mBoundsSurfaceControl, zOrderLayer)
.show(mBoundsSurfaceControl)
.apply();
mBoundsSurface.copyFrom(mBoundsSurfaceControl);
}
- private void setBoundsSurfaceSizeAndCrop() {
+ private void setBoundsSurfaceCrop() {
// mWinFrame is already adjusted for surface insets. So offset it and use it as
// the cropping bounds.
mTempBoundsRect.set(mWinFrame);
mTempBoundsRect.offsetTo(mWindowAttributes.surfaceInsets.left,
mWindowAttributes.surfaceInsets.top);
mTransaction.setWindowCrop(mBoundsSurfaceControl, mTempBoundsRect);
-
- // Expand the bounds by the surface insets to get the size of surface.
- mTempBoundsRect.inset(-mWindowAttributes.surfaceInsets.left,
- -mWindowAttributes.surfaceInsets.top,
- -mWindowAttributes.surfaceInsets.right,
- -mWindowAttributes.surfaceInsets.bottom);
- mTransaction.setSize(mBoundsSurfaceControl, mTempBoundsRect.width(),
- mTempBoundsRect.height());
}
/**
@@ -1506,7 +1518,7 @@
*/
private void updateBoundsSurface() {
if (mBoundsSurfaceControl != null && mSurface.isValid()) {
- setBoundsSurfaceSizeAndCrop();
+ setBoundsSurfaceCrop();
mTransaction.deferTransactionUntilSurface(mBoundsSurfaceControl,
mSurface, mSurface.getNextFrameNumber())
.apply();
@@ -1780,7 +1792,8 @@
Rect stableInsets = mDispatchStableInsets;
DisplayCutout displayCutout = mDispatchDisplayCutout;
// For dispatch we preserve old logic, but for direct requests from Views we allow to
- // immediately use pending insets.
+ // immediately use pending insets. This is such that getRootWindowInsets returns the
+ // result from the layout hint before we ran a traversal shortly after adding a window.
if (!forceConstruct
&& (!mPendingContentInsets.equals(contentInsets) ||
!mPendingStableInsets.equals(stableInsets) ||
@@ -1797,10 +1810,16 @@
}
contentInsets = ensureInsetsNonNegative(contentInsets, "content");
stableInsets = ensureInsetsNonNegative(stableInsets, "stable");
- mLastWindowInsets = new WindowInsets(contentInsets,
- null /* windowDecorInsets */, stableInsets,
- mContext.getResources().getConfiguration().isScreenRound(),
- mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ if (USE_NEW_INSETS) {
+ mLastWindowInsets = mInsetsController.calculateInsets(
+ mContext.getResources().getConfiguration().isScreenRound(),
+ mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ } else {
+ mLastWindowInsets = new WindowInsets(contentInsets,
+ null /* windowDecorInsets */, stableInsets,
+ mContext.getResources().getConfiguration().isScreenRound(),
+ mAttachInfo.mAlwaysConsumeNavBar, displayCutout);
+ }
}
return mLastWindowInsets;
}
@@ -2000,6 +2019,9 @@
if (mPendingAlwaysConsumeNavBar != mAttachInfo.mAlwaysConsumeNavBar) {
insetsChanged = true;
}
+ if (!mPendingInsets.equals(mInsetsController.getState())) {
+ insetsChanged = true;
+ }
if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
windowSizeMayChange = true;
@@ -2193,6 +2215,8 @@
mAttachInfo.mStableInsets);
final boolean cutoutChanged = !mPendingDisplayCutout.equals(
mAttachInfo.mDisplayCutout);
+ final boolean insetsStateChanged = !mPendingInsets.equals(
+ mInsetsController.getState());
final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
final boolean surfaceSizeChanged = (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
@@ -2230,6 +2254,10 @@
mAttachInfo.mAlwaysConsumeNavBar = mPendingAlwaysConsumeNavBar;
contentInsetsChanged = true;
}
+ if (insetsStateChanged) {
+ mInsetsController.setState(mPendingInsets);
+ contentInsetsChanged = true;
+ }
if (contentInsetsChanged || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested
|| mLastOverscanRequested != mAttachInfo.mOverscanRequested
@@ -2675,7 +2703,6 @@
}
private void maybeHandleWindowMove(Rect frame) {
-
// TODO: Well, we are checking whether the frame has changed similarly
// to how this is done for the insets. This is however incorrect since
// the insets and the frame are translated. For example, the old frame
@@ -4180,6 +4207,7 @@
private final static int MSG_UPDATE_POINTER_ICON = 27;
private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
private final static int MSG_DRAW_FINISHED = 29;
+ private final static int MSG_INSETS_CHANGED = 30;
final class ViewRootHandler extends Handler {
@Override
@@ -4235,6 +4263,8 @@
return "MSG_POINTER_CAPTURE_CHANGED";
case MSG_DRAW_FINISHED:
return "MSG_DRAW_FINISHED";
+ case MSG_INSETS_CHANGED:
+ return "MSG_INSETS_CHANGED";
}
return super.getMessageName(message);
}
@@ -4315,7 +4345,7 @@
|| !mPendingVisibleInsets.equals(args.arg3)
|| !mPendingOutsets.equals(args.arg7);
- mWinFrame.set((Rect) args.arg1);
+ setFrame((Rect) args.arg1);
mPendingOverscanInsets.set((Rect) args.arg5);
mPendingContentInsets.set((Rect) args.arg2);
mPendingStableInsets.set((Rect) args.arg6);
@@ -4338,16 +4368,25 @@
requestLayout();
}
break;
+ case MSG_INSETS_CHANGED:
+ mPendingInsets = (InsetsState) msg.obj;
+
+ // TODO: Full traversal not needed here
+ if (USE_NEW_INSETS) {
+ requestLayout();
+ }
+ break;
case MSG_WINDOW_MOVED:
if (mAdded) {
final int w = mWinFrame.width();
final int h = mWinFrame.height();
final int l = msg.arg1;
final int t = msg.arg2;
- mWinFrame.left = l;
- mWinFrame.right = l + w;
- mWinFrame.top = t;
- mWinFrame.bottom = t + h;
+ mTmpFrame.left = l;
+ mTmpFrame.right = l + w;
+ mTmpFrame.top = t;
+ mTmpFrame.bottom = t + h;
+ setFrame(mTmpFrame);
mPendingBackDropFrame.set(mWinFrame);
maybeHandleWindowMove(mWinFrame);
@@ -6733,9 +6772,9 @@
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
- mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
+ mTmpFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
- mPendingMergedConfiguration, mSurface);
+ mPendingMergedConfiguration, mSurface, mPendingInsets);
mPendingAlwaysConsumeNavBar =
(relayoutResult & WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_NAV_BAR) != 0;
@@ -6745,15 +6784,22 @@
}
if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+ mTranslator.translateRectInScreenToAppWinFrame(mTmpFrame);
mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets);
}
+ setFrame(mTmpFrame);
+
return relayoutResult;
}
+ private void setFrame(Rect frame) {
+ mWinFrame.set(frame);
+ mInsetsController.onFrameChanged(frame);
+ }
+
/**
* {@inheritDoc}
*/
@@ -6856,6 +6902,8 @@
mChoreographer.dump(prefix, writer);
+ mInsetsController.dump(prefix, writer);
+
writer.print(prefix); writer.println("View Hierarchy:");
dumpViewHierarchy(innerPrefix, writer, mView);
}
@@ -7064,6 +7112,10 @@
mHandler.sendMessage(msg);
}
+ private void dispatchInsetsChanged(InsetsState insetsState) {
+ mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget();
+ }
+
public void dispatchMoved(int newX, int newY) {
if (DEBUG_LAYOUT) Log.v(mTag, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
if (mTranslator != null) {
@@ -8127,6 +8179,14 @@
}
@Override
+ public void insetsChanged(InsetsState insetsState) {
+ final ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchInsetsChanged(insetsState);
+ }
+ }
+
+ @Override
public void moved(int newX, int newY) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
index 2f128de..7518ff5 100644
--- a/core/java/android/view/intelligence/IIntelligenceManager.aidl
+++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl
@@ -38,7 +38,8 @@
/**
* Finishes a session.
*/
- void finishSession(int userId, in InteractionSessionId sessionId);
+ void finishSession(int userId, in InteractionSessionId sessionId,
+ in List<ContentCaptureEvent> events);
/**
* Sends a batch of events
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index 755c54c..2f3b4ef 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -39,7 +39,6 @@
import android.view.autofill.AutofillId;
import android.view.intelligence.ContentCaptureEvent.EventType;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.Preconditions;
@@ -47,10 +46,18 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* TODO(b/111276913): add javadocs / implement
*/
+/*
+ * NOTE: all methods in this class should return right away, or do the real work in a handler
+ * thread.
+ *
+ * Hence, the only field that must be thread-safe is mEnabled, which is called at the beginning
+ * of every method.
+ */
@SystemService(Context.INTELLIGENCE_MANAGER_SERVICE)
public final class IntelligenceManager {
@@ -97,48 +104,48 @@
private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
/**
- * Maximum number of events that are delayed for an app.
- *
- * <p>If the session is not started after the limit is reached, it's discarded.
+ * Maximum number of events that are buffered before sent to the app.
*/
- private static final int MAX_DELAYED_SIZE = 20;
+ // TODO(b/111276913): use settings
+ private static final int MAX_BUFFER_SIZE = 100;
+ @NonNull
+ private final AtomicBoolean mDisabled = new AtomicBoolean();
+
+ @NonNull
private final Context mContext;
@Nullable
private final IIntelligenceManager mService;
- private final Object mLock = new Object();
-
@Nullable
- @GuardedBy("mLock")
private InteractionSessionId mId;
- @GuardedBy("mLock")
private int mState = STATE_UNKNOWN;
- @GuardedBy("mLock")
+ @Nullable
private IBinder mApplicationToken;
- // TODO(b/111276913): replace by an interface name implemented by Activity, similar to
- // AutofillClient
- @GuardedBy("mLock")
+ @Nullable
private ComponentName mComponentName;
- // TODO(b/111276913): create using maximum batch size as capacity
/**
* List of events held to be sent as a batch.
*/
- @GuardedBy("mLock")
- private final ArrayList<ContentCaptureEvent> mEvents = new ArrayList<>();
+ @Nullable
+ private ArrayList<ContentCaptureEvent> mEvents;
+ // TODO(b/111276913): use UI Thread directly (as calls are one-way) or a shared thread / handler
+ // held at the Application level
private final Handler mHandler;
/** @hide */
public IntelligenceManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
+ if (VERBOSE) {
+ Log.v(TAG, "Constructor for " + context.getPackageName());
+ }
mService = service;
-
// TODO(b/111276913): use an existing bg thread instead...
final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
bgThread.start();
@@ -149,102 +156,100 @@
public void onActivityCreated(@NonNull IBinder token, @NonNull ComponentName componentName) {
if (!isContentCaptureEnabled()) return;
- synchronized (mLock) {
- if (mState != STATE_UNKNOWN) {
- // TODO(b/111276913): revisit this scenario
- Log.w(TAG, "ignoring onActivityStarted(" + token + ") while on state "
- + getStateAsString(mState));
- return;
- }
- mState = STATE_WAITING_FOR_SERVER;
- mId = new InteractionSessionId();
- mApplicationToken = token;
- mComponentName = componentName;
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleStartSession, this,
+ token, componentName));
+ }
- if (VERBOSE) {
- Log.v(TAG, "onActivityCreated(): token=" + token + ", act="
- + getActivityDebugNameLocked() + ", id=" + mId);
- }
- final int flags = 0; // TODO(b/111276913): get proper flags
+ private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName) {
+ if (mState != STATE_UNKNOWN) {
+ // TODO(b/111276913): revisit this scenario
+ Log.w(TAG, "ignoring handleStartSession(" + token + ") while on state "
+ + getStateAsString(mState));
+ return;
+ }
+ mState = STATE_WAITING_FOR_SERVER;
+ mId = new InteractionSessionId();
+ mApplicationToken = token;
+ mComponentName = componentName;
- try {
- mService.startSession(mContext.getUserId(), mApplicationToken, componentName,
- mId, flags, new IResultReceiver.Stub() {
- @Override
- public void send(int resultCode, Bundle resultData)
- throws RemoteException {
- synchronized (mLock) {
- mState = resultCode;
- if (VERBOSE) {
- Log.v(TAG, "onActivityStarted() result: code=" + resultCode
- + ", id=" + mId
- + ", state=" + getStateAsString(mState));
- }
- }
- }
- });
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ if (VERBOSE) {
+ Log.v(TAG, "handleStartSession(): token=" + token + ", act="
+ + getActivityDebugName() + ", id=" + mId);
+ }
+ final int flags = 0; // TODO(b/111276913): get proper flags
+
+ try {
+ mService.startSession(mContext.getUserId(), mApplicationToken, componentName,
+ mId, flags, new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) {
+ handleSessionStarted(resultCode);
+ }
+ });
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error starting session for " + componentName.flattenToShortString() + ": "
+ + e);
}
}
- //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
- // calling right away
- private void sendEvent(@NonNull ContentCaptureEvent event) {
- mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, event));
+ private void handleSessionStarted(int resultCode) {
+ mState = resultCode;
+ mDisabled.set(mState == STATE_DISABLED);
+ if (VERBOSE) {
+ Log.v(TAG, "onActivityStarted() result: code=" + resultCode + ", id=" + mId
+ + ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get());
+ }
}
- private void handleSendEvent(@NonNull ContentCaptureEvent event) {
-
- //TODO(b/111276913): make a copy and don't use lock
- synchronized (mLock) {
- mEvents.add(event);
- final int numberEvents = mEvents.size();
- if (mState != STATE_ACTIVE) {
- if (numberEvents >= MAX_DELAYED_SIZE) {
- // Typically happens on system apps that are started before the system service
- // is ready (like com.android.settings/.FallbackHome)
- //TODO(b/111276913): try to ignore session while system is not ready / boot
- // not complete instead. Similarly, the manager service should return right away
- // when the user does not have a service set
- if (VERBOSE) {
- Log.v(TAG, "Closing session for " + getActivityDebugNameLocked()
- + " after " + numberEvents + " delayed events and state "
- + getStateAsString(mState));
- }
- // TODO(b/111276913): blacklist activity / use special flag to indicate that
- // when it's launched again
- resetStateLocked();
- return;
- }
-
- if (VERBOSE) {
- Log.v(TAG, "Delaying " + numberEvents + " events for "
- + getActivityDebugNameLocked() + " while on state "
- + getStateAsString(mState));
- }
- return;
+ private void handleSendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
+ if (mEvents == null) {
+ if (VERBOSE) {
+ Log.v(TAG, "Creating buffer for " + MAX_BUFFER_SIZE + " events");
}
+ mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
+ }
+ mEvents.add(event);
+ final int numberEvents = mEvents.size();
+ if (numberEvents < MAX_BUFFER_SIZE && !forceFlush) {
+ // Buffering events, return right away...
+ return;
+ }
- if (mId == null) {
- // Sanity check - should not happen
- Log.wtf(TAG, "null session id for " + mComponentName);
- return;
+ if (mState != STATE_ACTIVE) {
+ // Callback from startSession hasn't been called yet - typically happens on system
+ // apps that are started before the system service
+ // TODO(b/111276913): try to ignore session while system is not ready / boot
+ // not complete instead. Similarly, the manager service should return right away
+ // when the user does not have a service set
+ if (VERBOSE) {
+ Log.v(TAG, "Closing session for " + getActivityDebugName()
+ + " after " + numberEvents + " delayed events and state "
+ + getStateAsString(mState));
}
+ handleResetState();
+ // TODO(b/111276913): blacklist activity / use special flag to indicate that
+ // when it's launched again
+ return;
+ }
- //TODO(b/111276913): right now we're sending sending right away (unless not ready), but
- // we should hold the events and flush later.
- try {
- if (DEBUG) {
- Log.d(TAG, "Sending " + numberEvents + " event(s) for "
- + getActivityDebugNameLocked());
- }
- mService.sendEvents(mContext.getUserId(), mId, mEvents);
- mEvents.clear();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ if (mId == null) {
+ // Sanity check - should not happen
+ Log.wtf(TAG, "null session id for " + getActivityDebugName());
+ return;
+ }
+
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getActivityDebugName());
}
+ mService.sendEvents(mContext.getUserId(), mId, mEvents);
+ // TODO(b/111276913): decide whether we should clear or set it to null, as each has
+ // its own advantages: clearing will save extra allocations while the session is
+ // active, while setting to null would save memory if there's no more event coming.
+ mEvents.clear();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error sending " + numberEvents + " for " + getActivityDebugName()
+ + ": " + e);
}
}
@@ -256,41 +261,54 @@
public void onActivityLifecycleEvent(@EventType int type) {
if (!isContentCaptureEnabled()) return;
if (VERBOSE) {
- Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugNameLocked()
+ Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugName()
+ ": " + ContentCaptureEvent.getTypeAsString(type));
}
- sendEvent(new ContentCaptureEvent(type));
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this,
+ new ContentCaptureEvent(type), /* forceFlush= */ true));
}
/** @hide */
public void onActivityDestroyed() {
if (!isContentCaptureEnabled()) return;
- synchronized (mLock) {
- //TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
- // id) and send it to the cache of batched commands
+ //TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
+ // id) and send it to the cache of batched commands
+ if (VERBOSE) {
+ Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsString(mState)
+ + ", mId=" + mId);
+ }
- if (VERBOSE) {
- Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsString(mState)
- + ", mId=" + mId);
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleFinishSession, this));
+ }
+
+ private void handleFinishSession() {
+ //TODO(b/111276913): right now both the ContentEvents and lifecycle sessions are sent
+ // to system_server, so it's ok to call both in sequence here. But once we split
+ // them so the events are sent directly to the service, we need to make sure they're
+ // sent in order.
+ try {
+ if (DEBUG) {
+ Log.d(TAG, "Finishing session " + mId + " with "
+ + (mEvents == null ? 0 : mEvents.size()) + " event(s) for "
+ + getActivityDebugName());
}
- try {
- mService.finishSession(mContext.getUserId(), mId);
- resetStateLocked();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ mService.finishSession(mContext.getUserId(), mId, mEvents);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error finishing session " + mId + " for " + getActivityDebugName()
+ + ": " + e);
+ } finally {
+ handleResetState();
}
}
- @GuardedBy("mLock")
- private void resetStateLocked() {
+ private void handleResetState() {
mState = STATE_UNKNOWN;
mId = null;
mApplicationToken = null;
mComponentName = null;
- mEvents.clear();
+ mEvents = null;
}
/**
@@ -309,8 +327,11 @@
if (!(node instanceof ViewNode.ViewStructureImpl)) {
throw new IllegalArgumentException("Invalid node class: " + node.getClass());
}
- sendEvent(new ContentCaptureEvent(TYPE_VIEW_APPEARED)
- .setViewNode(((ViewNode.ViewStructureImpl) node).mNode));
+
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this,
+ new ContentCaptureEvent(TYPE_VIEW_APPEARED)
+ .setViewNode(((ViewNode.ViewStructureImpl) node).mNode),
+ /* forceFlush= */ false));
}
/**
@@ -325,7 +346,9 @@
Preconditions.checkNotNull(id);
if (!isContentCaptureEnabled()) return;
- sendEvent(new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id));
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this,
+ new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id),
+ /* forceFlush= */ false));
}
/**
@@ -339,10 +362,12 @@
public void notifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text,
int flags) {
Preconditions.checkNotNull(id);
+
if (!isContentCaptureEnabled()) return;
- sendEvent(new ContentCaptureEvent(TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
- .setText(text));
+ mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this,
+ new ContentCaptureEvent(TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
+ .setText(text), /* forceFlush= */ false));
}
/**
@@ -384,10 +409,7 @@
* Checks whether content capture is enabled for this activity.
*/
public boolean isContentCaptureEnabled() {
- //TODO(b/111276913): properly implement by checking if it was explicitly disabled by
- // service, or if service is not set
- // (and probably renamign to isEnabledLocked()
- return mService != null && mState != STATE_DISABLED;
+ return mService != null && !mDisabled.get();
}
/**
@@ -504,25 +526,36 @@
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.println("IntelligenceManager");
final String prefix2 = prefix + " ";
- synchronized (mLock) {
- pw.print(prefix2); pw.print("mContext: "); pw.println(mContext);
+ pw.print(prefix2); pw.print("mContext: "); pw.println(mContext);
+ pw.print(prefix2); pw.print("user: "); pw.println(mContext.getUserId());
+ if (mService != null) {
pw.print(prefix2); pw.print("mService: "); pw.println(mService);
- pw.print(prefix2); pw.print("user: "); pw.println(mContext.getUserId());
- pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
+ }
+ pw.print(prefix2); pw.print("mDisabled: "); pw.println(mDisabled.get());
+ pw.print(prefix2); pw.print("isEnabled(): "); pw.println(isContentCaptureEnabled());
+ if (mId != null) {
pw.print(prefix2); pw.print("id: "); pw.println(mId);
- pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
- pw.print(getStateAsString(mState)); pw.println(")");
+ }
+ pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
+ pw.print(getStateAsString(mState)); pw.println(")");
+ if (mApplicationToken != null) {
pw.print(prefix2); pw.print("app token: "); pw.println(mApplicationToken);
+ }
+ if (mComponentName != null) {
pw.print(prefix2); pw.print("component name: ");
- pw.println(mComponentName == null ? "null" : mComponentName.flattenToShortString());
+ pw.println(mComponentName.flattenToShortString());
+ }
+ if (mEvents != null) {
final int numberEvents = mEvents.size();
- pw.print(prefix2); pw.print("batched events: "); pw.println(numberEvents);
- if (numberEvents > 0) {
+ pw.print(prefix2); pw.print("batched events: "); pw.print(numberEvents);
+ pw.print('/'); pw.println(MAX_BUFFER_SIZE);
+ if (VERBOSE && numberEvents > 0) {
+ final String prefix3 = prefix2 + " ";
for (int i = 0; i < numberEvents; i++) {
final ContentCaptureEvent event = mEvents.get(i);
- pw.println(i); pw.print(": "); event.dump(pw); pw.println();
+ pw.print(prefix3); pw.print(i); pw.print(": "); event.dump(pw);
+ pw.println();
}
-
}
}
}
@@ -530,8 +563,7 @@
/**
* Gets a string that can be used to identify the activity on logging statements.
*/
- @GuardedBy("mLock")
- private String getActivityDebugNameLocked() {
+ private String getActivityDebugName() {
return mComponentName == null ? mContext.getPackageName()
: mComponentName.flattenToShortString();
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index f4c25c3..7d02757 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -837,7 +837,7 @@
mSurfaceSession = new SurfaceSession(parentSurface);
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
.setFormat(PixelFormat.TRANSLUCENT)
- .setSize(mSurfaceWidth, mSurfaceHeight)
+ .setBufferSize(mSurfaceWidth, mSurfaceHeight)
.setName("magnifier surface")
.setFlags(SurfaceControl.HIDDEN)
.build();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c0979fe..7b39efe 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -161,6 +161,7 @@
private static final int LAYOUT_PARAM_ACTION_TAG = 19;
private static final int OVERRIDE_TEXT_COLORS_TAG = 20;
private static final int SET_RIPPLE_DRAWABLE_COLOR_TAG = 21;
+ private static final int SET_INT_TAG_TAG = 22;
/**
* Application that hosts the remote views.
@@ -274,6 +275,15 @@
}
/**
+ * Sets an integer tag to the view.
+ *
+ * @hide
+ */
+ public void setIntTag(int viewId, int key, int tag) {
+ addAction(new SetIntTagAction(viewId, key, tag));
+ }
+
+ /**
* Set that it is disallowed to reapply another remoteview with the same layout as this view.
* This should be done if an action is destroying the view tree of the base layout.
*
@@ -2122,6 +2132,43 @@
}
}
+ private class SetIntTagAction extends Action {
+ private final int mViewId;
+ private final int mKey;
+ private final int mTag;
+
+ SetIntTagAction(int viewId, int key, int tag) {
+ mViewId = viewId;
+ mKey = key;
+ mTag = tag;
+ }
+
+ SetIntTagAction(Parcel parcel) {
+ mViewId = parcel.readInt();
+ mKey = parcel.readInt();
+ mTag = parcel.readInt();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mViewId);
+ dest.writeInt(mKey);
+ dest.writeInt(mTag);
+ }
+
+ @Override
+ public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+ final View target = root.findViewById(mViewId);
+ if (target == null) return;
+
+ target.setTagInternal(mKey, mTag);
+ }
+
+ @Override
+ public int getActionTag() {
+ return SET_INT_TAG_TAG;
+ }
+ }
+
/**
* Create a new RemoteViews object that will display the views contained
* in the specified layout file.
@@ -2326,6 +2373,8 @@
return new OverrideTextColorsAction(parcel);
case SET_RIPPLE_DRAWABLE_COLOR_TAG:
return new SetRippleDrawableColor(parcel);
+ case SET_INT_TAG_TAG:
+ return new SetIntTagAction(parcel);
default:
throw new ActionException("Tag " + tag + " not found");
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4ed9924f0d..85d851a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12268,13 +12268,13 @@
}
/**
- * Returns the current {@link TextDirectionHeuristic}.
- *
- * @return the current {@link TextDirectionHeuristic}.
- * @hide
+ * Returns resolved {@link TextDirectionHeuristic} that will be used for text layout.
+ * The {@link TextDirectionHeuristic} that is used by TextView is only available after
+ * {@link #getTextDirection()} and {@link #getLayoutDirection()} is resolved. Therefore the
+ * return value may not be the same as the one TextView uses if the View's layout direction is
+ * not resolved or detached from parent root view.
*/
- @UnsupportedAppUsage
- protected TextDirectionHeuristic getTextDirectionHeuristic() {
+ public TextDirectionHeuristic getTextDirectionHeuristic() {
if (hasPasswordTransformationMethod()) {
// passwords fields should be LTR
return TextDirectionHeuristics.LTR;
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index b9d53c1..d78bfac 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -120,6 +120,8 @@
arg5 = null;
arg6 = null;
arg7 = null;
+ arg8 = null;
+ arg9 = null;
argi1 = 0;
argi2 = 0;
argi3 = 0;
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 69ba070..b7ffb57 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -16,6 +16,7 @@
package com.android.internal.statusbar;
+import android.app.Notification;
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
@@ -55,7 +56,7 @@
// Mark current notifications as "seen" and stop ringing, vibrating, blinking.
void clearNotificationEffects();
void onNotificationClick(String key, in NotificationVisibility nv);
- void onNotificationActionClick(String key, int actionIndex, in NotificationVisibility nv);
+ void onNotificationActionClick(String key, int actionIndex, in Notification.Action action, in NotificationVisibility nv, boolean generatedByAssistant);
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
void onClearAllNotifications(int userId);
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 5da587b..344d7ef 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -63,7 +63,7 @@
public static final int
convertValueToList(CharSequence value, String[] options, int defaultValue)
{
- if (null != value) {
+ if (!TextUtils.isEmpty(value)) {
for (int i = 0; i < options.length; i++) {
if (value.equals(options[i]))
return i;
@@ -79,8 +79,9 @@
{
boolean result = false;
- if (null == value)
+ if (TextUtils.isEmpty(value)) {
return defaultValue;
+ }
if (value.equals("1")
|| value.equals("true")
@@ -94,8 +95,9 @@
public static final int
convertValueToInt(CharSequence charSeq, int defaultValue)
{
- if (null == charSeq)
+ if (TextUtils.isEmpty(charSeq)) {
return defaultValue;
+ }
String nm = charSeq.toString();
@@ -138,7 +140,7 @@
}
public static int convertValueToUnsignedInt(String value, int defaultValue) {
- if (null == value) {
+ if (TextUtils.isEmpty(value)) {
return defaultValue;
}
@@ -1674,7 +1676,7 @@
public static boolean readBooleanAttribute(XmlPullParser in, String name,
boolean defaultValue) {
final String value = in.getAttributeValue(null, name);
- if (value == null) {
+ if (TextUtils.isEmpty(value)) {
return defaultValue;
} else {
return Boolean.parseBoolean(value);
@@ -1711,7 +1713,7 @@
public static byte[] readByteArrayAttribute(XmlPullParser in, String name) {
final String value = in.getAttributeValue(null, name);
- if (value != null) {
+ if (!TextUtils.isEmpty(value)) {
return Base64.decode(value, Base64.DEFAULT);
} else {
return null;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 137ca7f..36fe4fc 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -27,6 +27,7 @@
import android.view.IWindow;
import android.view.IWindowSession;
import android.view.PointerIcon;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
@@ -53,6 +54,10 @@
}
@Override
+ public void insetsChanged(InsetsState insetsState) {
+ }
+
+ @Override
public void moved(int newX, int newY) {
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 7635a72..b7e656b 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -814,7 +814,14 @@
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp.alwaysShow && child.getVisibility() != GONE) {
- measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ if (lp.maxHeight != -1) {
+ final int remainingHeight = heightSize - heightUsed;
+ measureChildWithMargins(child, widthSpec, widthPadding,
+ MeasureSpec.makeMeasureSpec(lp.maxHeight, MeasureSpec.AT_MOST),
+ lp.maxHeight > remainingHeight ? lp.maxHeight - remainingHeight : 0);
+ } else {
+ measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ }
heightUsed += child.getMeasuredHeight();
}
}
@@ -824,9 +831,17 @@
// And now the rest.
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
+
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.alwaysShow && child.getVisibility() != GONE) {
- measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ if (lp.maxHeight != -1) {
+ final int remainingHeight = heightSize - heightUsed;
+ measureChildWithMargins(child, widthSpec, widthPadding,
+ MeasureSpec.makeMeasureSpec(lp.maxHeight, MeasureSpec.AT_MOST),
+ lp.maxHeight > remainingHeight ? lp.maxHeight - remainingHeight : 0);
+ } else {
+ measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ }
heightUsed += child.getMeasuredHeight();
}
}
@@ -938,6 +953,7 @@
public boolean alwaysShow;
public boolean ignoreOffset;
public boolean hasNestedScrollIndicator;
+ public int maxHeight;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
@@ -953,6 +969,8 @@
hasNestedScrollIndicator = a.getBoolean(
R.styleable.ResolverDrawerLayout_LayoutParams_layout_hasNestedScrollIndicator,
false);
+ maxHeight = a.getDimensionPixelSize(
+ R.styleable.ResolverDrawerLayout_LayoutParams_layout_maxHeight, -1);
a.recycle();
}
@@ -965,6 +983,7 @@
this.alwaysShow = source.alwaysShow;
this.ignoreOffset = source.ignoreOffset;
this.hasNestedScrollIndicator = source.hasNestedScrollIndicator;
+ this.maxHeight = source.maxHeight;
}
public LayoutParams(MarginLayoutParams source) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 68f5bef..ed6a84b 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -64,11 +64,10 @@
jint tileModeX, jint tileModeY) {
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
sk_sp<SkImage> image;
- sk_sp<SkColorFilter> colorFilter;
if (jbitmap) {
// Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
// we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
- image = android::bitmap::toBitmap(env, jbitmap).makeImage(&colorFilter);
+ image = android::bitmap::toBitmap(env, jbitmap).makeImage();
}
if (!image.get()) {
@@ -81,9 +80,6 @@
if (matrix) {
shader = shader->makeWithLocalMatrix(*matrix);
}
- if(colorFilter) {
- shader = shader->makeWithColorFilter(colorFilter);
- }
ThrowIAE_IfNull(env, shader.get());
return reinterpret_cast<jlong>(shader.release());
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp
index 5887fa7..10005dd 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.cpp
+++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -22,6 +22,7 @@
#include <utils/threads.h>
#include "android_hardware_input_InputApplicationHandle.h"
+#include "android_util_Binder.h"
namespace android {
@@ -29,6 +30,7 @@
jfieldID ptr;
jfieldID name;
jfieldID dispatchingTimeoutNanos;
+ jfieldID token;
} gInputApplicationHandleClassInfo;
static Mutex gHandleMutex;
@@ -75,6 +77,15 @@
mInfo->dispatchingTimeout = env->GetLongField(obj,
gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
+ jobject tokenObj = env->GetObjectField(obj,
+ gInputApplicationHandleClassInfo.token);
+ if (tokenObj) {
+ mInfo->token = ibinderForJavaObject(env, tokenObj);
+ env->DeleteLocalRef(tokenObj);
+ } else {
+ mInfo->token.clear();
+ }
+
env->DeleteLocalRef(obj);
return true;
}
@@ -153,6 +164,9 @@
clazz,
"dispatchingTimeoutNanos", "J");
+ GET_FIELD_ID(gInputApplicationHandleClassInfo.token, clazz,
+ "token", "Landroid/os/IBinder;");
+
return 0;
}
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index 6ecb5de..76920f5 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -21,19 +21,19 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/threads.h>
-#include <android_view_InputChannel.h>
#include <android/graphics/Region.h>
#include <ui/Region.h>
#include "android_hardware_input_InputWindowHandle.h"
#include "android_hardware_input_InputApplicationHandle.h"
+#include "android_util_Binder.h"
namespace android {
static struct {
jfieldID ptr;
jfieldID inputApplicationHandle;
- jfieldID inputChannel;
+ jfieldID token;
jfieldID name;
jfieldID layoutParamsFlags;
jfieldID layoutParamsType;
@@ -42,6 +42,7 @@
jfieldID frameTop;
jfieldID frameRight;
jfieldID frameBottom;
+ jfieldID surfaceInset;
jfieldID scaleFactor;
jfieldID touchableRegion;
jfieldID visible;
@@ -61,9 +62,7 @@
// --- NativeInputWindowHandle ---
-NativeInputWindowHandle::NativeInputWindowHandle(
- const sp<InputApplicationHandle>& inputApplicationHandle, jweak objWeak) :
- InputWindowHandle(inputApplicationHandle),
+NativeInputWindowHandle::NativeInputWindowHandle(jweak objWeak) :
mObjWeak(objWeak) {
}
@@ -86,13 +85,12 @@
mInfo.touchableRegion.clear();
- jobject inputChannelObj = env->GetObjectField(obj,
- gInputWindowHandleClassInfo.inputChannel);
- if (inputChannelObj) {
- mInfo.inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
- env->DeleteLocalRef(inputChannelObj);
+ jobject tokenObj = env->GetObjectField(obj,
+ gInputWindowHandleClassInfo.token);
+ if (tokenObj) {
+ mInfo.token = ibinderForJavaObject(env, tokenObj);
} else {
- mInfo.inputChannel.clear();
+ mInfo.token.clear();
}
jstring nameObj = jstring(env->GetObjectField(obj,
@@ -120,7 +118,9 @@
gInputWindowHandleClassInfo.frameRight);
mInfo.frameBottom = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameBottom);
- mInfo.scaleFactor = env->GetFloatField(obj,
+ mInfo.surfaceInset = env->GetIntField(obj,
+ gInputWindowHandleClassInfo.surfaceInset);
+ mInfo.globalScaleFactor = env->GetFloatField(obj,
gInputWindowHandleClassInfo.scaleFactor);
jobject regionObj = env->GetObjectField(obj,
@@ -155,6 +155,18 @@
mInfo.displayId = env->GetIntField(obj,
gInputWindowHandleClassInfo.displayId);
+ jobject inputApplicationHandleObj = env->GetObjectField(obj,
+ gInputWindowHandleClassInfo.inputApplicationHandle);
+ if (inputApplicationHandleObj) {
+ sp<InputApplicationHandle> inputApplicationHandle =
+ android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+ if (inputApplicationHandle != nullptr) {
+ inputApplicationHandle->updateInfo();
+ mInfo.applicationInfo = *(inputApplicationHandle->getInfo());
+ }
+ env->DeleteLocalRef(inputApplicationHandleObj);
+ }
+
env->DeleteLocalRef(obj);
return true;
}
@@ -175,14 +187,8 @@
if (ptr) {
handle = reinterpret_cast<NativeInputWindowHandle*>(ptr);
} else {
- jobject inputApplicationHandleObj = env->GetObjectField(inputWindowHandleObj,
- gInputWindowHandleClassInfo.inputApplicationHandle);
- sp<InputApplicationHandle> inputApplicationHandle =
- android_server_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
- env->DeleteLocalRef(inputApplicationHandleObj);
-
jweak objWeak = env->NewWeakGlobalRef(inputWindowHandleObj);
- handle = new NativeInputWindowHandle(inputApplicationHandle, objWeak);
+ handle = new NativeInputWindowHandle(objWeak);
handle->incStrong((void*)android_server_InputWindowHandle_getHandle);
env->SetLongField(inputWindowHandleObj, gInputWindowHandleClassInfo.ptr,
reinterpret_cast<jlong>(handle));
@@ -236,8 +242,8 @@
clazz,
"inputApplicationHandle", "Landroid/view/InputApplicationHandle;");
- GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
- "inputChannel", "Landroid/view/InputChannel;");
+ GET_FIELD_ID(gInputWindowHandleClassInfo.token, clazz,
+ "token", "Landroid/os/IBinder;");
GET_FIELD_ID(gInputWindowHandleClassInfo.name, clazz,
"name", "Ljava/lang/String;");
@@ -263,6 +269,9 @@
GET_FIELD_ID(gInputWindowHandleClassInfo.frameBottom, clazz,
"frameBottom", "I");
+ GET_FIELD_ID(gInputWindowHandleClassInfo.surfaceInset, clazz,
+ "surfaceInset", "I");
+
GET_FIELD_ID(gInputWindowHandleClassInfo.scaleFactor, clazz,
"scaleFactor", "F");
diff --git a/core/jni/android_hardware_input_InputWindowHandle.h b/core/jni/android_hardware_input_InputWindowHandle.h
index 2be267e..54b89f5 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.h
+++ b/core/jni/android_hardware_input_InputWindowHandle.h
@@ -26,8 +26,7 @@
class NativeInputWindowHandle : public InputWindowHandle {
public:
- NativeInputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle,
- jweak objWeak);
+ NativeInputWindowHandle(jweak objWeak);
virtual ~NativeInputWindowHandle();
jobject getInputWindowHandleObjLocalRef(JNIEnv* env);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 2c0158a..adab8e2 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2032,6 +2032,35 @@
return FCC_8;
}
+static jint
+android_media_AudioSystem_setAssistantUid(JNIEnv *env, jobject thiz, jint uid)
+{
+ status_t status = AudioSystem::setAssistantUid(uid);
+ return (jint)nativeToJavaStatus(status);
+}
+
+static jint
+android_media_AudioSystem_setA11yServicesUids(JNIEnv *env, jobject thiz, jintArray uids) {
+ std::vector<uid_t> nativeUidsVector;
+
+ if (uids != nullptr) {
+ jsize len = env->GetArrayLength(uids);
+
+ if (len > 0) {
+ int *nativeUids = nullptr;
+ nativeUids = env->GetIntArrayElements(uids, 0);
+ if (nativeUids != nullptr) {
+ for (size_t i = 0; i < len; i++) {
+ nativeUidsVector.push_back(nativeUids[i]);
+ }
+ env->ReleaseIntArrayElements(uids, nativeUids, 0);
+ }
+ }
+ }
+ status_t status = AudioSystem::setA11yServicesUids(nativeUidsVector);
+ return (jint)nativeToJavaStatus(status);
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -2092,6 +2121,8 @@
{"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
{"getSurroundFormats", "(Ljava/util/Map;Z)I", (void *)android_media_AudioSystem_getSurroundFormats},
{"setSurroundFormatEnabled", "(IZ)I", (void *)android_media_AudioSystem_setSurroundFormatEnabled},
+ {"setAssistantUid", "(I)I", (void *)android_media_AudioSystem_setAssistantUid},
+ {"setA11yServicesUids", "([I)I", (void *)android_media_AudioSystem_setA11yServicesUids},
};
static const JNINativeMethod gEventHandlerMethods[] = {
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 7de8020..d917536 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -550,6 +550,10 @@
}
optional MultiSim multi_sim = 76;
+ // Whether we've enabled native flags health check on this device. Takes effect on
+ // reboot. The value "1" enables native flags health check; otherwise it's disabled.
+ optional SettingProto native_flags_health_check_enabled = 144 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
message Netstats {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -987,5 +991,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 144;
+ // Next tag = 145;
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 99f096d..679a1d2 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -156,7 +156,7 @@
optional int32 rotation = 11;
optional ScreenRotationAnimationProto screen_rotation_animation = 12;
optional DisplayFramesProto display_frames = 13;
- optional int32 surface_size = 14;
+ optional int32 surface_size = 14 [deprecated=true];
optional string focused_app = 15;
optional AppTransitionProto app_transition = 16;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8c5b6f4..6c3085f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -620,6 +620,8 @@
<protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL" />
+ <protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
@@ -4204,6 +4206,18 @@
<permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
android:protectionLevel="signature|appop" />
+ <!-- @SystemApi Allows requesting the framework broadcast the
+ {@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY} intent.
+ @hide -->
+ <permission android:name="android.permission.SEND_DEVICE_CUSTOMIZATION_READY"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Permission that protects the {@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY}
+ intent.
+ @hide -->
+ <permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"
+ android:protectionLevel="signature|preinstalled" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6c4861b..470e1cc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8803,6 +8803,7 @@
<attr name="layout_ignoreOffset" format="boolean" />
<attr name="layout_gravity" />
<attr name="layout_hasNestedScrollIndicator" format="boolean" />
+ <attr name="layout_maxHeight" />
</declare-styleable>
<!-- @hide -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 64e5bc0..bbe3ff9 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -190,4 +190,7 @@
<!-- A tag used to save the view added to a transition overlay -->
<item type="id" name="transition_overlay_view_tag" />
+
+ <!-- A tag used to save the notification action object -->
+ <item type="id" name="notification_action_index_tag" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9264f90..e251e27 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2683,6 +2683,7 @@
<java-symbol type="id" name="smart_reply_container" />
<java-symbol type="id" name="remote_input_tag" />
<java-symbol type="id" name="pending_intent_tag" />
+ <java-symbol type="id" name="notification_action_index_tag" />
<java-symbol type="attr" name="seekBarDialogPreferenceStyle" />
<java-symbol type="string" name="ext_media_status_removed" />
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index e1cb911..e89a4d3 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -106,9 +106,9 @@
int backgroundColor = 0xff585868;
int initialForegroundColor = 0xff505868;
builder.setColorPalette(backgroundColor, initialForegroundColor);
- int primaryTextColor = builder.getPrimaryTextColor();
+ int primaryTextColor = builder.getPrimaryTextColor(builder.mParams);
assertTrue(satisfiesTextContrast(primaryTextColor, backgroundColor));
- int secondaryTextColor = builder.getSecondaryTextColor();
+ int secondaryTextColor = builder.getSecondaryTextColor(builder.mParams);
assertTrue(satisfiesTextContrast(secondaryTextColor, backgroundColor));
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8f58330..305d2af 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -126,6 +126,7 @@
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
Settings.Global.AUTOFILL_SMART_SUGGESTION_EMULATION_FLAGS,
Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED,
Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
@@ -314,6 +315,7 @@
Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION,
Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
Settings.Global.MULTI_SIM_VOICE_PROMPT,
+ Settings.Global.NATIVE_FLAGS_HEALTH_CHECK_ENABLED,
Settings.Global.NETSTATS_DEV_BUCKET_DURATION,
Settings.Global.NETSTATS_DEV_DELETE_AGE,
Settings.Global.NETSTATS_DEV_PERSIST_BYTES,
@@ -661,7 +663,8 @@
Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
Settings.Secure.FLASHLIGHT_AVAILABLE,
- Settings.Secure.FLASHLIGHT_ENABLED);
+ Settings.Secure.FLASHLIGHT_ENABLED,
+ Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
new file mode 100644
index 0000000..ed472d2
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.view;
+
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static junit.framework.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsSourceTest {
+
+ private InsetsSource mSource = new InsetsSource(TYPE_NAVIGATION_BAR);
+
+ @Before
+ public void setUp() {
+ mSource.setVisible(true);
+ }
+
+ @Test
+ public void testCalculateInsetsTop() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsBottom() {
+ mSource.setFrame(new Rect(0, 400, 500, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 100), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsLeft() {
+ mSource.setFrame(new Rect(0, 0, 100, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(100, 0, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsetsRight() {
+ mSource.setFrame(new Rect(400, 0, 500, 500));
+ Insets insets = mSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 100, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_overextend() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_invisible() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ mSource.setVisible(false);
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 0), insets);
+ }
+
+ @Test
+ public void testCalculateInsets_ignoreVisibility() {
+ mSource.setFrame(new Rect(0, 0, 500, 100));
+ mSource.setVisible(false);
+ Insets insets = mSource.calculateInsets(new Rect(100, 0, 500, 500),
+ true /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 100, 0, 0), insets);
+ }
+
+ // Parcel and equals already tested via InsetsStateTest
+}
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
new file mode 100644
index 0000000..6bb9539
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package android.view;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.graphics.Rect;
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsStateTest {
+
+ private InsetsState mState = new InsetsState();
+ private InsetsState mState2 = new InsetsState();
+
+ @Test
+ public void testCalculateInsets() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(new Rect(0, 100, 0, 100), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testCalculateInsets_imeAndNav() {
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(100, insets.getStableInsetBottom());
+ assertEquals(new Rect(0, 0, 0, 200), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testCalculateInsets_navRightStatusTop() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(new Rect(0, 100, 20, 0), insets.getSystemWindowInsets());
+ }
+
+ @Test
+ public void testStripForDispatch() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState.removeSource(TYPE_IME);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT);
+ assertEquals(0, insets.getSystemWindowInsetBottom());
+ }
+
+ @Test
+ public void testEquals_differentRect() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_differentSource() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_sameButDifferentInsertOrder() {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ assertEquals(mState, mState2);
+ }
+
+ @Test
+ public void testEquals_visibility() {
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ assertNotEquals(mState, mState2);
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_IME).setVisible(true);
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ Parcel p = Parcel.obtain();
+ mState.writeToParcel(p, 0 /* flags */);
+ mState2.readFromParcel(p);
+ p.recycle();
+ assertEquals(mState, mState2);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
index 2ec35e9..fbcb629 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.content.Intent;
import android.os.LocaleList;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -64,6 +65,8 @@
@Parameterized.Parameter
public String mTextClassifierType;
+ private static final TextClassificationConstants TC_CONSTANTS =
+ TextClassificationConstants.loadFromString("");
private static final LocaleList LOCALES = LocaleList.forLanguageTags("en-US");
private static final String NO_TYPE = null;
@@ -80,7 +83,7 @@
}
@Test
- public void testSmartSelection() {
+ public void testSuggestSelection() {
if (isTextClassifierDisabled()) return;
String text = "Contact me at droid@android.com";
@@ -101,7 +104,7 @@
}
@Test
- public void testSmartSelection_url() {
+ public void testSuggestSelection_url() {
if (isTextClassifierDisabled()) return;
String text = "Visit http://www.android.com for more information";
@@ -157,7 +160,7 @@
}
@Test
- public void testTextClassifyText_url() {
+ public void testClassifyText_url() {
if (isTextClassifierDisabled()) return;
String text = "Visit www.android.com for more information";
@@ -174,7 +177,7 @@
}
@Test
- public void testTextClassifyText_address() {
+ public void testClassifyText_address() {
if (isTextClassifierDisabled()) return;
String text = "Brandschenkestrasse 110, Zürich, Switzerland";
@@ -188,7 +191,7 @@
}
@Test
- public void testTextClassifyText_url_inCaps() {
+ public void testClassifyText_url_inCaps() {
if (isTextClassifierDisabled()) return;
String text = "Visit HTTP://ANDROID.COM for more information";
@@ -205,7 +208,7 @@
}
@Test
- public void testTextClassifyText_date() {
+ public void testClassifyText_date() {
if (isTextClassifierDisabled()) return;
String text = "Let's meet on January 9, 2018.";
@@ -222,7 +225,7 @@
}
@Test
- public void testTextClassifyText_datetime() {
+ public void testClassifyText_datetime() {
if (isTextClassifierDisabled()) return;
String text = "Let's meet 2018/01/01 10:30:20.";
@@ -240,6 +243,30 @@
}
@Test
+ public void testClassifyText_foreignText() {
+ LocaleList originalLocales = LocaleList.getDefault();
+ LocaleList.setDefault(LocaleList.forLanguageTags("en"));
+ String foreignText = "これは日本語のテキストです";
+
+ Context context = new FakeContextBuilder()
+ .setIntentComponent(Intent.ACTION_TRANSLATE, FakeContextBuilder.DEFAULT_COMPONENT)
+ .build();
+ TextClassifier classifier = new TextClassifierImpl(context, TC_CONSTANTS);
+ TextClassification.Request request = new TextClassification.Request.Builder(
+ foreignText, 0, foreignText.length())
+ .setDefaultLocales(LOCALES)
+ .build();
+
+ TextClassification classification = classifier.classifyText(request);
+ assertEquals(1, classification.getActions().size());
+ assertEquals(
+ context.getString(com.android.internal.R.string.translate),
+ classification.getActions().get(0).getTitle());
+
+ LocaleList.setDefault(originalLocales);
+ }
+
+ @Test
public void testGenerateLinks_phone() {
if (isTextClassifierDisabled()) return;
String text = "The number is +12122537077. See you tonight!";
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 4456122..36792bb 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -467,6 +467,21 @@
assertArrayEquals(container.mSharedViewNames, new String[] {"e0", "e1", "e2"});
}
+ @Test
+ public void setIntTag() {
+ RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
+ int index = 10;
+ views.setIntTag(
+ R.id.layout, com.android.internal.R.id.notification_action_index_tag, index);
+
+ RemoteViews recovered = parcelAndRecreate(views);
+ RemoteViews cloned = new RemoteViews(recovered);
+ View inflated = cloned.apply(mContext, mContainer);
+
+ assertEquals(
+ index, inflated.getTag(com.android.internal.R.id.notification_action_index_tag));
+ }
+
private class WidgetContainer extends AppWidgetHostView {
int[] mSharedViewIds;
String[] mSharedViewNames;
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
index 9fcb06e..404c99c 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java
@@ -103,6 +103,49 @@
}
@Test
+ public void setMaxHeight() throws Exception {
+ Intent sendIntent = createSendImageIntent();
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+ waitForIdle();
+
+ final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
+ final View resolverList = activity.findViewById(R.id.resolver_list);
+ final int initialResolverHeight = resolverList.getHeight();
+
+ activity.runOnUiThread(() -> {
+ ResolverDrawerLayout layout = (ResolverDrawerLayout)
+ activity.findViewById(
+ R.id.contentPanel);
+ ((ResolverDrawerLayout.LayoutParams) resolverList.getLayoutParams()).maxHeight
+ = initialResolverHeight - 1;
+ // Force a relayout
+ layout.invalidate();
+ layout.requestLayout();
+ });
+ waitForIdle();
+ assertThat("Drawer should be capped at maxHeight",
+ resolverList.getHeight() == (initialResolverHeight - 1));
+
+ activity.runOnUiThread(() -> {
+ ResolverDrawerLayout layout = (ResolverDrawerLayout)
+ activity.findViewById(
+ R.id.contentPanel);
+ ((ResolverDrawerLayout.LayoutParams) resolverList.getLayoutParams()).maxHeight
+ = initialResolverHeight + 1;
+ // Force a relayout
+ layout.invalidate();
+ layout.requestLayout();
+ });
+ waitForIdle();
+ assertThat("Drawer should not change height if its height is less than maxHeight",
+ resolverList.getHeight() == initialResolverHeight);
+ }
+
+ @Test
public void setShowAtTopToTrue() throws Exception {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index de110c8..d9da27c 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -82,6 +82,17 @@
}
/**
+ * Add two Insets.
+ *
+ * @param a The first Insets to add.
+ * @param b The second Insets to add.
+ * @return a + b, i. e. all insets on every side are added together.
+ */
+ public static @NonNull Insets add(@NonNull Insets a, @NonNull Insets b) {
+ return Insets.of(a.left + b.left, a.top + b.top, a.right + b.right, a.bottom + b.bottom);
+ }
+
+ /**
* Two Insets instances are equal iff they belong to the same class and their fields are
* pairwise equal.
*
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index c4dc0ad..40a32f3 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -106,6 +106,20 @@
}
/**
+ * @hide
+ */
+ public Rect(@Nullable Insets r) {
+ if (r == null) {
+ left = top = right = bottom = 0;
+ } else {
+ left = r.left;
+ top = r.top;
+ right = r.right;
+ bottom = r.bottom;
+ }
+ }
+
+ /**
* Returns a copy of {@code r} if {@code r} is not {@code null}, or {@code null} otherwise.
*
* @hide
@@ -418,6 +432,18 @@
}
/**
+ * Insets the rectangle on all sides specified by the dimensions of {@code insets}.
+ * @hide
+ * @param insets The insets to inset the rect by.
+ */
+ public void inset(Insets insets) {
+ left += insets.left;
+ top += insets.top;
+ right -= insets.right;
+ bottom -= insets.bottom;
+ }
+
+ /**
* Insets the rectangle on all sides specified by the insets.
* @hide
* @param left The amount to add from the rectangle's left
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 17d2db71..4a5b61a 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -45,9 +45,6 @@
],
product_variables: {
- device_uses_hwc2: {
- cflags: ["-DUSE_HWC2"],
- },
eng: {
lto: {
never: true,
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index b772e5b..3bee301 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -85,19 +85,18 @@
mUpdateTexImage = false;
sk_sp<SkImage> layerImage;
SkMatrix textureTransform;
- android_dataspace dataSpace;
bool queueEmpty = true;
// If the SurfaceTexture queue is in synchronous mode, need to discard all
// but latest frame. Since we can't tell which mode it is in,
// do this unconditionally.
do {
- layerImage = mSurfaceTexture->dequeueImage(textureTransform, dataSpace, &queueEmpty,
+ layerImage = mSurfaceTexture->dequeueImage(textureTransform, &queueEmpty,
mRenderState);
} while (layerImage.get() && (!queueEmpty));
if (layerImage.get()) {
// force filtration if buffer size != layer size
bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
- updateLayer(forceFilter, textureTransform, dataSpace, layerImage);
+ updateLayer(forceFilter, textureTransform, layerImage);
}
}
@@ -109,12 +108,11 @@
}
void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
- android_dataspace dataspace, const sk_sp<SkImage>& layerImage) {
+ const sk_sp<SkImage>& layerImage) {
mLayer->setBlend(mBlend);
mLayer->setForceFilter(forceFilter);
mLayer->setSize(mWidth, mHeight);
mLayer->getTexTransform() = textureTransform;
- mLayer->setDataSpace(dataspace);
mLayer->setImage(layerImage);
}
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index b2c5131..a91c111 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -95,7 +95,7 @@
void detachSurfaceTexture();
void updateLayer(bool forceFilter, const SkMatrix& textureTransform,
- android_dataspace dataspace, const sk_sp<SkImage>& layerImage);
+ const sk_sp<SkImage>& layerImage);
void destroyLayer();
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index e7ae767..ccbb6c1 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -82,7 +82,6 @@
JankTracker::JankTracker(ProfileDataContainer* globalData, const DisplayInfo& displayInfo) {
mGlobalData = globalData;
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
-#if USE_HWC2
nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset;
// There are two different offset cases. If the offsetDelta is positive
@@ -96,7 +95,6 @@
// return due to the staggering of VSYNC-app & VSYNC-sf.
mDequeueTimeForgiveness = offsetDelta + 4_ms;
}
-#endif
setFrameInterval(frameIntervalNanos);
}
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 32aaa54..d0df200 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -33,7 +33,6 @@
// TODO: This is a violation of Android's typical ref counting, but it
// preserves the old inc/dec ref locations. This should be changed...
incStrong(nullptr);
- buildColorSpaceWithFilter();
renderState.registerLayer(this);
texTransform.setIdentity();
transform.setIdentity();
@@ -43,36 +42,6 @@
mRenderState.unregisterLayer(this);
}
-void Layer::setColorFilter(sk_sp<SkColorFilter> filter) {
- if (filter != mColorFilter) {
- mColorFilter = filter;
- buildColorSpaceWithFilter();
- }
-}
-
-void Layer::setDataSpace(android_dataspace dataspace) {
- if (dataspace != mCurrentDataspace) {
- mCurrentDataspace = dataspace;
- buildColorSpaceWithFilter();
- }
-}
-
-void Layer::buildColorSpaceWithFilter() {
- sk_sp<SkColorFilter> colorSpaceFilter;
- sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(mCurrentDataspace);
- if (colorSpace && !colorSpace->isSRGB()) {
- colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
- }
-
- if (mColorFilter && colorSpaceFilter) {
- mColorSpaceWithFilter = mColorFilter->makeComposed(colorSpaceFilter);
- } else if (colorSpaceFilter) {
- mColorSpaceWithFilter = colorSpaceFilter;
- } else {
- mColorSpaceWithFilter = mColorFilter;
- }
-}
-
void Layer::postDecStrong() {
mRenderState.postDecStrong(this);
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e4f96e9..98600db 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -69,15 +69,9 @@
SkBlendMode getMode() const;
- inline SkColorFilter* getColorFilter() const { return mColorFilter.get(); }
+ inline sk_sp<SkColorFilter> getColorFilter() const { return mColorFilter; }
- void setColorFilter(sk_sp<SkColorFilter> filter);
-
- void setDataSpace(android_dataspace dataspace);
-
- void setColorSpace(sk_sp<SkColorSpace> colorSpace);
-
- inline sk_sp<SkColorFilter> getColorSpaceWithFilter() const { return mColorSpaceWithFilter; }
+ void setColorFilter(sk_sp<SkColorFilter> filter) { mColorFilter = filter; };
inline SkMatrix& getTexTransform() { return texTransform; }
@@ -98,24 +92,12 @@
RenderState& mRenderState;
private:
- void buildColorSpaceWithFilter();
-
/**
* Color filter used to draw this layer. Optional.
*/
sk_sp<SkColorFilter> mColorFilter;
/**
- * Colorspace of the contents of the layer. Optional.
- */
- android_dataspace mCurrentDataspace = HAL_DATASPACE_UNKNOWN;
-
- /**
- * A color filter that is the combination of the mColorFilter and mColorSpace. Optional.
- */
- sk_sp<SkColorFilter> mColorSpaceWithFilter;
-
- /**
* Indicates raster data backing the layer is scaled, requiring filtration.
*/
bool forceFilter = false;
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 80f2b57..2a48837 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -66,13 +66,10 @@
sk_sp<SkColorSpace> colorSpace =
DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace()));
- sk_sp<SkColorFilter> colorSpaceFilter;
- if (colorSpace && !colorSpace->isSRGB()) {
- colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
- }
sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
- reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType);
- return copyImageInto(image, colorSpaceFilter, texTransform, srcRect, bitmap);
+ reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()),
+ kPremul_SkAlphaType, colorSpace);
+ return copyImageInto(image, texTransform, srcRect, bitmap);
}
CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
@@ -83,20 +80,7 @@
transform.loadScale(1, -1, 1);
transform.translate(0, -1);
- // TODO: Try to take and reuse the image inside HW bitmap with "hwBitmap->makeImage".
- // TODO: When this was attempted, it resulted in instability.
- sk_sp<SkColorFilter> colorSpaceFilter;
- sk_sp<SkColorSpace> colorSpace = hwBitmap->info().refColorSpace();
- if (colorSpace && !colorSpace->isSRGB()) {
- colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
- }
- sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
- reinterpret_cast<AHardwareBuffer*>(hwBitmap->graphicBuffer()), kPremul_SkAlphaType);
-
- // HW Bitmap currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888 format
- // and SRGB color space. ImageDecoder can create a new HW Bitmap with non-SRGB color space: for
- // example see android.graphics.cts.BitmapColorSpaceTest#testEncodeP3hardware test.
- return copyImageInto(image, colorSpaceFilter, transform, srcRect, bitmap);
+ return copyImageInto(hwBitmap->makeImage(), transform, srcRect, bitmap);
}
CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
@@ -118,8 +102,7 @@
return copyResult;
}
-CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
- sk_sp<SkColorFilter>& colorSpaceFilter, Matrix4& texTransform,
+CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
const Rect& srcRect, SkBitmap* bitmap) {
if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
mRenderThread.requireGlContext();
@@ -157,11 +140,7 @@
return copyResult;
}
- // See Readback::copyLayerInto for an overview of color space conversion.
- // HW Bitmap are allowed to be in a non-SRGB color space (for example coming from ImageDecoder).
- // For Surface and HW Bitmap readback flows we pass colorSpaceFilter, which does the conversion.
- // TextureView readback is using Layer::setDataSpace, which creates a SkColorFilter internally.
- Layer layer(mRenderThread.renderState(), colorSpaceFilter, 255, SkBlendMode::kSrc);
+ Layer layer(mRenderThread.renderState(), nullptr, 255, SkBlendMode::kSrc);
bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width()) &&
MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
layer.setForceFilter(!disableFilter);
@@ -177,38 +156,6 @@
bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
SkBitmap* bitmap) {
- /*
- * In the past only TextureView readback was setting the temporary surface color space to null.
- * Now all 3 readback flows are drawing into a SkSurface with null color space.
- * At readback there are 3 options to convert the source image color space to the destination
- * color space requested in "bitmap->info().colorSpace()":
- * 1. Set color space for temporary surface render target to null (disables color management),
- * colorspace tag from source SkImage is ignored by Skia,
- * convert SkImage to SRGB at draw time with SkColorFilter/SkToSRGBColorFilter,
- * do a readback from temporary SkSurface to a temporary SRGB SkBitmap "bitmap2",
- * read back from SRGB "bitmap2" into non-SRGB "bitmap" which will do a CPU color conversion.
- *
- * 2. Set color space for temporary surface render target to SRGB (not nullptr),
- * colorspace tag on the source SkImage is used by Skia to enable conversion,
- * convert SkImage to SRGB at draw time with drawImage (no filters),
- * do a readback from temporary SkSurface, which will do a color conversion from SRGB to
- * bitmap->info().colorSpace() on the CPU.
- *
- * 3. Set color space for temporary surface render target to bitmap->info().colorSpace(),
- * colorspace tag on the source SkImage is used by Skia to enable conversion,
- * convert SkImage to bitmap->info().colorSpace() at draw time with drawImage (no filters),
- * do a readback from SkSurface, which will not do any color conversion, because
- * surface was created with the same color space as the "bitmap".
- *
- * Option 1 is used for all readback flows.
- * Options 2 and 3 are new, because skia added support for non-SRGB render targets without
- * linear blending.
- * TODO: evaluate if options 2 or 3 for color space conversion are better.
- */
-
- // drop the colorSpace from the temporary surface.
- SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
-
/* This intermediate surface is present to work around a bug in SwiftShader that
* prevents us from reading the contents of the layer's texture directly. The
* workaround involves first rendering that texture into an intermediate buffer and
@@ -217,70 +164,44 @@
* with reading incorrect data from EGLImage backed SkImage (likely a driver bug).
*/
sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
- SkBudgeted::kYes, surfaceInfo);
+ SkBudgeted::kYes, bitmap->info());
+ // if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we
+ // attempt to do the intermediate rendering step in 8888
if (!tmpSurface.get()) {
- surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
+ SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
- surfaceInfo);
+ tmpInfo);
if (!tmpSurface.get()) {
- ALOGW("Unable to readback GPU contents into the provided bitmap");
+ ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap");
return false;
}
}
- if (skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
- tmpSurface->getCanvas(), layer, srcRect, dstRect,
- false)) {
- // If bitmap->info().colorSpace() is non-SRGB, convert the data from SRGB to non-SRGB on
- // CPU. We can't just pass bitmap->info() to SkSurface::readPixels, because "tmpSurface" has
- // disabled color conversion.
- SkColorSpace* destColorSpace = bitmap->info().colorSpace();
- SkBitmap tempSRGBBitmap;
- SkBitmap tmpN32Bitmap;
- SkBitmap* bitmapInSRGB;
- if (destColorSpace && !destColorSpace->isSRGB()) {
- tempSRGBBitmap.allocPixels(bitmap->info().makeColorSpace(SkColorSpace::MakeSRGB()));
- bitmapInSRGB = &tempSRGBBitmap; // Need to convert latter from SRGB to non-SRGB.
- } else {
- bitmapInSRGB = bitmap; // No need for color conversion - write directly into output.
- }
- bool success = false;
+ if (!skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
+ tmpSurface->getCanvas(), layer, srcRect, dstRect,
+ false)) {
+ ALOGW("Unable to draw content from GPU into the provided bitmap");
+ return false;
+ }
- // TODO: does any of the readbacks below clamp F16 exSRGB?
- // Readback into a SRGB SkBitmap.
- if (tmpSurface->readPixels(bitmapInSRGB->info(), bitmapInSRGB->getPixels(),
- bitmapInSRGB->rowBytes(), 0, 0)) {
- success = true;
- } else {
- // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
- // 8888 and then convert that into the destination format before giving up.
- SkImageInfo bitmapInfo =
- SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType(),
- SkColorSpace::MakeSRGB());
- if (tmpN32Bitmap.tryAllocPixels(bitmapInfo) &&
- tmpSurface->readPixels(bitmapInfo, tmpN32Bitmap.getPixels(),
- tmpN32Bitmap.rowBytes(), 0, 0)) {
- success = true;
- bitmapInSRGB = &tmpN32Bitmap;
- }
- }
-
- if (success) {
- if (bitmapInSRGB != bitmap) {
- // Convert from SRGB to non-SRGB color space if needed. Convert from N32 to
- // destination bitmap color format if needed.
- if (!bitmapInSRGB->readPixels(bitmap->info(), bitmap->getPixels(),
- bitmap->rowBytes(), 0, 0)) {
- return false;
- }
- }
- bitmap->notifyPixelsChanged();
- return true;
+ if (!tmpSurface->readPixels(*bitmap, 0, 0)) {
+ // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
+ // 8888 and then convert that into the destination format before giving up.
+ SkBitmap tmpBitmap;
+ SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType);
+ if (bitmap->info().colorType() == SkColorType::kN32_SkColorType ||
+ !tmpBitmap.tryAllocPixels(tmpInfo) ||
+ !tmpSurface->readPixels(tmpBitmap, 0, 0) ||
+ !tmpBitmap.readPixels(bitmap->info(), bitmap->getPixels(),
+ bitmap->rowBytes(), 0, 0)) {
+ ALOGW("Unable to convert content into the provided bitmap");
+ return false;
}
}
- return false;
+ bitmap->notifyPixelsChanged();
+ return true;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index d9e10ce..e86a813 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -54,8 +54,8 @@
CopyResult copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
private:
- CopyResult copyImageInto(const sk_sp<SkImage>& image, sk_sp<SkColorFilter>& colorSpaceFilter,
- Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap);
+ CopyResult copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform,
+ const Rect& srcRect, SkBitmap* bitmap);
bool copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
SkBitmap* bitmap);
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9a15ff2..ba34384 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -27,7 +27,6 @@
#include <SkAnimatedImage.h>
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
-#include <SkColorSpaceXformCanvas.h>
#include <SkDeque.h>
#include <SkDrawable.h>
#include <SkFont.h>
@@ -61,19 +60,8 @@
SkiaCanvas::SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {}
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
- sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
- mCanvasOwned =
- std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- if (cs.get() == nullptr || cs->isSRGB()) {
- mCanvas = mCanvasOwned.get();
- } else {
- /** The wrapper is needed if we are drawing into a non-sRGB destination, since
- * we need to transform all colors (not just bitmaps via filters) into the
- * destination's colorspace.
- */
- mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), std::move(cs));
- mCanvas = mCanvasWrapper.get();
- }
+ mCanvasOwned = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
+ mCanvas = mCanvasOwned.get();
}
SkiaCanvas::~SkiaCanvas() {}
@@ -82,7 +70,6 @@
if (mCanvas != skiaCanvas) {
mCanvas = skiaCanvas;
mCanvasOwned.reset();
- mCanvasWrapper.reset();
}
mSaveStack.reset(nullptr);
}
@@ -92,18 +79,9 @@
// ----------------------------------------------------------------------------
void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
- sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
- std::unique_ptr<SkCanvas> newCanvas =
- std::unique_ptr<SkCanvas>(new SkCanvas(bitmap, SkCanvas::ColorBehavior::kLegacy));
- std::unique_ptr<SkCanvas> newCanvasWrapper;
- if (cs.get() != nullptr && !cs->isSRGB()) {
- newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(), std::move(cs));
- }
-
// deletes the previously owned canvas (if any)
- mCanvasOwned = std::move(newCanvas);
- mCanvasWrapper = std::move(newCanvasWrapper);
- mCanvas = mCanvasWrapper ? mCanvasWrapper.get() : mCanvasOwned.get();
+ mCanvasOwned.reset(new SkCanvas(bitmap));
+ mCanvas = mCanvasOwned.get();
// clean up the old save stack
mSaveStack.reset(nullptr);
@@ -548,40 +526,14 @@
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
-SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint,
- sk_sp<SkColorFilter> colorSpaceFilter) const {
- /* We don't apply the colorSpace filter if this canvas is already wrapped with
- * a SkColorSpaceXformCanvas since it already takes care of converting the
- * contents of the bitmap into the appropriate colorspace. The mCanvasWrapper
- * should only be used if this canvas is backed by a surface/bitmap that is known
- * to have a non-sRGB colorspace.
- */
- if (!mCanvasWrapper && colorSpaceFilter) {
- SkPaint& tmpPaint = paint.writeable();
- if (tmpPaint.getColorFilter()) {
- tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(),
- std::move(colorSpaceFilter)));
- LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
- } else {
- tmpPaint.setColorFilter(std::move(colorSpaceFilter));
- }
- }
- return filterPaint(std::move(paint));
-}
-
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
+ mCanvas->drawImage(bitmap.makeImage(), left, top, filterPaint(paint));
}
void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
SkAutoCanvasRestore acr(mCanvas, true);
mCanvas->concat(matrix);
-
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
+ mCanvas->drawImage(bitmap.makeImage(), 0, 0, filterPaint(paint));
}
void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
@@ -590,9 +542,7 @@
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
+ mCanvas->drawImageRect(bitmap.makeImage(), srcRect, dstRect, filterPaint(paint),
SkCanvas::kFast_SrcRectConstraint);
}
@@ -674,13 +624,9 @@
PaintCoW paintCoW(paint);
SkPaint& tmpPaint = paintCoW.writeable();
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ sk_sp<SkImage> image = bitmap.makeImage();
sk_sp<SkShader> shader =
image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
- if (colorFilter) {
- shader = shader->makeWithColorFilter(std::move(colorFilter));
- }
tmpPaint.setShader(std::move(shader));
mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate,
@@ -711,10 +657,7 @@
lattice.fBounds = nullptr;
SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mCanvas->drawImageLattice(image.get(), lattice, dst,
- filterBitmap(paint, std::move(colorFilter)));
+ mCanvas->drawImageLattice(bitmap.makeImage().get(), lattice, dst, filterPaint(paint));
}
double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 3a877cf..24d9c08 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -232,7 +232,6 @@
class Clip;
- std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas
std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated
SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us
// unless it is the same as mCanvasOwned.get()
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 75a6e72..6c77f9e 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -32,7 +32,6 @@
#include <SkCanvas.h>
#include <SkImagePriv.h>
-#include <SkToSRGBColorFilter.h>
#include <SkHighContrastFilter.h>
#include <limits>
@@ -287,14 +286,8 @@
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
if (isHardware()) {
- outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
- info().colorType(), info().alphaType(), nullptr));
+ outBitmap->allocPixels(mInfo);
uirenderer::renderthread::RenderProxy::copyHWBitmapInto(this, outBitmap);
- if (mInfo.colorSpace()) {
- sk_sp<SkPixelRef> pixelRef = sk_ref_sp(outBitmap->pixelRef());
- outBitmap->setInfo(mInfo);
- outBitmap->setPixelRef(std::move(pixelRef), 0, 0);
- }
return;
}
outBitmap->setInfo(mInfo, rowBytes());
@@ -313,7 +306,7 @@
return nullptr;
}
-sk_sp<SkImage> Bitmap::makeImage(sk_sp<SkColorFilter>* outputColorFilter) {
+sk_sp<SkImage> Bitmap::makeImage() {
sk_sp<SkImage> image = mImage;
if (!image) {
SkASSERT(!isHardware());
@@ -325,9 +318,6 @@
// TODO: refactor Bitmap to not derive from SkPixelRef, which would allow caching here.
image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
}
- if (image->colorSpace() != nullptr && !image->colorSpace()->isSRGB()) {
- *outputColorFilter = SkToSRGBColorFilter::Make(image->refColorSpace());
- }
return image;
}
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 238c764..d446377 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -105,14 +105,8 @@
* Creates or returns a cached SkImage and is safe to be invoked from either
* the UI or RenderThread.
*
- * @param outputColorFilter is a required param that will be populated by
- * this function if the bitmap's colorspace is not sRGB. If populated the
- * filter will convert colors from the bitmaps colorspace into sRGB. It
- * is the callers responsibility to use this colorFilter when drawing
- * this image into any destination that is presumed to be sRGB (i.e. a
- * buffer that has no colorspace defined).
*/
- sk_sp<SkImage> makeImage(sk_sp<SkColorFilter>* outputColorFilter);
+ sk_sp<SkImage> makeImage();
static BitmapPalette computePalette(const SkImageInfo& info, const void* addr, size_t rowBytes);
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 0cd6406..9b408fb 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -89,7 +89,7 @@
SkPaint paint;
paint.setAlpha(layer->getAlpha());
paint.setBlendMode(layer->getMode());
- paint.setColorFilter(layer->getColorSpaceWithFilter());
+ paint.setColorFilter(layer->getColorFilter());
const bool nonIdentityMatrix = !matrix.isIdentity();
if (nonIdentityMatrix) {
canvas->save();
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 6ae5999..142bca9 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -97,7 +97,7 @@
SkASSERT(mRenderThread.getGrContext() != nullptr);
sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(
mRenderThread.getGrContext(), backendRT, kBottomLeft_GrSurfaceOrigin, colorType,
- nullptr, &props));
+ mSurfaceColorSpace, &props));
SkiaPipeline::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
@@ -176,6 +176,7 @@
} else if (colorMode == ColorMode::WideColorGamut) {
mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
}
+ mSurfaceColorSpace = SkColorSpace::MakeSRGB();
if (mEglSurface != EGL_NO_SURFACE) {
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 2dfe7c7..7a255c1 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -169,7 +169,7 @@
if (!layer || layer->width() != surfaceWidth || layer->height() != surfaceHeight) {
SkImageInfo info;
info = SkImageInfo::Make(surfaceWidth, surfaceHeight, getSurfaceColorType(),
- kPremul_SkAlphaType);
+ kPremul_SkAlphaType, getSurfaceColorSpace());
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
SkASSERT(mRenderThread.getGrContext() != nullptr);
node->setLayerSurface(SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
@@ -204,8 +204,7 @@
GrContext* context = thread.getGrContext();
if (context) {
ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
- sk_sp<SkColorFilter> colorFilter;
- auto image = bitmap->makeImage(&colorFilter);
+ auto image = bitmap->makeImage();
if (image.get() && !bitmap->isHardware()) {
SkImage_pinAsTexture(image.get(), context);
SkImage_unpinAsTexture(image.get(), context);
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 45022e7..f5de1c8 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -179,9 +179,8 @@
}
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mRecorder.drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)), bitmap.palette());
+ sk_sp<SkImage> image = bitmap.makeImage();
+ mRecorder.drawImage(image, left, top, filterPaint(paint), bitmap.palette());
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
// when this function ends.
@@ -194,9 +193,8 @@
SkAutoCanvasRestore acr(&mRecorder, true);
concat(matrix);
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mRecorder.drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)), bitmap.palette());
+ sk_sp<SkImage> image = bitmap.makeImage();
+ mRecorder.drawImage(image, 0, 0, filterPaint(paint), bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
@@ -208,9 +206,8 @@
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
- mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
+ sk_sp<SkImage> image = bitmap.makeImage();
+ mRecorder.drawImageRect(image, srcRect, dstRect, filterPaint(paint),
SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
!dstRect.isEmpty()) {
@@ -247,10 +244,9 @@
if (!filteredPaint || filteredPaint->getFilterQuality() != kLow_SkFilterQuality) {
filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
}
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ sk_sp<SkImage> image = bitmap.makeImage();
mRecorder.drawImageLattice(image, lattice, dst,
- filterBitmap(std::move(filteredPaint), std::move(colorFilter)),
+ filterPaint(std::move(filteredPaint)),
bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp
index 9ffccfb..15aec9f 100644
--- a/libs/hwui/surfacetexture/ImageConsumer.cpp
+++ b/libs/hwui/surfacetexture/ImageConsumer.cpp
@@ -22,6 +22,7 @@
#include "renderthread/EglManager.h"
#include "renderthread/RenderThread.h"
#include "renderthread/VulkanManager.h"
+#include "utils/Color.h"
// Macro for including the SurfaceTexture name in log messages
#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
@@ -44,13 +45,16 @@
mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
}
-void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer) {
- if (!mImage.get()) {
+void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
+ android_dataspace dataspace) {
+ if (!mImage.get() || dataspace != mDataspace) {
mImage = graphicBuffer.get()
? SkImage::MakeFromAHardwareBuffer(
reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
- kPremul_SkAlphaType)
+ kPremul_SkAlphaType,
+ uirenderer::DataSpaceToColorSpace(dataspace))
: nullptr;
+ mDataspace = dataspace;
}
}
@@ -66,7 +70,7 @@
int slot = st.mCurrentTexture;
if (slot != BufferItem::INVALID_BUFFER_SLOT) {
*queueEmpty = true;
- mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+ mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
return mImageSlots[slot].mImage;
}
}
@@ -145,7 +149,7 @@
st.computeCurrentTransformMatrixLocked();
*queueEmpty = false;
- mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer);
+ mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace);
return mImageSlots[slot].mImage;
}
diff --git a/libs/hwui/surfacetexture/ImageConsumer.h b/libs/hwui/surfacetexture/ImageConsumer.h
index 31ee8db..5bab0ef5 100644
--- a/libs/hwui/surfacetexture/ImageConsumer.h
+++ b/libs/hwui/surfacetexture/ImageConsumer.h
@@ -68,18 +68,21 @@
* ImageConsumer maintains about a BufferQueue buffer slot.
*/
struct ImageSlot {
- ImageSlot() : mEglFence(EGL_NO_SYNC_KHR) {}
+ ImageSlot() : mDataspace(HAL_DATASPACE_UNKNOWN), mEglFence(EGL_NO_SYNC_KHR) {}
// mImage is the SkImage created from mGraphicBuffer.
sk_sp<SkImage> mImage;
+ // the dataspace associated with the current image
+ android_dataspace mDataspace;
+
/**
* mEglFence is the EGL sync object that must signal before the buffer
* associated with this buffer slot may be dequeued.
*/
EGLSyncKHR mEglFence;
- void createIfNeeded(sp<GraphicBuffer> graphicBuffer);
+ void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace);
};
/**
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.cpp b/libs/hwui/surfacetexture/SurfaceTexture.cpp
index 4bff715..90f8912 100644
--- a/libs/hwui/surfacetexture/SurfaceTexture.cpp
+++ b/libs/hwui/surfacetexture/SurfaceTexture.cpp
@@ -470,8 +470,7 @@
ConsumerBase::dumpLocked(result, prefix);
}
-sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
- bool* queueEmpty,
+sk_sp<SkImage> SurfaceTexture::dequeueImage(SkMatrix& transformMatrix, bool* queueEmpty,
uirenderer::RenderState& renderState) {
Mutex::Autolock _l(mMutex);
@@ -488,7 +487,6 @@
auto image = mImageConsumer.dequeueImage(queueEmpty, *this, renderState);
if (image.get()) {
uirenderer::mat4(mCurrentTransformMatrix).copyTo(transformMatrix);
- dataSpace = mCurrentDataSpace;
}
return image;
}
diff --git a/libs/hwui/surfacetexture/SurfaceTexture.h b/libs/hwui/surfacetexture/SurfaceTexture.h
index db392a9..96afd82 100644
--- a/libs/hwui/surfacetexture/SurfaceTexture.h
+++ b/libs/hwui/surfacetexture/SurfaceTexture.h
@@ -258,8 +258,8 @@
*/
status_t attachToContext(uint32_t tex);
- sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, android_dataspace& dataSpace,
- bool* queueEmpty, uirenderer::RenderState& renderState);
+ sk_sp<SkImage> dequeueImage(SkMatrix& transformMatrix, bool* queueEmpty,
+ uirenderer::RenderState& renderState);
/**
* attachToView attaches a SurfaceTexture that is currently in the
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 66b9b85..8a1bc4d 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -72,9 +72,7 @@
layerUpdater->setTransform(&transform);
// updateLayer so it's ready to draw
- SkMatrix identity;
- identity.setIdentity();
- layerUpdater->updateLayer(true, identity, HAL_DATASPACE_UNKNOWN, nullptr);
+ layerUpdater->updateLayer(true, SkMatrix::I(), nullptr);
return layerUpdater;
}
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index 15039b5..ad11a1d 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -44,8 +44,7 @@
});
SkPaint paint;
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = hwuiBitmap->makeImage(&colorFilter);
+ sk_sp<SkImage> image = hwuiBitmap->makeImage();
sk_sp<SkShader> repeatShader =
image->makeShader(SkShader::TileMode::kRepeat_TileMode,
SkShader::TileMode::kRepeat_TileMode, nullptr);
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index f137562..448408d 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -72,8 +72,7 @@
void doFrame(int frameNr) override {}
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
- sk_sp<SkColorFilter> colorFilter;
- sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
+ sk_sp<SkImage> image = bitmap.makeImage();
return image->makeShader(SkShader::TileMode::kClamp_TileMode,
SkShader::TileMode::kClamp_TileMode);
}
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index c235715..210fced 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -54,8 +54,7 @@
// create an image and pin it so that we have something with a unique key in the cache
sk_sp<Bitmap> bitmap =
Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(displayInfo.w, displayInfo.h));
- sk_sp<SkColorFilter> filter;
- sk_sp<SkImage> image = bitmap->makeImage(&filter);
+ sk_sp<SkImage> image = bitmap->makeImage();
ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
// attempt to trim all memory while we still hold strong refs
diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
index 6c8775b..a686979 100644
--- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
+++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp
@@ -43,7 +43,7 @@
SkBitmap bitmap;
bitmap.allocN32Pixels(16, 16);
sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap);
- layerUpdater->updateLayer(true, scaledMatrix, HAL_DATASPACE_UNKNOWN, layerImage);
+ layerUpdater->updateLayer(true, scaledMatrix, layerImage);
// the backing layer should now have all the properties applied.
EXPECT_EQ(100u, layerUpdater->backingLayer()->getWidth());
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index 634ceff..f3a7648 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -53,12 +53,12 @@
adobeBitmap->getSkBitmap(&adobeSkBitmap);
*adobeSkBitmap.getAddr32(0, 0) = 0xFF0000F0; // Opaque, almost fully-red
- SkImageInfo info = adobeInfo.makeColorSpace(nullptr);
+ SkImageInfo info = adobeInfo.makeColorSpace(SkColorSpace::MakeSRGB());
sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(info);
SkBitmap skBitmap;
bitmap->getSkBitmap(&skBitmap);
- // Create a software canvas.
+ // Create a software sRGB canvas.
SkiaCanvas canvas(skBitmap);
canvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
// The result should be fully red, since we convert to sRGB at draw time.
@@ -77,7 +77,7 @@
picCanvas.drawBitmap(*adobeBitmap, 0, 0, nullptr);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
- // Playback to an software canvas. The result should be fully red.
+ // Playback to a software sRGB canvas. The result should be fully red.
canvas.asSkCanvas()->drawPicture(picture);
ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
}
diff --git a/libs/services/include/android/os/StatsLogEventWrapper.h b/libs/services/include/android/os/StatsLogEventWrapper.h
index f60c338..8de2ab4 100644
--- a/libs/services/include/android/os/StatsLogEventWrapper.h
+++ b/libs/services/include/android/os/StatsLogEventWrapper.h
@@ -82,6 +82,11 @@
STATS_LOG_VALUE_TYPE type;
};
+struct WorkChain {
+ std::vector<int32_t> uids;
+ std::vector<std::string> tags;
+};
+
// Represents a parcelable object. Only used to send data from Android OS to statsd.
class StatsLogEventWrapper : public android::Parcelable {
public:
@@ -99,7 +104,9 @@
int64_t getWallClockTimeNs() const { return mWallClockTimeNs; }
- std::vector<StatsLogValue> getElements() const { return mElements; }
+ const std::vector<StatsLogValue>& getElements() const { return mElements; }
+
+ const std::vector<WorkChain>& getWorkChains() const { return mWorkChains; }
private:
int mTagId;
@@ -109,6 +116,8 @@
int64_t mWallClockTimeNs;
std::vector<StatsLogValue> mElements;
+
+ std::vector<WorkChain> mWorkChains;
};
} // Namespace os
} // Namespace android
diff --git a/libs/services/src/os/StatsLogEventWrapper.cpp b/libs/services/src/os/StatsLogEventWrapper.cpp
index 04c4629..f6dfdef 100644
--- a/libs/services/src/os/StatsLogEventWrapper.cpp
+++ b/libs/services/src/os/StatsLogEventWrapper.cpp
@@ -58,6 +58,31 @@
ALOGE("statsd could not read wall clock time from parcel");
return res;
}
+ int numWorkChain = 0;
+ if ((res = in->readInt32(&numWorkChain)) != OK) {
+ ALOGE("statsd could not read number of work chains from parcel");
+ return res;
+ }
+ if (numWorkChain > 0) {
+ for (int i = 0; i < numWorkChain; i++) {
+ int numNodes = 0;
+ if ((res = in->readInt32(&numNodes)) != OK) {
+ ALOGE(
+ "statsd could not read number of nodes in work chain from parcel");
+ return res;
+ }
+ if (numNodes == 0) {
+ ALOGE("empty work chain");
+ return BAD_VALUE;
+ }
+ WorkChain wc;
+ for (int j = 0; j < numNodes; j++) {
+ wc.uids.push_back(in->readInt32());
+ wc.tags.push_back(std::string(String8(in->readString16()).string()));
+ }
+ mWorkChains.push_back(wc);
+ }
+ }
int dataSize = 0;
if ((res = in->readInt32(&dataSize)) != OK) {
ALOGE("statsd could not read data size from parcel");
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 1ebe059..082a375 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -924,6 +924,15 @@
public static native int setSurroundFormatEnabled(int audioFormat, boolean enabled);
+ /**
+ * Communicate UID of active assistant to audio policy service.
+ */
+ public static native int setAssistantUid(int uid);
+ /**
+ * Communicate UIDs of active accessibility services to audio policy service.
+ */
+ public static native int setA11yServicesUids(int[] uids);
+
// Items shared with audio service
/**
diff --git a/media/java/android/media/CallbackDataSourceDesc.java b/media/java/android/media/CallbackDataSourceDesc.java
index 82273da..0e8e6ce 100644
--- a/media/java/android/media/CallbackDataSourceDesc.java
+++ b/media/java/android/media/CallbackDataSourceDesc.java
@@ -20,27 +20,29 @@
/**
* @hide
- * Structure for file data source descriptor.
+ * Structure of data source descriptor for sources using callback.
*
- * Used by {@link MediaPlayer2#setDataSource(CallbackDataSourceDesc)}
+ * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
* to set data source for playback.
*
* <p>Users should use {@link Builder} to create {@link CallbackDataSourceDesc}.
*
*/
public class CallbackDataSourceDesc extends DataSourceDesc {
- private Media2DataSource mMedia2DataSource;
+ private DataSourceCallback mDataSourceCallback;
private CallbackDataSourceDesc() {
}
/**
- * Return the Media2DataSource of this data source.
+ * Return the DataSourceCallback of this data source.
* It's meaningful only when {@code getType} returns {@link #TYPE_CALLBACK}.
- * @return the Media2DataSource of this data source
+ * @return the DataSourceCallback of this data source
*/
- public Media2DataSource getMedia2DataSource() {
- return mMedia2DataSource;
+ public DataSourceCallback getDataSourceCallback() {
+ return mDataSourceCallback;
}
/**
@@ -58,7 +60,7 @@
* </pre>
*/
public static class Builder extends BuilderBase<Builder> {
- private Media2DataSource mMedia2DataSource;
+ private DataSourceCallback mDataSourceCallback;
/**
* Constructs a new Builder with the defaults.
@@ -77,7 +79,7 @@
if (dsd == null) {
return; // use default
}
- mMedia2DataSource = dsd.mMedia2DataSource;
+ mDataSourceCallback = dsd.mDataSourceCallback;
}
/**
@@ -90,21 +92,21 @@
public @NonNull CallbackDataSourceDesc build() {
CallbackDataSourceDesc dsd = new CallbackDataSourceDesc();
super.build(dsd);
- dsd.mMedia2DataSource = mMedia2DataSource;
+ dsd.mDataSourceCallback = mDataSourceCallback;
return dsd;
}
/**
- * Sets the data source (Media2DataSource) to use.
+ * Sets the data source (DataSourceCallback) to use.
*
- * @param m2ds the Media2DataSource for the media to play
+ * @param dscb the DataSourceCallback for the media to play
* @return the same Builder instance.
- * @throws NullPointerException if m2ds is null.
+ * @throws NullPointerException if dscb is null.
*/
- public @NonNull Builder setDataSource(@NonNull Media2DataSource m2ds) {
- Media2Utils.checkArgument(m2ds != null, "data source cannot be null.");
- mMedia2DataSource = m2ds;
+ public @NonNull Builder setDataSource(@NonNull DataSourceCallback dscb) {
+ Media2Utils.checkArgument(dscb != null, "data source cannot be null.");
+ mDataSourceCallback = dscb;
return this;
}
}
diff --git a/media/java/android/media/Media2DataSource.java b/media/java/android/media/DataSourceCallback.java
similarity index 89%
rename from media/java/android/media/Media2DataSource.java
rename to media/java/android/media/DataSourceCallback.java
index 08df632..9b27baf 100644
--- a/media/java/android/media/Media2DataSource.java
+++ b/media/java/android/media/DataSourceCallback.java
@@ -27,12 +27,12 @@
*
* <p class="note">Methods of this interface may be called on multiple different
* threads. There will be a thread synchronization point between each call to ensure that
- * modifications to the state of your Media2DataSource are visible to future calls. This means
+ * modifications to the state of your DataSourceCallback are visible to future calls. This means
* you don't need to do your own synchronization unless you're modifying the
- * Media2DataSource from another thread while it's being used by the framework.</p>
+ * DataSourceCallback from another thread while it's being used by the framework.</p>
*
*/
-public abstract class Media2DataSource implements Closeable {
+public abstract class DataSourceCallback implements Closeable {
/**
* Called to request data from the given position.
*
diff --git a/media/java/android/media/DataSourceDesc.java b/media/java/android/media/DataSourceDesc.java
index 360af34..702034e9 100644
--- a/media/java/android/media/DataSourceDesc.java
+++ b/media/java/android/media/DataSourceDesc.java
@@ -22,7 +22,9 @@
* @hide
* Base class of data source descriptor.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)}
+ * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
* to set data source for playback.
*
* <p>Users should use subclasses' builder to change {@link DataSourceDesc}.
@@ -30,7 +32,7 @@
*/
public class DataSourceDesc {
// intentionally less than long.MAX_VALUE
- public static final long LONG_MAX = 0x7ffffffffffffffL;
+ static final long LONG_MAX = 0x7ffffffffffffffL;
// keep consistent with native code
public static final long LONG_MAX_TIME_MS = LONG_MAX / 1000;
@@ -46,6 +48,19 @@
}
/**
+ * Releases the resources held by this {@code DataSourceDesc} object.
+ */
+ void close() {
+ }
+
+ // Have to declare protected for finalize() since it is protected
+ // in the base class Object.
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ }
+
+ /**
* Return the media Id of data source.
* @return the media Id of data source
*/
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index b96a585..01a0cb6 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,7 +16,10 @@
package android.media;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
@@ -26,12 +29,14 @@
import android.system.OsConstants;
import android.util.Log;
import android.util.Pair;
-import android.annotation.IntDef;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
import java.io.DataInput;
+import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileDescriptor;
@@ -42,14 +47,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Arrays;
-import java.util.LinkedList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -58,11 +63,6 @@
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
/**
* This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
@@ -583,11 +583,19 @@
private static class ExifAttribute {
public final int format;
public final int numberOfComponents;
+ public final long bytesOffset;
public final byte[] bytes;
+ public static final long BYTES_OFFSET_UNKNOWN = -1;
+
private ExifAttribute(int format, int numberOfComponents, byte[] bytes) {
+ this(format, numberOfComponents, BYTES_OFFSET_UNKNOWN, bytes);
+ }
+
+ private ExifAttribute(int format, int numberOfComponents, long bytesOffset, byte[] bytes) {
this.format = format;
this.numberOfComponents = numberOfComponents;
+ this.bytesOffset = bytesOffset;
this.bytes = bytes;
}
@@ -1318,6 +1326,7 @@
private int mOrfThumbnailLength;
private int mRw2JpgFromRawOffset;
private boolean mIsSupportedFile;
+ private boolean mModified;
// Pattern to check non zero timestamp
private static final Pattern sNonZeroTimePattern = Pattern.compile(".*[1-9].*");
@@ -1328,7 +1337,14 @@
/**
* Reads Exif tags from the specified image file.
*/
- public ExifInterface(String filename) throws IOException {
+ public ExifInterface(@NonNull File file) throws IOException {
+ this(file.getAbsolutePath());
+ }
+
+ /**
+ * Reads Exif tags from the specified image file.
+ */
+ public ExifInterface(@NonNull String filename) throws IOException {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}
@@ -1354,7 +1370,7 @@
* for writable and seekable file descriptors only. This constructor will not rewind the offset
* of the given file descriptor. Developers should close the file descriptor after use.
*/
- public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
+ public ExifInterface(@NonNull FileDescriptor fileDescriptor) throws IOException {
if (fileDescriptor == null) {
throw new IllegalArgumentException("fileDescriptor cannot be null");
}
@@ -1388,7 +1404,7 @@
* for input streams. The given input stream will proceed its current position. Developers
* should close the input stream after use.
*/
- public ExifInterface(InputStream inputStream) throws IOException {
+ public ExifInterface(@NonNull InputStream inputStream) throws IOException {
if (inputStream == null) {
throw new IllegalArgumentException("inputStream cannot be null");
}
@@ -1414,7 +1430,7 @@
*
* @param tag the name of the tag.
*/
- private ExifAttribute getExifAttribute(String tag) {
+ private @Nullable ExifAttribute getExifAttribute(@NonNull String tag) {
// Retrieves all tag groups. The value from primary image tag group has a higher priority
// than the value from the thumbnail tag group if there are more than one candidates.
for (int i = 0; i < EXIF_TAGS.length; ++i) {
@@ -1432,7 +1448,7 @@
*
* @param tag the name of the tag.
*/
- public String getAttribute(String tag) {
+ public @Nullable String getAttribute(@NonNull String tag) {
ExifAttribute attribute = getExifAttribute(tag);
if (attribute != null) {
if (!sTagSetForCompatibility.contains(tag)) {
@@ -1470,7 +1486,7 @@
* @param tag the name of the tag.
* @param defaultValue the value to return if the tag is not available.
*/
- public int getAttributeInt(String tag, int defaultValue) {
+ public int getAttributeInt(@NonNull String tag, int defaultValue) {
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1491,7 +1507,7 @@
* @param tag the name of the tag.
* @param defaultValue the value to return if the tag is not available.
*/
- public double getAttributeDouble(String tag, double defaultValue) {
+ public double getAttributeDouble(@NonNull String tag, double defaultValue) {
ExifAttribute exifAttribute = getExifAttribute(tag);
if (exifAttribute == null) {
return defaultValue;
@@ -1510,7 +1526,7 @@
* @param tag the name of the tag.
* @param value the value of the tag.
*/
- public void setAttribute(String tag, String value) {
+ public void setAttribute(@NonNull String tag, @Nullable String value) {
// Convert the given value to rational values for backwards compatibility.
if (value != null && sTagSetForCompatibility.contains(tag)) {
if (tag.equals(TAG_GPS_TIMESTAMP)) {
@@ -1772,12 +1788,18 @@
}
/**
- * Save the tag data into the original image file. This is expensive because it involves
- * copying all the data from one file to another and deleting the old file and renaming the
- * other. It's best to use {@link #setAttribute(String,String)} to set all attributes to write
- * and make a single call rather than multiple calls for each attribute.
+ * Save the tag data into the original image file. This is expensive because
+ * it involves copying all the data from one file to another and deleting
+ * the old file and renaming the other. It's best to use
+ * {@link #setAttribute(String,String)} to set all attributes to write and
+ * make a single call rather than multiple calls for each attribute.
* <p>
* This method is only supported for JPEG files.
+ * <p class="note">
+ * Note: after calling this method, any attempts to obtain range information
+ * from {@link #getAttributeRange(String)} or {@link #getThumbnailRange()}
+ * will throw {@link IllegalStateException}, since the offsets may have
+ * changed in the newly written file.
* </p>
*/
public void saveAttributes() throws IOException {
@@ -1789,6 +1811,10 @@
"ExifInterface does not support saving attributes for the current input.");
}
+ // Remember the fact that we've changed the file on disk from what was
+ // originally parsed, meaning we can't answer range questions
+ mModified = true;
+
// Keep the thumbnail in memory
mThumbnailBytes = getThumbnail();
@@ -1849,6 +1875,15 @@
}
/**
+ * Returns true if the image file has the given attribute defined.
+ *
+ * @param tag the name of the tag.
+ */
+ public boolean hasAttribute(String tag) {
+ return (getExifAttribute(tag) != null);
+ }
+
+ /**
* Returns the JPEG compressed thumbnail inside the image file, or {@code null} if there is no
* JPEG compressed thumbnail.
* The returned data can be decoded using
@@ -1968,17 +2003,45 @@
*
* @return two-element array, the offset in the first value, and length in
* the second, or {@code null} if no thumbnail was found.
+ * @throws IllegalStateException if {@link #saveAttributes()} has been
+ * called since the underlying file was initially parsed, since
+ * that means offsets may have changed.
*/
- public long[] getThumbnailRange() {
- if (!mHasThumbnail) {
- return null;
+ public @Nullable long[] getThumbnailRange() {
+ if (mModified) {
+ throw new IllegalStateException(
+ "The underlying file has been modified since being parsed");
}
- long[] range = new long[2];
- range[0] = mThumbnailOffset;
- range[1] = mThumbnailLength;
+ if (mHasThumbnail) {
+ return new long[] { mThumbnailOffset, mThumbnailLength };
+ } else {
+ return null;
+ }
+ }
- return range;
+ /**
+ * Returns the offset and length of the requested tag inside the image file,
+ * or {@code null} if the tag is not contained.
+ *
+ * @return two-element array, the offset in the first value, and length in
+ * the second, or {@code null} if no tag was found.
+ * @throws IllegalStateException if {@link #saveAttributes()} has been
+ * called since the underlying file was initially parsed, since
+ * that means offsets may have changed.
+ */
+ public @Nullable long[] getAttributeRange(@NonNull String tag) {
+ if (mModified) {
+ throw new IllegalStateException(
+ "The underlying file has been modified since being parsed");
+ }
+
+ final ExifAttribute attribute = getExifAttribute(tag);
+ if (attribute != null) {
+ return new long[] { attribute.bytesOffset, attribute.bytes.length };
+ } else {
+ return null;
+ }
}
/**
@@ -2023,13 +2086,41 @@
}
/**
- * Returns number of milliseconds since Jan. 1, 1970, midnight local time.
- * Returns -1 if the date time information if not available.
+ * Returns parsed {@code DateTime} value, or -1 if unavailable or invalid.
+ *
* @hide
*/
@UnsupportedAppUsage
- public long getDateTime() {
- String dateTimeString = getAttribute(TAG_DATETIME);
+ public @CurrentTimeMillisLong long getDateTime() {
+ return parseDateTime(getAttribute(TAG_DATETIME),
+ getAttribute(TAG_SUBSEC_TIME));
+ }
+
+ /**
+ * Returns parsed {@code DateTimeDigitized} value, or -1 if unavailable or
+ * invalid.
+ *
+ * @hide
+ */
+ public @CurrentTimeMillisLong long getDateTimeDigitized() {
+ return parseDateTime(getAttribute(TAG_DATETIME_DIGITIZED),
+ getAttribute(TAG_SUBSEC_TIME_DIGITIZED));
+ }
+
+ /**
+ * Returns parsed {@code DateTimeOriginal} value, or -1 if unavailable or
+ * invalid.
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public @CurrentTimeMillisLong long getDateTimeOriginal() {
+ return parseDateTime(getAttribute(TAG_DATETIME_ORIGINAL),
+ getAttribute(TAG_SUBSEC_TIME_ORIGINAL));
+ }
+
+ private static @CurrentTimeMillisLong long parseDateTime(@Nullable String dateTimeString,
+ @Nullable String subSecs) {
if (dateTimeString == null
|| !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
@@ -2041,7 +2132,6 @@
if (datetime == null) return -1;
long msecs = datetime.getTime();
- String subSecs = getAttribute(TAG_SUBSEC_TIME);
if (subSecs != null) {
try {
long sub = Long.parseLong(subSecs);
@@ -3125,9 +3215,11 @@
continue;
}
- byte[] bytes = new byte[(int) byteCount];
+ final int bytesOffset = dataInputStream.peek();
+ final byte[] bytes = new byte[(int) byteCount];
dataInputStream.readFully(bytes);
- ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes);
+ ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents,
+ bytesOffset, bytes);
mAttributes[ifdType].put(tag.name, attribute);
// DNG files have a DNG Version tag specifying the version of specifications that the
diff --git a/media/java/android/media/FileDataSourceDesc.java b/media/java/android/media/FileDataSourceDesc.java
index 9e80975..763a81f 100644
--- a/media/java/android/media/FileDataSourceDesc.java
+++ b/media/java/android/media/FileDataSourceDesc.java
@@ -17,20 +17,26 @@
package android.media;
import android.annotation.NonNull;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
-import java.io.FileDescriptor;
+import java.io.IOException;
/**
* @hide
- * Structure for data source descriptor.
+ * Structure of data source descriptor for sources using file descriptor.
*
- * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)}
+ * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
* to set data source for playback.
*
* <p>Users should use {@link Builder} to create {@link FileDataSourceDesc}.
*
*/
public class FileDataSourceDesc extends DataSourceDesc {
+ private static final String TAG = "FileDataSourceDesc";
+
/**
* Used when the length of file descriptor is unknown.
*
@@ -38,34 +44,61 @@
*/
public static final long FD_LENGTH_UNKNOWN = LONG_MAX;
- private FileDescriptor mFD;
+ private ParcelFileDescriptor mPFD;
private long mOffset = 0;
private long mLength = FD_LENGTH_UNKNOWN;
private FileDataSourceDesc() {
+ super();
}
/**
- * Return the FileDescriptor of this data source.
- * @return the FileDescriptor of this data source
+ * Releases the resources held by this {@code FileDataSourceDesc} object.
*/
- public FileDescriptor getFileDescriptor() {
- return mFD;
+ @Override
+ void close() {
+ super.close();
+ closeFD();
}
/**
- * Return the offset associated with the FileDescriptor of this data source.
+ * Releases the file descriptor held by this {@code FileDataSourceDesc} object.
+ */
+ void closeFD() {
+ synchronized (this) {
+ if (mPFD != null) {
+ try {
+ mPFD.close();
+ } catch (IOException e) {
+ Log.e(TAG, "failed to close pfd: " + e);
+ }
+
+ mPFD = null;
+ }
+ }
+ }
+
+ /**
+ * Return the ParcelFileDescriptor of this data source.
+ * @return the ParcelFileDescriptor of this data source
+ */
+ public ParcelFileDescriptor getParcelFileDescriptor() {
+ return mPFD;
+ }
+
+ /**
+ * Return the offset associated with the ParcelFileDescriptor of this data source.
* It's meaningful only when it has been set by the {@link Builder}.
- * @return the offset associated with the FileDescriptor of this data source
+ * @return the offset associated with the ParcelFileDescriptor of this data source
*/
public long getOffset() {
return mOffset;
}
/**
- * Return the content length associated with the FileDescriptor of this data source.
+ * Return the content length associated with the ParcelFileDescriptor of this data source.
* {@link #FD_LENGTH_UNKNOWN} means same as the length of source content.
- * @return the content length associated with the FileDescriptor of this data source
+ * @return the content length associated with the ParcelFileDescriptor of this data source
*/
public long getLength() {
return mLength;
@@ -78,7 +111,7 @@
*
* <pre class="prettyprint">
* FileDataSourceDesc newDSD = new FileDataSourceDesc.Builder()
- * .setDataSource(fd, 0, srcLength)
+ * .setDataSource(pfd, 0, srcLength)
* .setStartPosition(1000)
* .setEndPosition(15000)
* .build();
@@ -86,7 +119,7 @@
* </pre>
*/
public static class Builder extends BuilderBase<Builder> {
- private FileDescriptor mFD;
+ private ParcelFileDescriptor mPFD;
private long mOffset = 0;
private long mLength = FD_LENGTH_UNKNOWN;
@@ -107,7 +140,7 @@
if (dsd == null) {
return; // use default
}
- mFD = dsd.mFD;
+ mPFD = dsd.mPFD;
mOffset = dsd.mOffset;
mLength = dsd.mLength;
}
@@ -122,7 +155,7 @@
public @NonNull FileDataSourceDesc build() {
FileDataSourceDesc dsd = new FileDataSourceDesc();
super.build(dsd);
- dsd.mFD = mFD;
+ dsd.mPFD = mPFD;
dsd.mOffset = mOffset;
dsd.mLength = mLength;
@@ -130,38 +163,46 @@
}
/**
- * Sets the data source (FileDescriptor) to use. The FileDescriptor must be
- * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
- * to close the file descriptor after the source has been used.
+ * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
+ * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
+ * created by this builder is passed to {@link MediaPlayer2} via
+ * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+ * close the ParcelFileDescriptor.
*
- * @param fd the FileDescriptor for the file to play
+ * @param pfd the ParcelFileDescriptor for the file to play
* @return the same Builder instance.
- * @throws NullPointerException if fd is null.
+ * @throws NullPointerException if pfd is null.
*/
- public @NonNull Builder setDataSource(@NonNull FileDescriptor fd) {
- Media2Utils.checkArgument(fd != null, "fd cannot be null.");
+ public @NonNull Builder setDataSource(@NonNull ParcelFileDescriptor pfd) {
+ Media2Utils.checkArgument(pfd != null, "pfd cannot be null.");
resetDataSource();
- mFD = fd;
+ mPFD = pfd;
return this;
}
/**
- * Sets the data source (FileDescriptor) to use. The FileDescriptor must be
- * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
- * to close the file descriptor after the source has been used.
+ * Sets the data source (ParcelFileDescriptor) to use. The ParcelFileDescriptor must be
+ * seekable (N.B. a LocalSocket is not seekable). When the {@link FileDataSourceDesc}
+ * created by this builder is passed to {@link MediaPlayer2} via
+ * {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} or
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}, MediaPlayer2 will
+ * close the ParcelFileDescriptor.
*
* Any negative number for offset is treated as 0.
* Any negative number for length is treated as maximum length of the data source.
*
- * @param fd the FileDescriptor for the file to play
+ * @param pfd the ParcelFileDescriptor for the file to play
* @param offset the offset into the file where the data to be played starts, in bytes
* @param length the length in bytes of the data to be played
* @return the same Builder instance.
- * @throws NullPointerException if fd is null.
+ * @throws NullPointerException if pfd is null.
*/
public @NonNull Builder setDataSource(
- @NonNull FileDescriptor fd, long offset, long length) {
- Media2Utils.checkArgument(fd != null, "fd cannot be null.");
+ @NonNull ParcelFileDescriptor pfd, long offset, long length) {
+ Media2Utils.checkArgument(pfd != null, "pfd cannot be null.");
if (offset < 0) {
offset = 0;
}
@@ -169,14 +210,14 @@
length = FD_LENGTH_UNKNOWN;
}
resetDataSource();
- mFD = fd;
+ mPFD = pfd;
mOffset = offset;
mLength = length;
return this;
}
private void resetDataSource() {
- mFD = null;
+ mPFD = null;
mOffset = 0;
mLength = FD_LENGTH_UNKNOWN;
}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 267dab9..b047f8d 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -36,6 +36,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.util.Log;
@@ -412,6 +413,9 @@
mHandlerThread = null;
}
+ setCurrentSourceInfo(null);
+ clearNextSourceInfos();
+
// Modular DRM clean up
mOnDrmConfigHelper = null;
synchronized (mDrmEventCbLock) {
@@ -457,10 +461,8 @@
synchronized (mDrmEventCbLock) {
mDrmEventCallbackRecords.clear();
}
- synchronized (mSrcLock) {
- mCurrentSourceInfo = null;
- mNextSourceInfos.clear();
- }
+ setCurrentSourceInfo(null);
+ clearNextSourceInfos();
synchronized (mTaskLock) {
mPendingTasks.clear();
@@ -685,6 +687,8 @@
/**
* Sets the data source as described by a DataSourceDesc.
+ * When the data source is of {@link FileDataSourceDesc} type, the {@link ParcelFileDescriptor}
+ * in the {@link FileDataSourceDesc} will be closed by the player.
*
* @param dsd the descriptor of data source you want to play
* @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
@@ -696,13 +700,17 @@
void process() throws IOException {
Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
int state = getState();
- if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
- throw new IllegalStateException("called in wrong state " + state);
- }
+ try {
+ if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
+ throw new IllegalStateException("called in wrong state " + state);
+ }
- synchronized (mSrcLock) {
- mCurrentSourceInfo = new SourceInfo(dsd);
- handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
+ synchronized (mSrcLock) {
+ setCurrentSourceInfo(new SourceInfo(dsd));
+ handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
+ }
+ } finally {
+ dsd.close();
}
}
});
@@ -711,6 +719,8 @@
/**
* Sets a single data source as described by a DataSourceDesc which will be played
* after current data source is finished.
+ * When the data source is of {@link FileDataSourceDesc} type, the {@link ParcelFileDescriptor}
+ * in the {@link FileDataSourceDesc} will be closed by the player.
*
* @param dsd the descriptor of data source you want to play after current one
* @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
@@ -722,7 +732,7 @@
void process() {
Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
synchronized (mSrcLock) {
- mNextSourceInfos.clear();
+ clearNextSourceInfos();
mNextSourceInfos.add(new SourceInfo(dsd));
}
prepareNextDataSource();
@@ -732,6 +742,8 @@
/**
* Sets a list of data sources to be played sequentially after current data source is done.
+ * When the data source is of {@link FileDataSourceDesc} type, the {@link ParcelFileDescriptor}
+ * in the {@link FileDataSourceDesc} will be closed by the player.
*
* @param dsds the list of data sources you want to play after current one
* @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
@@ -744,17 +756,15 @@
if (dsds == null || dsds.size() == 0) {
throw new IllegalArgumentException("data source list cannot be null or empty.");
}
- for (DataSourceDesc dsd : dsds) {
- if (dsd == null) {
- throw new IllegalArgumentException(
- "DataSourceDesc in the source list cannot be null.");
- }
- }
synchronized (mSrcLock) {
- mNextSourceInfos.clear();
+ clearNextSourceInfos();
for (DataSourceDesc dsd : dsds) {
- mNextSourceInfos.add(new SourceInfo(dsd));
+ if (dsd != null) {
+ mNextSourceInfos.add(new SourceInfo(dsd));
+ } else {
+ Log.w(TAG, "DataSourceDesc in the source list shall not be null.");
+ }
}
}
prepareNextDataSource();
@@ -771,7 +781,7 @@
return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
@Override
void process() {
- mNextSourceInfos.clear();
+ clearNextSourceInfos();
}
});
}
@@ -795,14 +805,14 @@
CallbackDataSourceDesc cbDSD = (CallbackDataSourceDesc) dsd;
handleDataSource(isCurrent,
srcId,
- cbDSD.getMedia2DataSource(),
+ cbDSD.getDataSourceCallback(),
cbDSD.getStartPosition(),
cbDSD.getEndPosition());
} else if (dsd instanceof FileDataSourceDesc) {
FileDataSourceDesc fileDSD = (FileDataSourceDesc) dsd;
handleDataSource(isCurrent,
srcId,
- fileDSD.getFileDescriptor(),
+ fileDSD.getParcelFileDescriptor(),
fileDSD.getOffset(),
fileDSD.getLength(),
fileDSD.getStartPosition(),
@@ -886,7 +896,7 @@
if (afd.getDeclaredLength() < 0) {
handleDataSource(isCurrent,
srcId,
- afd.getFileDescriptor(),
+ ParcelFileDescriptor.dup(afd.getFileDescriptor()),
0,
DataSourceDesc.LONG_MAX,
startPos,
@@ -894,7 +904,7 @@
} else {
handleDataSource(isCurrent,
srcId,
- afd.getFileDescriptor(),
+ ParcelFileDescriptor.dup(afd.getFileDescriptor()),
afd.getStartOffset(),
afd.getDeclaredLength(),
startPos,
@@ -960,7 +970,8 @@
if (file.exists()) {
FileInputStream is = new FileInputStream(file);
FileDescriptor fd = is.getFD();
- handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX, startPos, endPos);
+ handleDataSource(isCurrent, srcId, ParcelFileDescriptor.dup(fd),
+ 0, DataSourceDesc.LONG_MAX, startPos, endPos);
is.close();
} else {
throw new IOException("handleDataSource failed.");
@@ -984,9 +995,10 @@
*/
private void handleDataSource(
boolean isCurrent, long srcId,
- FileDescriptor fd, long offset, long length,
+ ParcelFileDescriptor pfd, long offset, long length,
long startPos, long endPos) throws IOException {
- nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length, startPos, endPos);
+ nativeHandleDataSourceFD(isCurrent, srcId, pfd.getFileDescriptor(), offset, length,
+ startPos, endPos);
}
private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId,
@@ -995,15 +1007,15 @@
/**
* @throws IllegalStateException if it is called in an invalid state
- * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
+ * @throws IllegalArgumentException if dataSource is not a valid DataSourceCallback
*/
- private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource,
+ private void handleDataSource(boolean isCurrent, long srcId, DataSourceCallback dataSource,
long startPos, long endPos) {
nativeHandleDataSourceCallback(isCurrent, srcId, dataSource, startPos, endPos);
}
private native void nativeHandleDataSourceCallback(
- boolean isCurrent, long srcId, Media2DataSource dataSource,
+ boolean isCurrent, long srcId, DataSourceCallback dataSource,
long startPos, long endPos);
// return true if there is a next data source, false otherwise.
@@ -1037,7 +1049,10 @@
MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
mTaskHandler.handleMessage(msg, nextSource.mId);
- mNextSourceInfos.poll();
+ SourceInfo nextSourceInfo = mNextSourceInfos.poll();
+ if (nextSource != null) {
+ nextSourceInfo.close();
+ }
return prepareNextDataSource();
}
}
@@ -1058,7 +1073,7 @@
SourceInfo nextSourceInfo = mNextSourceInfos.peek();
if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) {
// Switch to next source only when it has been prepared.
- mCurrentSourceInfo = mNextSourceInfos.poll();
+ setCurrentSourceInfo(mNextSourceInfos.poll());
long srcId = mCurrentSourceInfo.mId;
try {
@@ -4490,6 +4505,7 @@
final DataSourceDesc mDSD;
final long mId = mSrcIdGenerator.getAndIncrement();
AtomicInteger mBufferedPercentage = new AtomicInteger(0);
+ boolean mClosed = false;
// m*AsNextSource (below) only applies to pending data sources in the playlist;
// the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource}
@@ -4501,6 +4517,17 @@
this.mDSD = dsd;
}
+ void close() {
+ synchronized (this) {
+ if (!mClosed) {
+ if (mDSD != null) {
+ mDSD.close();
+ }
+ mClosed = true;
+ }
+ }
+ }
+
@Override
public String toString() {
return String.format("%s(%d)", SourceInfo.class.getName(), mId);
@@ -4531,6 +4558,26 @@
return nextSourceInfo != null && nextSourceInfo.mId == srcId;
}
+ private void setCurrentSourceInfo(SourceInfo newSourceInfo) {
+ synchronized (mSrcLock) {
+ if (mCurrentSourceInfo != null) {
+ mCurrentSourceInfo.close();
+ }
+ mCurrentSourceInfo = newSourceInfo;
+ }
+ }
+
+ private void clearNextSourceInfos() {
+ synchronized (mSrcLock) {
+ for (SourceInfo sourceInfo : mNextSourceInfos) {
+ if (sourceInfo != null) {
+ sourceInfo.close();
+ }
+ }
+ mNextSourceInfos.clear();
+ }
+ }
+
public static final class MetricsConstants {
private MetricsConstants() {}
diff --git a/media/java/android/media/UriDataSourceDesc.java b/media/java/android/media/UriDataSourceDesc.java
index d4a43a1..6a83dab 100644
--- a/media/java/android/media/UriDataSourceDesc.java
+++ b/media/java/android/media/UriDataSourceDesc.java
@@ -31,9 +31,11 @@
/**
* @hide
- * Structure for data source descriptor.
+ * Structure of data source descriptor for sources using URI.
*
- * Used by {@link MediaPlayer2#setDataSource(UriDataSourceDesc)}
+ * Used by {@link MediaPlayer2#setDataSource(DataSourceDesc)},
+ * {@link MediaPlayer2#setNextDataSource(DataSourceDesc)} and
+ * {@link MediaPlayer2#setNextDataSources(List<DataSourceDesc>)}
* to set data source for playback.
*
* <p>Users should use {@link Builder} to change {@link UriDataSourceDesc}.
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index faf4301..e25e6a5 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -88,7 +88,7 @@
name: "libmedia2_jni",
srcs: [
- "android_media_Media2DataSource.cpp",
+ "android_media_DataSourceCallback.cpp",
"android_media_MediaMetricsJNI.cpp",
"android_media_MediaPlayer2.cpp",
"android_media_SyncParams.cpp",
diff --git a/media/jni/android_media_Media2DataSource.cpp b/media/jni/android_media_DataSourceCallback.cpp
similarity index 79%
rename from media/jni/android_media_Media2DataSource.cpp
rename to media/jni/android_media_DataSourceCallback.cpp
index b3434e9..c91d409 100644
--- a/media/jni/android_media_Media2DataSource.cpp
+++ b/media/jni/android_media_DataSourceCallback.cpp
@@ -15,10 +15,10 @@
*/
//#define LOG_NDEBUG 0
-#define LOG_TAG "JMedia2DataSource-JNI"
+#define LOG_TAG "JDataSourceCallback-JNI"
#include <utils/Log.h>
-#include "android_media_Media2DataSource.h"
+#include "android_media_DataSourceCallback.h"
#include "log/log.h"
#include "jni.h"
@@ -33,14 +33,14 @@
static const size_t kBufferSize = 64 * 1024;
-JMedia2DataSource::JMedia2DataSource(JNIEnv* env, jobject source)
+JDataSourceCallback::JDataSourceCallback(JNIEnv* env, jobject source)
: mJavaObjStatus(OK),
mSizeIsCached(false),
mCachedSize(0) {
- mMedia2DataSourceObj = env->NewGlobalRef(source);
- CHECK(mMedia2DataSourceObj != NULL);
+ mDataSourceCallbackObj = env->NewGlobalRef(source);
+ CHECK(mDataSourceCallbackObj != NULL);
- ScopedLocalRef<jclass> media2DataSourceClass(env, env->GetObjectClass(mMedia2DataSourceObj));
+ ScopedLocalRef<jclass> media2DataSourceClass(env, env->GetObjectClass(mDataSourceCallbackObj));
CHECK(media2DataSourceClass.get() != NULL);
mReadAtMethod = env->GetMethodID(media2DataSourceClass.get(), "readAt", "(J[BII)I");
@@ -55,17 +55,17 @@
CHECK(mByteArrayObj != NULL);
}
-JMedia2DataSource::~JMedia2DataSource() {
+JDataSourceCallback::~JDataSourceCallback() {
JNIEnv* env = JavaVMHelper::getJNIEnv();
- env->DeleteGlobalRef(mMedia2DataSourceObj);
+ env->DeleteGlobalRef(mDataSourceCallbackObj);
env->DeleteGlobalRef(mByteArrayObj);
}
-status_t JMedia2DataSource::initCheck() const {
+status_t JDataSourceCallback::initCheck() const {
return OK;
}
-ssize_t JMedia2DataSource::readAt(off64_t offset, void *data, size_t size) {
+ssize_t JDataSourceCallback::readAt(off64_t offset, void *data, size_t size) {
Mutex::Autolock lock(mLock);
if (mJavaObjStatus != OK) {
@@ -76,7 +76,7 @@
}
JNIEnv* env = JavaVMHelper::getJNIEnv();
- jint numread = env->CallIntMethod(mMedia2DataSourceObj, mReadAtMethod,
+ jint numread = env->CallIntMethod(mDataSourceCallbackObj, mReadAtMethod,
(jlong)offset, mByteArrayObj, (jint)0, (jint)size);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred in readAt()");
@@ -106,7 +106,7 @@
return numread;
}
-status_t JMedia2DataSource::getSize(off64_t* size) {
+status_t JDataSourceCallback::getSize(off64_t* size) {
Mutex::Autolock lock(mLock);
if (mJavaObjStatus != OK) {
@@ -118,7 +118,7 @@
}
JNIEnv* env = JavaVMHelper::getJNIEnv();
- *size = env->CallLongMethod(mMedia2DataSourceObj, mGetSizeMethod);
+ *size = env->CallLongMethod(mDataSourceCallbackObj, mGetSizeMethod);
if (env->ExceptionCheck()) {
ALOGW("An exception occurred in getSize()");
jniLogException(env, ANDROID_LOG_WARN, LOG_TAG);
@@ -139,20 +139,20 @@
return OK;
}
-void JMedia2DataSource::close() {
+void JDataSourceCallback::close() {
Mutex::Autolock lock(mLock);
JNIEnv* env = JavaVMHelper::getJNIEnv();
- env->CallVoidMethod(mMedia2DataSourceObj, mCloseMethod);
+ env->CallVoidMethod(mDataSourceCallbackObj, mCloseMethod);
// The closed state is effectively the same as an error state.
mJavaObjStatus = UNKNOWN_ERROR;
}
-String8 JMedia2DataSource::toString() {
- return String8::format("JMedia2DataSource(pid %d, uid %d)", getpid(), getuid());
+String8 JDataSourceCallback::toString() {
+ return String8::format("JDataSourceCallback(pid %d, uid %d)", getpid(), getuid());
}
-String8 JMedia2DataSource::getMIMEType() const {
+String8 JDataSourceCallback::getMIMEType() const {
return String8("application/octet-stream");
}
diff --git a/media/jni/android_media_Media2DataSource.h b/media/jni/android_media_DataSourceCallback.h
similarity index 80%
rename from media/jni/android_media_Media2DataSource.h
rename to media/jni/android_media_DataSourceCallback.h
index dc085f3..5bde682 100644
--- a/media/jni/android_media_Media2DataSource.h
+++ b/media/jni/android_media_DataSourceCallback.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef _ANDROID_MEDIA_MEDIA2DATASOURCE_H_
-#define _ANDROID_MEDIA_MEDIA2DATASOURCE_H_
+#ifndef _ANDROID_MEDIA_DATASOURCECALLBACK_H_
+#define _ANDROID_MEDIA_DATASOURCECALLBACK_H_
#include "jni.h"
@@ -26,16 +26,16 @@
namespace android {
-// The native counterpart to a Java android.media.Media2DataSource. It inherits from
+// The native counterpart to a Java android.media.DataSourceCallback. It inherits from
// DataSource.
//
// If the java DataSource returns an error or throws an exception it
// will be considered to be in a broken state, and the only further call this
// will make is to close().
-class JMedia2DataSource : public DataSource {
+class JDataSourceCallback : public DataSource {
public:
- JMedia2DataSource(JNIEnv *env, jobject source);
- virtual ~JMedia2DataSource();
+ JDataSourceCallback(JNIEnv *env, jobject source);
+ virtual ~JDataSourceCallback();
virtual status_t initCheck() const override;
virtual ssize_t readAt(off64_t offset, void *data, size_t size) override;
@@ -56,15 +56,15 @@
bool mSizeIsCached;
off64_t mCachedSize;
- jobject mMedia2DataSourceObj;
+ jobject mDataSourceCallbackObj;
jmethodID mReadAtMethod;
jmethodID mGetSizeMethod;
jmethodID mCloseMethod;
jbyteArray mByteArrayObj;
- DISALLOW_EVIL_CONSTRUCTORS(JMedia2DataSource);
+ DISALLOW_EVIL_CONSTRUCTORS(JDataSourceCallback);
};
} // namespace android
-#endif // _ANDROID_MEDIA_MEDIA2DATASOURCE_H_
+#endif // _ANDROID_MEDIA_DATASOURCECALLBACK_H_
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index f7de2e7..4567492 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -46,7 +46,7 @@
#include "utils/KeyedVector.h"
#include "utils/String8.h"
#include "android_media_BufferingParams.h"
-#include "android_media_Media2DataSource.h"
+#include "android_media_DataSourceCallback.h"
#include "android_media_MediaMetricsJNI.h"
#include "android_media_PlaybackParams.h"
#include "android_media_SyncParams.h"
@@ -423,7 +423,7 @@
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return;
}
- sp<DataSource> callbackDataSource = new JMedia2DataSource(env, dataSource);
+ sp<DataSource> callbackDataSource = new JDataSourceCallback(env, dataSource);
sp<DataSourceDesc> dsd = new DataSourceDesc();
dsd->mId = srcId;
dsd->mType = DataSourceDesc::TYPE_CALLBACK;
@@ -1390,7 +1390,7 @@
},
{
"nativeHandleDataSourceCallback",
- "(ZJLandroid/media/Media2DataSource;JJ)V",
+ "(ZJLandroid/media/DataSourceCallback;JJ)V",
(void *)android_media_MediaPlayer2_handleDataSourceCallback
},
{"nativePlayNextDataSource", "(J)V", (void *)android_media_MediaPlayer2_playNextDataSource},
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index e7e8384..207508e 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -144,6 +144,7 @@
AHardwareBuffer_describe; # introduced=26
AHardwareBuffer_fromHardwareBuffer; # introduced=26
AHardwareBuffer_getNativeHandle; # introduced=26
+ AHardwareBuffer_isSupported; # introduced=29
AHardwareBuffer_lock; # introduced=26
AHardwareBuffer_recvHandleFromUnixSocket; # introduced=26
AHardwareBuffer_release; # introduced=26
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 22d0e3b..4b212c2 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -378,6 +378,14 @@
}
@Override
+ public void onActionClicked(String key, Notification.Action action, int source) {
+ if (DEBUG) {
+ Log.d(TAG, "onActionClicked() called with: key = [" + key + "], action = [" + action.title
+ + "], source = [" + source + "]");
+ }
+ }
+
+ @Override
public void onListenerConnected() {
if (DEBUG) Log.i(TAG, "CONNECTED");
try {
diff --git a/packages/SettingsLib/SearchWidget/res/values-as/strings.xml b/packages/SettingsLib/SearchWidget/res/values-as/strings.xml
new file mode 100644
index 0000000..813e764
--- /dev/null
+++ b/packages/SettingsLib/SearchWidget/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="search_menu" msgid="1604061903696928905">"সন্ধান সম্পৰ্কীয় ছেটিংসমূহ"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index d34820c..1dd7838 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan nie skandeer vir netwerke nie"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gestoor"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Gedeaktiveer"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-opstelling het misluk"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sal op grond van jou gebruik waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sal waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Sal waarskynlik hou tot omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Tot <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vra elke keer"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Totdat jy dit afskakel"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sopas"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Aansluitingprogram om opgedateerde grafikadrywer in ontwikkeling te gebruik"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Foonluidspreker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index b595e2b..2ce5f44 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ለአውታረመረቦች መቃኘት አይቻልም"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"የለም"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ተቀምጧል"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ተሰናክሏል"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"የአይ.ፒ. ውቅረት መሰናከል"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"በአጠቃቀምዎ መሠረት እስከ <xliff:g id="TIME">%1$s</xliff:g> ገደማ መቆየት አለበት"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"እስከ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ገደማ ድረስ መቆየት አለበት"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"እስከ <xliff:g id="TIME">%1$s</xliff:g> ገደማ መቆየት አለበት"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"እስከ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ሁልጊዜ ጠይቅ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"እስኪያጠፉት ድረስ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ልክ አሁን"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"በግንባታ ላይ የተዘመነ የግራፊክስ ነጂን ለመጠቀም መተግበሪያን መርጠው ያስገቡ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"የስልክ ድምጽ ማጉያ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index f8c2ba2..23f3a12 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"لا يمكن فحص الشبكات"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"بدون"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"تم الحفظ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غير مفعّلة"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"تعذّرت تهيئة عنوان IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
<string name="power_discharge_by" msgid="6453537733650125582">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"حتى <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
@@ -451,4 +453,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"الطلب في كل مرة"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"إلى أن توقف الوضع يدويًا"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"للتو"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"فعِّل التطبيق لاستخدام برنامج تشغيل الرسومات المُحدَّث في تطوير البرامج."</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"مكبر صوت الهاتف"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 72122c2..86d1459 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটৱৰ্ক বিচাৰি স্কেন কৰিব পৰা নাই"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"নাই"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ছেভ কৰি থোৱা নেটৱৰ্কসমূহ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"নিষ্ক্ৰিয় হৈ আছে"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগাৰেশ্বন বিফল হৈছে"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"বেটাৰি আনুমানিকভাৱে <xliff:g id="TIME">%1$s</xliff:g> লৈকে চলিব"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> পৰ্যন্ত"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>তকৈও কম সময় বাকী আছে"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>তকৈও কম সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>তকৈও বেছি সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"প্ৰতিবাৰতে সোধক"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"আপুনি অফ নকৰা পর্যন্ত"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"এই মাত্ৰ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"বিকাশকাৰ্য চলি থকা আপডে\'টেড গ্ৰাফিক ড্ৰাইভাৰ ব্যৱহাৰ কৰিবলৈ এপ্ অপ্ট ইন কৰক"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ফ’নৰ স্পীকাৰ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 23008e2..17d0ca6 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Şəbəkə axtarmaq olmur"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Heç biri"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Yadda saxlanılan"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiv"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Konfiqurasiya Uğursuzluğu"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"İstifadəyə əsasən təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Təxminən <xliff:g id="TIME">%1$s</xliff:g> olana qədər davam edəcək"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> olana qədər"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Hər dəfə soruşun"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Deaktiv edənə qədər"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"İndicə"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Qrafik drayverdən istifadə etmək üçün tətbiq seçin"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefon spikeri"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 3ee8589..56052d2 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nije moguće skenirati mreže"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfiguracija je otkazala"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> na osnovu korišćenja"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Trajaće približno do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uvek pitaj"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Omogući aplikaciju za korišćenje upravljačkog programa grafičke katice u razvoju"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Zvučnik telefona"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 64253bf..f2c2046 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не атрымлiваецца выканаць сканаванне для сетак"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Захавана"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Адключана"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Збой канфігурацыі IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Зараду хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g> пры цяперашнім узроўні выкарыстання"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Зараду (<xliff:g id="LEVEL">%2$s</xliff:g>) хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Зараду хопіць прыблізна да <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Да <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Засталося менш за <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць менш чым на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць больш чым на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Заўсёды пытацца"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Пакуль не выключыце"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Зараз"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Выбраная праграма, якая выкарыстоўвае абноўлены драйвер графічнай сістэмы (падчас распрацоўкі)"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Дынамік тэлефона"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 668aa2d..5b8d6b8 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да се сканира за мрежи"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Запазено"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Деактивирани"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Неуспешно конфигуриране на IP адреса"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Следва да издържи до около <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Да се пита винаги"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"До изключване"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Току-що"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Включване на приложението за използване на актуализирания графичен драйвер в разработка"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Високоговорител на телефона"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index c6eed2c..7efad99 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটওয়ার্কগুলির জন্য স্ক্যান করা যাবে না"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"কোনো কিছুই নয়"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"সংরক্ষিত"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"অক্ষম হয়েছে"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"বর্তমান ব্যবহার অনুযায়ী আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"আনুমানিক <xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত চলবে"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> পর্যন্ত"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> এর থেকেও কম বাকি আছে"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"আর <xliff:g id="THRESHOLD">%1$s</xliff:g>-এর কম চার্জ বাকি আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"আরও <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-এর বেশি চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"প্রতিবার জিজ্ঞেস করা হবে"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"এখনই"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ডেভলপমেন্টে আপডেট হওয়া গ্রাফিক্স ড্রাইভার ব্যবহার করতে অ্যাপ বেছে নিন"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ফেনের স্পিকার"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 16179fb..92435f7 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Trebala bi trajati otprilike do <xliff:g id="TIME">%1$s</xliff:g> na osnovu vaše upotrebe"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Trebala bi trajati do otprilike <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Trebala bi trajati otprilike do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Prijavi aplikaciju za korištenje ažuriranog grafičkog drajvera u razvoju"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Zvučnik telefona"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index f906ea4..3182f16 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No es poden cercar xarxes"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Cap"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Desat"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivat"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuració d\'IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> segons l\'ús que en fas"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"La bateria hauria de durar aproximadament fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Fins a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Temps restant superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pregunta sempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Fins que no ho desactivis"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ara mateix"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Aplicació activada per utilitzar el controlador de gràfics actualitzat en desenvolupament"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altaveu del telèfon"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f9c8669..3785433 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nelze hledat sítě"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Žádné"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Uloženo"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuto"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Selhání konfigurace protokolu IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Při vašem obvyklém využití vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Vydrží asi do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pokaždé se zeptat"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokud tuto funkci nevypnete"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Právě teď"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Přihlaste aplikaci k použití vyvíjeného aktualizovaného grafického ovladače"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Reproduktor telefonu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6b2bd98..eeeccee 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Der kan ikke søges efter netværk"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gemt"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiveret"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfejl"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> baseret på dit forbrug"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Bør holde indtil ca. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Indtil <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spørg hver gang"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Indtil du deaktiverer"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Lige nu"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Tilvælg en app, der skal bruge den opdaterede grafikdriver under udvikling"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefonens højttaler"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index ad6f5f2..95f7416 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Netzwerkscan nicht möglich"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Keine"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gespeichert"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiviert"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-Konfigurationsfehler"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sollte basierend auf deiner Nutzung etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sollte etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Sollte etwa bis <xliff:g id="TIME">%1$s</xliff:g> reichen"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Bis <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Jedes Mal fragen"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Bis zur Deaktivierung"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Gerade eben"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"App aktivieren, um den aktualisierten Grafiktreiber in der Entwicklung zu verwenden"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefon-Lautsprecher"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 5bfbf2c..310b6cf 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Δεν είναι δυνατή η σάρωση για δίκτυα"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Καμία"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Αποθηκευμένο"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Απενεργοποιημένο"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Αποτυχία διαμόρφωσης διεύθυνσης IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου, ανάλογα με τη χρήση σας"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Θα διαρκέσει μέχρι τις <xliff:g id="TIME">%1$s</xliff:g> περίπου"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Έως τις <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Να ερωτώμαι κάθε φορά"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Μέχρι την απενεργοποίηση"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Μόλις τώρα"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Επιλέξτε μια εφαρμογή για τη χρήση του ενημερωμένου προγράμματος οδήγησης γραφικών σε ανάπτυξη"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Ηχείο τηλεφώνου"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index f0eaeed..5b11d63 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Opt in app to use updated graphics driver in development"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Phone speaker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index f0eaeed..5b11d63 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Opt in app to use updated graphics driver in development"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Phone speaker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index f0eaeed..5b11d63 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Opt in app to use updated graphics driver in development"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Phone speaker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index f0eaeed..5b11d63 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Opt in app to use updated graphics driver in development"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Phone speaker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 6927fda..d7ed49a 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Until <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ask every time"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Opt in app to use updated graphcis driver in developement"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Phone speaker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 675084f..ecec63c 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se pueden buscar las redes."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitada"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> según el uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hasta <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Recién"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Habilitar app para que use el controlador de gráficos actualizado en el desarrollo"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altavoz del teléfono"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b51b847..b8fdf30 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se puede buscar redes."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardado"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración de IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> según el uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Debería durar aproximadamente hasta <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hasta: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Queda menos del <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Queda más del <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que se desactive"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Justo ahora"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Habilitar aplicación para usar controlador de gráficos actualizado en desarrollo"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altavoz del teléfono"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index fb077be..1246626 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Võrke ei saa kontrollida"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Puudub"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvestatud"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Keelatud"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP seadistamise ebaõnnestumine"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Peaks teie kasutuse põhjal kestma kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Peaks kestma kuni <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Peaks kestma kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Kuni <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Küsi iga kord"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Kuni välja lülitate"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Äsja"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Lubage rakendus, et kasutada arenduses olevat värskendatud graafikadraiverit"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefoni kõlar"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 3d3b8c3..68b4840 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ezin dira sareak bilatu"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Bat ere ez"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gordeta"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desgaituta"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ezin izan da konfiguratu IP helbidea"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Erabileraren arabera, ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Ordu honetara arte iraungo du, gutxi gorabehera: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> arte"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen dira"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Galdetu beti"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Desaktibatu arte"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Oraintxe"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Hautatu zein aplikaziorekin erabili nahi duzun garatze-prozesuan dagoen grafikoen kontrolatzaile eguneratua"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefonoaren bozgorailua"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 0af118e..7882b056 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"اسکن شبکهها امکانپذیر نیست"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"هیچکدام"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ذخیرهشده"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"پیکربندی IP انجام نشد"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"باتوجه به میزان مصرفتان، باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> شارژ داشته باشید"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) شارژ داشته باشید"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"باید حدوداً تا <xliff:g id="TIME">%1$s</xliff:g> شارژ داشته باشید"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"تا <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> باقی مانده"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"بیش از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"هربار پرسیده شود"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"تا زمانیکه آن را خاموش کنید"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"هماکنون"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"برنامه انتخابشده برای استفاده از درایور گرافیک بهروزرسانیشده در برنامهنویس"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"بلندگوی تلفن"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index dde10d0d..1904c4d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Verkkoja ei voi etsiä."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ei mitään"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Tallennettu"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Pois käytöstä"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-kokoonpanovirhe"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Varaus loppuu käyttösi perusteella noin <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Varaus loppuu noin <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Varaus loppuu noin <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> saakka"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Kysy aina"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Kunnes poistat sen käytöstä"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Äsken"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Lisää sovellus käyttämään päivitettyä grafiikkaohjainta kehitysvaiheessa"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Puhelimen kaiutin"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 1257ea5..45b2872 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivés"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>, en fonction de votre usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Sélectionnez l\'application pour utiliser le pilote graphique mis à jour en mode de conception"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Haut-parleur du téléphone"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 444a52e..13361d7 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivé"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Sélectionner une application pour le développement de laquelle utiliser le pilote graphique mis à jour"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Haut-parleur du téléphone"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 8df2697..e8cf009 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Non se poden explorar redes"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ningunha"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Gardada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivadas"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Erro na configuración de IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"En función do uso, debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Debería durar aproximadamente ata a seguinte hora: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Ata: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo restante inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Tempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Tempo restante: máis de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Preguntar sempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Ata a desactivación"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Subscribirse á aplicación para utilizar o controlador de gráficos actualizado en desenvolvemento"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altofalante do teléfono"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 4a92f2a..918920d 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"નેટવર્ક્સ માટે સ્કૅન કરી શકતા નથી"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"કોઈ નહીં"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"સાચવેલા"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"અક્ષમ કર્યો"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP કન્ફિગરેશન નિષ્ફળ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"તમારા વપરાશના આધારે લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"લગભગ <xliff:g id="TIME">%1$s</xliff:g> સુધી ચાલવી જોઈએ"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> સુધી"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> કરતાં ઓછો સમય બાકી છે"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> કરતાં ઓછો સમય બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> કરતાં વધુ સમય બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"દર વખતે પૂછો"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"તમે બંધ ન કરો ત્યાં સુધી"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"હમણાં જ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"અપડેટ કરેલ ગ્રાફિક્સ ડ્રાઇવરનો ઉપયોગ કરવા માટે અૅપ પસંદ કરો"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ફોન સ્પીકર"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6d88c35..890d036 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्क के लिए स्कैन नहीं कर सकता"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"कोई नहीं"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सेव किया गया"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फ़िगरेशन की विफलता"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"आपके इस्तेमाल के हिसाब से बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"बैटरी लगभग <xliff:g id="TIME">%1$s</xliff:g> चलेगी"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> तक"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम समय बचा है"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा चलने लायक बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"हर बार पूछें"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"जब तक आप इसे बंद नहीं करते"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"अभी-अभी"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"डेवलपमेंट में अपडेट किए गए ग्राफ़िक्स ड्राइवर का इस्तेमाल करने के लिए ऐप्लिकेशन में ऑप्ट इन करें"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"फ़ोन स्पीकर"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 32c9a62..1464b91 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Skeniranje mreža nije moguće"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Spremljeno"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-a nije uspjela"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> na temelju vaše upotrebe"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Otprilike bi trebalo trajati do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sad"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Uključi aplikaciju za upotrebu ažuriranog upravljačkog programa u razvoju"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Zvučnik telefona"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index ed19267..c9fdd45 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nem lehet beolvasni a hálózatokat"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nincs"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Mentve"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Letiltva"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurációs hiba"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"A használat alapján nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Nagyjából még ennyit bír: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Eddig: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Kevesebb mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Mindig kérdezzen rá"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Kikapcsolásig"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Az imént"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"A frissített, fejlesztés alatt álló grafikus drivert használja a választott alkalmazás"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefon hangszórója"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 6d516ea..3b13ed1 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Հնարավոր չէ սկանավորել ցանցերը"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ոչ մեկը"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Պահված է"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Անջատված"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP կարգավորման ձախողում"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Լիցքը պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>՝ կախված օգտագործման եղանակից"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Լիցքը (<xliff:g id="LEVEL">%2$s</xliff:g>) պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Լիցքը պետք է, որ բավականացնի մոտ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Մինչև <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Հարցնել ամեն անգամ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Մինչև չանջատեք"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Հենց նոր"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Ընտրված հավելվածը, որը պետք է օգտագործի թարմացված գրաֆիկական սարքավարը մշակման ժամանակ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Հեռախոսի բարձրախոս"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index a5f2317..4d1b2df 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak dapat memindai jaringan"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Tidak ada"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Nonaktif"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan Anda"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Akan bertahan kira-kira sampai <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hingga <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Selalu tanya"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Sampai Anda menonaktifkannya"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Baru saja"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Ikut sertakan aplikasi untuk menggunakan driver grafis yang diupdate dalam pengembangan"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Speaker ponsel"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 6cf09a6..600ffa4 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ekki er hægt að leita að netum"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ekkert"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Vistað"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Óvirkt"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-stillingarvilla"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> miðað við notkun þína"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Ætti að endast til u.þ.b. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Til klukkan <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spyrja í hvert skipti"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Þar til þú slekkur"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Rétt í þessu"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Velja að nota uppfærðan myndefnisrekil í þróun í forriti"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Símahátalari"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index a1b9b82..068aa91 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossibile cercare reti"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nessuna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvata"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Disattivata"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Errore configurazione IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tempo stimato rimanente in base al tuo utilizzo: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Tempo stimato rimanente: <xliff:g id="TIME">%1$s</xliff:g> circa (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Tempo stimato rimanente: <xliff:g id="TIME">%1$s</xliff:g> circa"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Fino alle ore <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Chiedi ogni volta"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Fino alla disattivazione"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Adesso"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Attiva l\'app per utilizzare il driver grafico aggiornato nella versione di sviluppo"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altoparlante telefono"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 1a50622..fa38f77 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"לא ניתן לסרוק לאיתור רשתות"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ללא"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"נשמר"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"מושבת"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"כשל בתצורת IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> על סמך השימוש במכשיר"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"אמורה להחזיק מעמד בערך עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"עד <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"נותרו יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"שאל בכל פעם"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"עד הכיבוי"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"הרגע"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"האפליקציה שנבחרה לשימוש במנהל ההתקן המעודכן לגרפיקה שבפיתוח"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"רמקול של טלפון"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4c544af..9927654 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ネットワークをスキャンできません"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"なし"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"保存済み"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"無効"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP設定エラー"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(使用状況に基づく)"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"電池切れの推定時間: <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> まで"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"毎回確認"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"OFF にするまで"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"たった今"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"更新したグラフィックス ドライバを開発に使用するオプトイン アプリ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"スマートフォンのスピーカー"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 92f3049..7ba0153 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ქსელების სკანირება არა არის შესაძლებელი"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"არცერთი"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"დამახსოვრებულია"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"გამორთულია"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP კონფიგურაციის შეფერხება"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>, მოხმარების გათვალისწინებით"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"უნდა იმუშაოს დაახლოებით <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g>-მდე"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ყოველთვის მკითხეთ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"გამორთვამდე"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ახლახან"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"გააქტიურების აპი, რომელიც გამოიყენებს შემუშავების პროცესში მყოფ, განახლებულ გრაფიკულ დრაივერს"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ტელეფონის დინამიკი"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index b56c6fd..d5b4441 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Желілерді шолу мүмкін емес"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ешқандай"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сақталды"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Өшірілген"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясының қатесі"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Пайдалануға байланысты шамамен <xliff:g id="TIME">%1$s</xliff:g> уақытқа жетеді"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) уақытқа жетеді"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Шамамен <xliff:g id="TIME">%1$s</xliff:g> уақытқа жетеді"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> дейін"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> шамасынан көп уақыт қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Әрдайым сұрау"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Өшірілгенге дейін"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Дәл қазір"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Әзірлеу барысында қолданба жаңартылған графика драйверін пайдаланады"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Телефон динамигі"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 5860473..d1d1c76 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"មិនអាចវិភាគរកបណ្ដាញ"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"គ្មាន"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"បានរក្សាទុក"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"បានបិទ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ការកំណត់រចនាសម្ព័ន្ធ IP បរាជ័យ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> ដោយផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"គួរតែអាចប្រើបានរហូតដល់ម៉ោងប្រហែល <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"រហូតដល់ម៉ោង <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"នៅសល់តិចជាង <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"នៅសល់តិចជាង <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"នៅសល់ច្រើនជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"សួរគ្រប់ពេល"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"រហូតទាល់តែអ្នកបិទ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"អម្បាញ់មិញ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ភ្ជាប់កម្មវិធី ដើម្បីប្រើដ្រាយវើក្រាហ្វិកដែលបានដំឡើងជំនាន់សម្រាប់ការអភិវឌ្ឍ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ឧបករណ៍បំពងសំឡេងទូរសព្ទ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 87e18e6..46759f5 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ಯಾವುದೂ ಇಲ್ಲ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ಉಳಿಸಲಾಗಿದೆ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ನಿಮ್ಮ ಬಳಕೆ ಆಧರಿಸಿ <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"<xliff:g id="TIME">%1$s</xliff:g> ಸಮಯದವರೆಗೆ ಫೋನ್ ರನ್ ಆಗಬೇಕು"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> ರವರೆಗೆ"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ನಿಮಿಷಕ್ಕಿಂತ ಕಡಿಮೆ ಸಮಯ ಉಳಿದಿದೆ"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ಪ್ರತಿ ಬಾರಿ ಕೇಳಿ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ಇದೀಗ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ಅಭಿವೃದ್ಧಿಯಲ್ಲಿ ಅಪ್ಡೇಟ್ ಮಾಡಲಾದ ಗ್ರಾಫಿಕ್ಗಳ ಡ್ರೈವರ್ ಬಳಸಲು ಆ್ಯಪ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ಫೋನ್ ಸ್ಪೀಕರ್"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 3333c0d..067175b 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"네트워크를 검색할 수 없습니다."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"없음"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"저장됨"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"사용 중지됨"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 설정 실패"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"사용량을 기준으로 약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"약 <xliff:g id="TIME">%1$s</xliff:g>까지 사용 가능"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g>까지"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -435,7 +437,7 @@
<string name="cancel" msgid="6859253417269739139">"취소"</string>
<string name="okay" msgid="1997666393121016642">"확인"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"켜기"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"알림 일시중지 사용 설정"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"방해 금지 모드 사용 설정"</string>
<string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"사용 안함"</string>
<string name="zen_interruption_level_priority" msgid="2078370238113347720">"중요 알림만"</string>
<string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"항상 확인"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"사용 중지할 때까지"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"조금 전"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"개발 중인 업데이트된 그래픽 드라이버를 사용할 앱을 선택하세요."</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"휴대전화 스피커"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index cbbc47c..8e994da 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Түйүндөрдү издөө мүмкүн эмес"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Жок"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сакталды"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Өчүрүлгөн"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясы бузулду"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%1$s</xliff:g> кийин өчөт"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) кийин өчөт"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Болжол менен <xliff:g id="TIME">%1$s</xliff:g> кийин өчөт"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> чейин"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ашыгыраак убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Ар дайым суралсын"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Бул функция өчүрүлгөнгө чейин"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Азыр эле"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Иштеп чыгууда жаңыртылган графикалык драйверлерди пайдалануу үчүн колдонмону кошуңуз"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Телефондун динамиги"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 21e4679..7bf46c0 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ບໍ່ສາມາດກວດຫາເຄືອຂ່າຍໄດ້"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ບໍ່ໃຊ້"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ບັນທຶກແລ້ວ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ປິດການນຳໃຊ້"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ການຕັ້ງຄ່າ IP ລົ້ມເຫຼວ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> based on your usage"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Should last until about <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Should last until about <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"ຈົນກວ່າຈະຮອດ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ຖາມທຸກເທື່ອ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ຕອນນີ້"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ເຂົ້າຮ່ວມແອັບເພື່ອໃຊ້ໄດຣເວີກຣາຟິກທີ່ອັບເດດແລ້ວໃນການພັດທະນາ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ລຳໂພງໂທລະສັບ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index cbff9e7..9da3d52 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nepavyksta nuskaityti tinklų"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nėra"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Išsaugotas"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Neleidžiama"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigūracijos triktis"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Pagal tai, kaip naudojama, turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Turėtų išsikrauti maždaug po <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Iki <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Klausti kaskart"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Kol išjungsite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ką tik"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Pasirinkti programą, kuri bus naudojama su atnaujinta kuriama grafikos tvarkykle"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefono garsiakalbis"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index d200828..2233468 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nevar skenēt tīklus"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nav"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saglabāts"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Atspējots"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigurācijas kļūme"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Ņemot vērā lietojumu, darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Darbosies aptuveni līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Līdz <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Atlikušais laiks — mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Atlicis mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Atlicis vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vaicāt katru reizi"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Līdz brīdim, kad izslēgsiet"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Tikko"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Izvēlēties izmantot atjaunināto grafikas dzini šīs lietotnes izstrādē"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Tālruņa skaļrunis"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index db16847..534d154 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да скенира за мрежи"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ниедна"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Зачувано"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Оневозможено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Конфигурирањето ИП не успеа"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> според вашето користење"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Треба да трае до околу <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Секогаш прашувај"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Додека не го исклучите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Неодамнешни"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Прифатете ја апликацијата за да се користи ажурираниот драјвер за графика во програмирање"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Телефонски звучник"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index c3af968..7a335cd 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"നെറ്റ്വർക്കുകൾക്കായി സ്കാൻ ചെയ്യാനായില്ല"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ഒന്നുമില്ല"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"സംരക്ഷിച്ചു"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"പ്രവർത്തനരഹിതമാക്കി"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP കോൺഫിഗറേഷൻ പരാജയം"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"നിങ്ങളുടെ ഉപയോഗത്തെ അടിസ്ഥാനമാക്കി ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ്"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ് (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"ഏകദേശം <xliff:g id="TIME">%1$s</xliff:g> വരെ നീണ്ടുനിൽക്കേണ്ടതാണ്"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> വരെ"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"എപ്പോഴും ചോദിക്കുക"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ഇപ്പോൾ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"വികസനത്തിൽ, അപ്ഡേറ്റ് ചെയ്ത ഗ്രാഫിക്സ് ഡ്രൈവർ ഉപയോഗിക്കാൻ ഓപ്റ്റ് ഇൻ ചെയ്യുക"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ഫോൺ സ്പീക്കർ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 8627e1b..4816643 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Сүлжээнүүдийг скан хийх боломжгүй"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Байхгүй"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Хадгалагдсан"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Идэвхгүйжүүлсэн"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP тохируулга амжилтгүй"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Ойролцоогоор <xliff:g id="TIME">%1$s</xliff:g> хүртэл барих ёстой"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> хүртэл"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Тухай бүрт асуух"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Таныг унтраах хүртэл"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Дөнгөж сая"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Хөгжүүлэлтэд буй шинэчилсэн график драйверийг ашиглахын тулд аппад нэгдэх"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Утасны чанга яригч"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index cd7f175..8ebb182 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्कसाठी स्कॅन करू शकत नाही"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"काहीही नाही"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सेव्ह केले"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फिगरेशन अयशस्वी"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"तुमच्या वापरावर अवलंबून सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकावी"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकेल (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"सुमारे <xliff:g id="TIME">%1$s</xliff:g> पर्यंत टिकावी"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी शिल्लक आहे"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"प्रत्येक वेळी विचारा"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"तुम्ही बंद करेपर्यंत"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"आत्ताच"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"अपडेट केलेले ग्राफिक ड्राइव्हर डेव्हलमेंटमध्ये वापरण्यासाठी अॅप निवडा"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"फोनचा स्पीकर"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index d0b2e12..3593882 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak boleh mengimbas untuk rangkaian"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Tiada"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Dinyahdayakan"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> berdasarkan penggunaan anda"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Seharusnya boleh digunakan hingga kira-kira <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hingga <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Tinggal kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Tanya setiap kali"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Sehingga anda matikan"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sebentar tadi"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Sertakan apl untuk menggunakan pemacu grafik yang dikemas kini dalam pembangunan"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Pembesar suara telefon"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 5f5957c..7ac3742 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ကွန်ယက်များကို စကင်မလုပ်နိုင်ပါ"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"တစ်ခုမျှ မဟုတ်ပါ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"သိမ်းဆည်းပြီး"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ပိတ်ထားသည်"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"သင်၏ အသုံးပြုမှုအပေါ် အခြေခံ၍ <xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည်"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"<xliff:g id="TIME">%1$s</xliff:g> ခန့်အထိ သုံးနိုင်သည်"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> အထိ"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ခန့်သာ ကျန်တော့သည်"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> အောက်သာ ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"အမြဲမေးပါ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"သင်ပိတ်လိုက်သည် အထိ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ယခုလေးတင်"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ဆော့ဖ်ဝဲရေးဆွဲမှုအတွင်း အပ်ဒိတ်လုပ်ထားသော ဂရပ်ဖစ်ဒရိုင်ဗာကို အသုံးပြုရန် အက်ပ်ကို ရွေးချယ်ပါ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ဖုန်းစပီကာ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 3c240f8..ae9c5f2 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan ikke søke etter nettverk"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Lagret"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Slått av"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurasjonsfeil"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>, basert på bruken din"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Skal vare til omtrent <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Til <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Spør hver gang"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Til du slår av"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Nå nettopp"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Velg app for å bruke en oppdatert grafikkdriver som er under utvikling"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefonhøyttaler"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 1699870..0b4510fd 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"तपाईंको प्रयोगका आधारमा लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ब्याट्री लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"लगभग <xliff:g id="TIME">%1$s</xliff:g> सम्म टिक्नु पर्छ"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> सम्म"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी छ"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"प्रत्येक पटक सोध्नुहोस्"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"तपाईंले निष्क्रिय नपार्दासम्म"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"अहिले भर्खरै"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"विकासको क्रममा अद्यावधिक गरिएको ग्राफिक ड्राइभर प्रयोग गर्न अप्ट इन गर्नुहोस्"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"फोनको स्पिकर"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 738df94..f227e1c 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan niet zoeken naar netwerken"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Opgeslagen"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Uitgeschakeld"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-configuratie mislukt"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> op basis van je gebruik"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Is nog genoeg tot ongeveer <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Tot <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> resterend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> resterend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Altijd vragen"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Totdat je uitschakelt"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Zojuist"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Meld een app aan om het geüpdatete grafische stuurprogramma in ontwikkeling te gebruiken"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefoonluidspreker"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 2d39cc6..bf8493a 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ନେଟ୍ୱର୍କଗୁଡ଼ିକୁ ଖୋଜିପାରୁନାହିଁ"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"କିଛି ନାହିଁ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ସେଭ୍ ହୋଇଗଲା"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ଅକ୍ଷମ ହୋଇଛି"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ବ୍ୟାଟେରୀ <xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ ଚାଲିବ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ବ୍ୟାଟେରୀ ପାଖାପାଖି <xliff:g id="TIME">%1$s</xliff:g> ଚାଲିବ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"ବ୍ୟାଟେରୀ <xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ ଚାଲିବ"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ରୁ କମ୍ ସମୟ ବଳକା ଅଛି"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ରୁ କମ୍ ସମୟ ବଳକା ଅଛି (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ରୁ ଅଧିକ ସମୟ ବଳକା ଅଛି(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ପ୍ରତ୍ୟେକ ଥର ପଚାରନ୍ତୁ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ DND ଅନ୍ ରହିବ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ଏହିକ୍ଷଣି"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ଡେଭଲପ୍ମେଣ୍ଟରେ ଅପ୍ଡେଟ୍ ଗ୍ରାଫିକ୍ସ ଡ୍ରାଇଭର୍ ବ୍ୟବହାର କରିବାକୁ ଆପ୍ଟ ଇନ୍ ଅପ୍ଲିକେସନ୍"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ଫୋନ୍ ସ୍ପିକର୍"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 61f0447..f948a7e 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ਨੈਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ਕੋਈ ਨਹੀਂ"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"ਰੱਖਿਅਤ ਕੀਤਾ"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ਅਯੋਗ ਬਣਾਇਆ"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ਕੌਂਫਿਗਰੇਸ਼ਨ ਅਸਫਲਤਾ"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"ਲਗਭਗ <xliff:g id="TIME">%1$s</xliff:g> ਚੱਲੇਗਾ"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> ਤੱਕ"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ਹਰ ਵਾਰ ਪੁੱਛੋ"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ਹੁਣੇ ਹੀ"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ਅੱਪਡੇਟ ਕੀਤੇ ਵਿਕਾਸ-ਅਧੀਨ ਗ੍ਰਾਫਿਕਸ ਡਰਾਈਵਰ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਐਪ ਦੀ ਚੋਣ ਕਰੋ"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ਫ਼ੋਨ ਦਾ ਸਪੀਕਰ"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 519f82c..c75a894 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nie można wyszukać sieci."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Brak"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Zapisana"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Wyłączona"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Błąd konfiguracji IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Na podstawie Twojego sposobu korzystania jeszcze około <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Powinno wystarczyć do <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Powinno wystarczyć do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Pozostało ponad: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Zawsze pytaj"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dopóki nie wyłączysz"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Przed chwilą"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Wybierz aplikację, która ma używać opracowywanego sterownika grafiki"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Głośnik telefonu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 16844a2..c273f59 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Até <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Ative o app para usar o driver gráfico atualizado no desenvolvimento"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Alto-falante do smartphone"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index f01ddfa..26e4729 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar redes"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> com base na sua utilização."</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Deve durar até cerca da(s) <xliff:g id="TIME">%1$s</xliff:g>."</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Até à(s) <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Até ser desativado"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Optar pela aplicação para utilizar a placa gráfica atualizada em desenvolvimento"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altifalante do telemóvel"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 16844a2..c273f59 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> com base no seu uso"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Deve durar até cerca de <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Até <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s)"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Ative o app para usar o driver gráfico atualizado no desenvolvimento"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Alto-falante do smartphone"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 8a7b440..94f4842 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nu se poate scana pentru rețele"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Niciuna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Salvată"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Dezactivată"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Eroare de configurație IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"În baza utilizării, ar trebui să reziste până la aproximativ <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Ar trebui să reziste până la <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Ar trebui să reziste până la <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Până la <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"a mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"A mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"A mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Întreabă de fiecare dată"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Până când dezactivați"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Chiar acum"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Aplicația pentru înscriere pentru a folosi driverul actualizat al plăcii grafice este în dezvoltare"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Difuzorul telefonului"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 31274d1..1c331d8 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не удалось начать поиск сетей."</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Нет"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сохранено"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Отключено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ошибка IP-конфигурации"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"При текущем уровне использования заряда хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Заряда (<xliff:g id="LEVEL">%2$s</xliff:g>) хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Заряда хватит примерно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Осталось менее <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит менее чем на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит более чем на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Всегда спрашивать"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Пока вы не отключите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Только что"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Приложение будет использовать обновленный драйвер графической системы (на стадии разработки)"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Встроенный динамик"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index b22e068..608ff7f 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ජාල සඳහා පරිලෝකනය කළ නොහැක"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"කිසිවක් නැත"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"සුරකින ලදි"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"අබලයි"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP වින්යාස කිරීම අසාර්ථකයි"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"ඔබේ භාවිතය මත පදනම්ව <xliff:g id="TIME">%1$s</xliff:g> පමන වන තෙක් තිබිය යුතුය"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>) පමණ වන තෙක් තිබිය යුතුය"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"<xliff:g id="TIME">%1$s</xliff:g> පමණ වන තෙක් තිබිය යුතුය"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> දක්වා"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිව ඇත"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"සෑම විටම ඉල්ලන්න"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ඔබ ක්රියාවිරහිත කරන තුරු"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"මේ දැන්"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"වැඩිදියුණු වෙමින් ඇති යාවත්කාලීන කළ චිත්රක ධාවකය භාවිත කිරීමට යෙදුමට ඇතුළු වන්න"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"දුරකථන ස්පීකරය"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 43923b8..2f76ef9 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Siete sa nedajú vyhľadávať"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Žiadne"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuté"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Mal by vydržať približne do <xliff:g id="TIME">%1$s</xliff:g> v závislosti od využitia"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Mal by vydržať približne <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Mal by vydržať približne do <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vždy sa opýtať"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokiaľ túto funkciu nevypnete"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Teraz"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Prihlásiť aplikáciu, ktorá má používať aktualizovaný ovládač grafickej karty vo vývoji"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Reproduktor telefónu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 6d392fe..64124cb 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ni mogoče iskati omrežij"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Brez"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Shranjeno"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogočeno"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-ja ni uspela"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Naprava bi morala glede na način uporabe delovati do približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Naprava bi morala delovati do približno <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Naprava bi morala delovati do približno <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Do <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Preostalo manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Preostanek: manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Preostali čas delovanja: manj kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Vedno vprašaj"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokler ne izklopite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Pravkar"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Omogočena aplikacija za uporabo posodobljenega grafičnega gonilnika pri razvoju"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Zvočnik telefona"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index e05a019..25d575e 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nuk mund të skanojë për rrjete"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Asnjë"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"U ruajt"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Të çaktivizuara"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Dështim në konfigurimin e IP-së"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> bazuar në përdorimin tënd"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Duhet të zgjasë deri në rreth <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Deri në <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> të mbetura"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Mbeten më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mbeten më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Pyet çdo herë"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Deri sa ta çaktivizosh"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Pikërisht tani"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Prano aplikacionin për të përdorur drejtuesin e përditësuar të grafikës që është në zhvillim"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Altoparlanti i telefonit"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 371b909..b58b47c 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Није могуће скенирати мреже"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Нема"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Сачувано"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Онемогућено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурација је отказала"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> на основу коришћења"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Трајаће приближно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -448,4 +450,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Увек питај"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Омогући апликацију за коришћење управљачког програма графичке катице у развоју"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Звучник телефона"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e6872bb..7198b84 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Det går inte att söka efter nätverk"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Sparat"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Inaktiverad"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfel"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> utifrån din användning"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Bör räcka ungefär till klockan <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Till kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Fråga varje gång"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Tills du inaktiverar funktionen"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Nyss"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Välj om appen ska använda den uppdaterade grafikdrivrutinen under utveckling"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Mobilens högtalare"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 23efb91..657b54f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Haiwezi kutambaza mitandao"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Hamna"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Imehifadhiwa"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Imezimwa"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Haikuweza Kusanidi IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Inapaswa kudumu hadi <xliff:g id="TIME">%1$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Inapaswa kudumu kwa takribani <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Inapaswa kudumu hadi <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hadi <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uliza kila wakati"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Hadi utakapoizima"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sasa hivi"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Chagua programu itakayotumia kiendeshaji cha michoro kilichosasishwa katika hatua ya kusanidi"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Spika ya simu"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 53ba738..59b42d8 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"நெட்வொர்க்குகளுக்கு ஸ்கேன் செய்யப்படவில்லை"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ஏதுமில்லை"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"சேமிக்கப்பட்டது"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"முடக்கப்பட்டது"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP உள்ளமைவில் தோல்வி"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"நீங்கள் பயன்படுத்துவதன் அடிப்படையில் <xliff:g id="TIME">%1$s</xliff:g> வரை உபயோகிக்க முடியும்"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"<xliff:g id="TIME">%1$s</xliff:g> வரை பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"<xliff:g id="TIME">%1$s</xliff:g> வரை பயன்படுத்த முடியும்"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> வரை"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்த முடியும்"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>க்கும் மேல் பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ஒவ்வொரு முறையும் கேள்"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"ஆஃப் செய்யும் வரை"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"சற்றுமுன்"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"உருவாக்கத்திலுள்ள புதுப்பிக்கப்பட்ட கிராஃபிக்ஸ் டிரைவரைப் பயன்படுத்த ஆப்ஸைத் தேர்ந்தெடுக்கவும்"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"மொபைல் ஸ்பீக்கர்"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c8c6b4c..af233da 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"నెట్వర్క్ల కోసం స్కాన్ చేయడం సాధ్యపడదు"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ఏదీ లేదు"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"సేవ్ చేయబడింది"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"నిలిపివేయబడింది"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"మీ వినియోగం ఆధారంగా దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"దాదాపు <xliff:g id="TIME">%1$s</xliff:g> వరకు ఉండాలి"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> వరకు"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ప్రతిసారి అడుగు"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"మీరు ఆఫ్ చేసే వరకు"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ఇప్పుడే"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"అభివృద్దిలో అప్డేట్ చేసిన గ్రాఫిక్ డ్రైవర్ను ఉపయోగించడానికి యాప్ని ప్రారంభించండి"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ఫోన్ స్పీకర్"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index d293d59..636c3f2 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"ไม่สามารถสแกนหาเครือข่าย"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"ไม่มี"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"บันทึกแล้ว"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"ปิดอยู่"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"การกำหนดค่า IP ล้มเหลว"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> เมื่อดูจากการใช้งานของคุณ"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"น่าจะใช้งานได้ถึงเวลาประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"จนถึง <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"เหลืออีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"เหลือเวลาอีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ถามทุกครั้ง"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"จนกว่าคุณจะปิด"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"เมื่อสักครู่"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"เลือกใช้แอปเพื่อใช้ไดรเวอร์กราฟิกที่อัปเดตในการพัฒนา"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"ลำโพงโทรศัพท์"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 9da4561..1bcc36a 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Hindi makapag-scan ng mga network"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Wala"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Na-save"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Naka-disable"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Pagkabigo ng Configuration ng IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Tatagal hanggang mga <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Hanggang <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Magtanong palagi"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Hanggang sa i-off mo"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ngayon lang"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"App sa pag-opt in para magamit ang na-update na graphics driver na ginagawa"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Speaker ng telepono"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 2d5cd7f..ff669f6 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ağlar taranamıyor"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Yok"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Kaydedildi"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Devre dışı"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Yapılandırması Hatası"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Kullanımınıza göre saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Saat yaklaşık <xliff:g id="TIME">%1$s</xliff:g> olana kadar kullanılabilmelidir"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Şu saate kadar: <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"En fazla <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"En çok <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"En az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Her zaman sor"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Siz kapatana kadar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Az önce"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Güncellenmiş grafik sürücüsünü geliştirme ortamında kullanmak için uygulamayı kaydedin"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefon hoparlörü"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 512ea86..2ded8c1 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Неможливо здійснити сканування мереж"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Немає"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Збережено"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Вимкнено"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Помилка конфігурації IP-адреси"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"На основі даних про використання, вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Вистачить приблизно до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"До <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Залишилося понад <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -449,4 +451,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Запитувати щоразу"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Доки ви не вимкнете"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Щойно"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Вибраний додаток, який використовуватиме оновлений графічний драйвер під час розробки"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Динамік телефона"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 84ad3ed..7dc4690 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"نیٹ ورکس کیلئے اسکین نہيں کر سکتے ہیں"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"کوئی نہیں"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"محفوظ کردیا گیا"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"غیر فعال"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP کنفیگریشن کی ناکامی"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"تقریباً <xliff:g id="TIME">%1$s</xliff:g> تک بیٹری چلے گی"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> تک"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"ہر بار پوچھیں"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"یہاں تک کہ آپ آف کر دیں"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ابھی ابھی"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"ڈیولپمنٹ میں اپ ڈیٹ کردہ گرافکس ڈرائیور کو استعمال کرنے کے لیے ایپ آپٹ ان کریں"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"فون اسپیکر"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index af2ada5..5f92c9a 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tarmoqlarni tekshirib chiqishni iloji bo‘lmadi"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Hech qanday"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Saqlandi"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"O‘chiq"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP manzilini sozlab bo‘lmadi"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"<xliff:g id="TIME">%1$s</xliff:g> gacha"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Har safar so‘ralsin"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Bekor qilinmaguncha"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Hozir"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Ilova yangilangan grafik drayverdan (hali ishlov jarayonida) foydalanadi"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Telefon karnayi"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index f454127..eb10fb1 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Không thể dò tìm mạng"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Không"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Đã lưu"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Đã tắt"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Lỗi cấu hình IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Sẽ hết pin cho tới khoảng <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Cho đến <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Luôn hỏi"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Cho đến khi bạn tắt"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Vừa xong"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Chọn ứng dụng để sử dụng trình điều khiển đồ họa được cập nhật trong giai đoạn phát triển"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Loa điện thoại"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 10a20be..7b14138 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"无法扫描网络"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"无"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已保存"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 配置失败"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根据您的使用情况,估计大约还能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"目前电量为 <xliff:g id="LEVEL">%2$s</xliff:g>,估计大约还能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"估计大约还能用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"直到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩余电池续航时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"电量剩余使用时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"电量剩余使用时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都询问"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"直到您将其关闭"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"刚刚"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"为应用启用更新后的显卡驱动,以在开发过程中使用"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"手机扬声器"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 1510545..48b6959 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃瞄網絡"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根據您的使用情況,電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"電量剩餘約 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"還可用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"剩餘電量時間少於 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"還有少於 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"還有超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"直至您關閉為止"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"請選取應用程式,以在開發階段使用更新的顯示卡驅動程式"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"手機喇叭"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 90c0d80..684569b 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃描網路"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"根據你的使用情形,預估可持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"目前電量 <xliff:g id="LEVEL">%2$s</xliff:g>,預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"預估還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"還能持續使用到<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"直到你關閉為止"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"選取要在開發階段使用最新版繪圖驅動程式的應用程式"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"手機喇叭"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index e4f9f4d7..d107a5a 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -21,6 +21,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ayikwazi ukuhlola amanethiwekhi"</string>
+ <string name="wifi_security_none" msgid="7985461072596594400">"Lutho"</string>
<string name="wifi_remembered" msgid="4955746899347821096">"Kulondoloziwe"</string>
<string name="wifi_disabled_generic" msgid="4259794910584943386">"Akusebenzi"</string>
<string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ukwehluleka kokulungiswa kwe-IP"</string>
@@ -374,6 +375,7 @@
<string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
<string name="power_discharge_by" msgid="6453537733650125582">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_discharge_by_only" msgid="107616694963545745">"Kumele ihlale cishe kube ngu-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Kuze kube ngu-<xliff:g id="TIME">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Kusele okungaphansi kunokungu-<xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
<string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Ngaphansi kuka-<xliff:g id="THRESHOLD">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Ngaphezu kuka-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
@@ -447,4 +449,6 @@
<string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Buza njalo"</string>
<string name="zen_mode_forever" msgid="2704305038191592967">"Uze uvale isikrini"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Khona manje"</string>
+ <string name="updated_gfx_driver_dev_opt_in_app_summary" msgid="5309913444094165199">"Uhlelo lokusebenza lokukhetha ukungena olungasebenzisa idrayivu yamagrafikhi ekuthuthukiseni"</string>
+ <string name="media_transfer_phone_device_name" msgid="1003823744105758574">"Isipikha sefoni"</string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index cbb6e82..b2c12b2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -855,6 +855,10 @@
GlobalSettingsProto.MultiSim.SMS_PROMPT);
p.end(multiSimToken);
+ dumpSetting(s, p,
+ Global.NATIVE_FLAGS_HEALTH_CHECK_ENABLED,
+ GlobalSettingsProto.NATIVE_FLAGS_HEALTH_CHECK_ENABLED);
+
final long netstatsToken = p.start(GlobalSettingsProto.NETSTATS);
dumpSetting(s, p,
Settings.Global.NETSTATS_ENABLED,
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
index f492208..4891e50 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
@@ -30,6 +30,12 @@
int VERSION = 1;
void startPendingIntentDismissingKeyguard(PendingIntent intent);
+
+ /**
+ * Similar to {@link #startPendingIntentDismissingKeyguard(PendingIntent, Runnable)}, but
+ * allow you to specify the callback that is executed after the intent is sent.
+ */
+ void startPendingIntentDismissingKeyguard(PendingIntent intent, Runnable intentSentCallback);
void startActivity(Intent intent, boolean dismissShade);
void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade);
void startActivity(Intent intent, boolean dismissShade, Callback callback);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index 70258c2..2aba3fa 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -20,7 +20,6 @@
import android.graphics.Rect;
import android.os.IBinder;
import android.view.Surface;
-import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
public class TransactionCompat {
@@ -53,7 +52,7 @@
}
public TransactionCompat setSize(SurfaceControlCompat surfaceControl, int w, int h) {
- mTransaction.setSize(surfaceControl.mSurfaceControl, w, h);
+ mTransaction.setBufferSize(surfaceControl.mSurfaceControl, w, h);
return this;
}
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index e1b8dc8..9e7c5ba 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -36,6 +36,15 @@
}
@Override
+ public void startPendingIntentDismissingKeyguard(PendingIntent intent,
+ Runnable intentSentCallback) {
+ if (mActualStarter == null) {
+ return;
+ }
+ mActualStarter.startPendingIntentDismissingKeyguard(intent, intentSentCallback);
+ }
+
+ @Override
public void startActivity(Intent intent, boolean dismissShade) {
if (mActualStarter == null) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index c6dcfc7..416cc59 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -23,10 +23,10 @@
import static com.android.systemui.bubbles.BubbleMovementHelper.EDGE_OVERLAP;
import android.app.Notification;
-import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
+import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -57,6 +57,11 @@
// When a bubble is dismissed, recreate it as a notification
public static final boolean DEBUG_DEMOTE_TO_NOTIF = false;
+ // Secure settings
+ private static final String ENABLE_AUTO_BUBBLE_MESSAGES = "experiment_autobubble_messaging";
+ private static final String ENABLE_AUTO_BUBBLE_ONGOING = "experiment_autobubble_ongoing";
+ private static final String ENABLE_AUTO_BUBBLE_ALL = "experiment_autobubble_all";
+
private Context mContext;
private BubbleDismissListener mDismissListener;
private BubbleStateChangeListener mStateChangeListener;
@@ -318,11 +323,15 @@
/**
* Whether the notification should bubble or not.
*/
- public static boolean shouldAutoBubble(NotificationData.Entry entry, int priority,
- boolean canAppOverlay) {
- if (!DEBUG_ENABLE_AUTO_BUBBLE || entry.isBubbleDismissed()) {
+ public static boolean shouldAutoBubble(Context context, NotificationData.Entry entry) {
+ if (entry.isBubbleDismissed()) {
return false;
}
+
+ boolean autoBubbleMessages = shouldAutoBubbleMessages(context) || DEBUG_ENABLE_AUTO_BUBBLE;
+ boolean autoBubbleOngoing = shouldAutoBubbleOngoing(context) || DEBUG_ENABLE_AUTO_BUBBLE;
+ boolean autoBubbleAll = shouldAutoBubbleAll(context) || DEBUG_ENABLE_AUTO_BUBBLE;
+
StatusBarNotification n = entry.notification;
boolean hasRemoteInput = false;
if (n.getNotification().actions != null) {
@@ -333,12 +342,28 @@
}
}
}
+
Class<? extends Notification.Style> style = n.getNotification().getNotificationStyle();
- boolean shouldBubble = priority >= NotificationManager.IMPORTANCE_HIGH
- || Notification.MessagingStyle.class.equals(style)
+ boolean isMessageType = Notification.MessagingStyle.class.equals(style)
|| Notification.CATEGORY_MESSAGE.equals(n.getNotification().category)
- || hasRemoteInput
- || canAppOverlay;
- return shouldBubble && !entry.isBubbleDismissed();
+ || hasRemoteInput;
+ return (isMessageType && autoBubbleMessages)
+ || (n.isOngoing() && autoBubbleOngoing)
+ || autoBubbleAll;
+ }
+
+ private static boolean shouldAutoBubbleMessages(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_AUTO_BUBBLE_MESSAGES, 0) != 0;
+ }
+
+ private static boolean shouldAutoBubbleOngoing(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_AUTO_BUBBLE_ONGOING, 0) != 0;
+ }
+
+ private static boolean shouldAutoBubbleAll(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_AUTO_BUBBLE_ALL, 0) != 0;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 01a2345..1dd31010 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -24,20 +24,21 @@
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
-import android.os.Build;
import android.os.Handler;
+import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
/**
* Controls the screen brightness when dozing.
*/
public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachine.Part,
SensorEventListener {
+ private static final boolean DEBUG_AOD_BRIGHTNESS = SystemProperties
+ .getBoolean("debug.aod_brightness", false);
protected static final String ACTION_AOD_BRIGHTNESS =
"com.android.systemui.doze.AOD_BRIGHTNESS";
protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
@@ -83,11 +84,9 @@
mSensorToScrimOpacity = sensorToScrimOpacity;
if (mDebuggable) {
- Dependency.get(Dependency.BG_HANDLER).post(()-> {
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_AOD_BRIGHTNESS);
- mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
- });
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_AOD_BRIGHTNESS);
+ mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
}
}
@@ -97,7 +96,7 @@
this(context, service, sensorManager, lightSensor, host, handler,
context.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze),
- policy.screenBrightnessArray, policy.dimmingScrimArray, Build.IS_DEBUGGABLE);
+ policy.screenBrightnessArray, policy.dimmingScrimArray, DEBUG_AOD_BRIGHTNESS);
}
@Override
@@ -126,9 +125,7 @@
private void onDestroy() {
setLightSensorEnabled(false);
if (mDebuggable) {
- Dependency.get(Dependency.BG_HANDLER).post(()-> {
- mContext.unregisterReceiver(this);
- });
+ mContext.unregisterReceiver(this);
}
}
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 e447def..8495fd3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -19,6 +19,8 @@
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
+import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
@@ -65,6 +67,7 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -90,8 +93,8 @@
public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5;
public static final int MESSAGE_ANIMATION_ENDED = 6;
- private static final long INITIAL_DISMISS_DELAY = 3500;
- private static final long POST_INTERACTION_DISMISS_DELAY = 2000;
+ private static final int INITIAL_DISMISS_DELAY = 3500;
+ private static final int POST_INTERACTION_DISMISS_DELAY = 2000;
private static final long MENU_FADE_DURATION = 125;
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
@@ -105,6 +108,7 @@
private final List<RemoteAction> mActions = new ArrayList<>();
+ private AccessibilityManager mAccessibilityManager;
private View mViewRoot;
private Drawable mBackgroundDrawable;
private View mMenuContainer;
@@ -194,6 +198,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.pip_menu_activity);
+ mAccessibilityManager = getSystemService(AccessibilityManager.class);
mBackgroundDrawable = new ColorDrawable(Color.BLACK);
mBackgroundDrawable.setAlpha(0);
mViewRoot = findViewById(R.id.background);
@@ -639,8 +644,10 @@
mHandler.removeCallbacks(mFinishRunnable);
}
- private void repostDelayedFinish(long delay) {
+ private void repostDelayedFinish(int delay) {
+ int recommendedTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(delay,
+ FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS);
mHandler.removeCallbacks(mFinishRunnable);
- mHandler.postDelayed(mFinishRunnable, delay);
+ mHandler.postDelayed(mFinishRunnable, recommendedTimeout);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 03a573e..6a9f24c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -368,7 +368,7 @@
private void onAccessibilityShowMenu() {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
- mMovementBounds, false /* allowMenuTimeout */, willResizeMenu());
+ mMovementBounds, true /* allowMenuTimeout */, willResizeMenu());
}
private boolean handleTouchEvent(MotionEvent ev) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 8b434a5..496aa0e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -323,7 +323,9 @@
post(new Runnable() {
@Override
public void run() {
- handleShowingDetail(detail, x, y, false /* toggleQs */);
+ if (isAttachedToWindow()) {
+ handleShowingDetail(detail, x, y, false /* toggleQs */);
+ }
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 2ee5443..7be5461 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -150,34 +150,42 @@
}
private void logActionClick(View view) {
+ Integer actionIndex = (Integer)
+ view.getTag(com.android.internal.R.id.notification_action_index_tag);
+ if (actionIndex == null) {
+ Log.e(TAG, "Couldn't retrieve the actionIndex from the clicked button");
+ return;
+ }
ViewParent parent = view.getParent();
- String key = getNotificationKeyForParent(parent);
- if (key == null) {
+ StatusBarNotification statusBarNotification = getNotificationForParent(parent);
+ if (statusBarNotification == null) {
Log.w(TAG, "Couldn't determine notification for click.");
return;
}
- int index = -1;
+ String key = statusBarNotification.getKey();
+ int buttonIndex = -1;
// If this is a default template, determine the index of the button.
if (view.getId() == com.android.internal.R.id.action0 &&
parent != null && parent instanceof ViewGroup) {
ViewGroup actionGroup = (ViewGroup) parent;
- index = actionGroup.indexOfChild(view);
+ buttonIndex = actionGroup.indexOfChild(view);
}
final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
final int rank = mEntryManager.getNotificationData().getRank(key);
+ final Notification.Action action =
+ statusBarNotification.getNotification().actions[actionIndex];
final NotificationVisibility nv = NotificationVisibility.obtain(key, rank, count, true);
try {
- mBarService.onNotificationActionClick(key, index, nv);
+ mBarService.onNotificationActionClick(key, buttonIndex, action, nv, false);
} catch (RemoteException e) {
// Ignore
}
}
- private String getNotificationKeyForParent(ViewParent parent) {
+ private StatusBarNotification getNotificationForParent(ViewParent parent) {
while (parent != null) {
if (parent instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) parent)
- .getStatusBarNotification().getKey();
+ return ((ExpandableNotificationRow) parent).getStatusBarNotification();
}
parent = parent.getParent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index 37bdc1c..f5d6904 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -15,12 +15,15 @@
*/
package com.android.systemui.statusbar;
+import android.app.Notification;
import android.os.RemoteException;
import android.util.ArraySet;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import java.util.Set;
@@ -32,6 +35,9 @@
private IStatusBarService mBarService;
private Set<String> mSendingKeys = new ArraySet<>();
private Callback mCallback;
+ private final NotificationEntryManager mEntryManager =
+ Dependency.get(NotificationEntryManager.class);
+
public SmartReplyController() {
mBarService = Dependency.get(IStatusBarService.class);
@@ -57,6 +63,24 @@
}
/**
+ * Notifies StatusBarService a smart action is clicked.
+ */
+ public void smartActionClicked(
+ NotificationData.Entry entry, int actionIndex, Notification.Action action,
+ boolean generatedByAssistant) {
+ final int count = mEntryManager.getNotificationData().getActiveNotifications().size();
+ final int rank = mEntryManager.getNotificationData().getRank(entry.key);
+ final NotificationVisibility nv =
+ NotificationVisibility.obtain(entry.key, rank, count, true);
+ try {
+ mBarService.onNotificationActionClick(
+ entry.key, actionIndex, action, nv, generatedByAssistant);
+ } catch (RemoteException e) {
+ // Nothing to do, system going down
+ }
+ }
+
+ /**
* Have we posted an intent to an app about sending a smart reply from the
* notification with this key.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index e333729..7970f16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -24,7 +24,6 @@
import android.annotation.Nullable;
import android.app.Notification;
-import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@@ -766,7 +765,7 @@
}
NotificationData.Entry entry = new NotificationData.Entry(sbn, ranking);
- if (shouldAutoBubble(entry)) {
+ if (BubbleController.shouldAutoBubble(getContext(), entry)) {
entry.setIsBubble(true);
}
@@ -1207,17 +1206,6 @@
}
}
-
- /**
- * Whether a bubble is appropriate to auto-bubble or not.
- */
- private boolean shouldAutoBubble(NotificationData.Entry entry) {
- int priority = mNotificationData.getImportance(entry.key);
- NotificationChannel channel = mNotificationData.getChannel(entry.key);
- boolean canAppOverlay = channel != null && channel.canOverlayApps();
- return BubbleController.shouldAutoBubble(entry, priority, canAppOverlay);
- }
-
/**
* Callback for NotificationEntryManager.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
index 247c1ab..a194eef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisibilityLocationProvider.java
@@ -16,15 +16,13 @@
package com.android.systemui.statusbar.notification;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-
/**
* An object that can determine the visibility of a Notification.
*/
public interface VisibilityLocationProvider {
/**
- * Returns whether an ExpandableNotificationRow is in a visible location or not.
+ * Returns whether an Entry is in a visible location or not.
*
* @param entry
* @return true if row is in a visible location
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index a4fdc08..92d1b45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -57,7 +57,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Collections;
import java.util.List;
/**
@@ -1520,7 +1519,8 @@
smartRepliesAndActions.smartReplies, mSmartReplyController, entry);
}
if (smartRepliesAndActions.smartActions != null) {
- smartReplyView.addSmartActions(smartRepliesAndActions.smartActions);
+ smartReplyView.addSmartActions(
+ smartRepliesAndActions.smartActions, mSmartReplyController, entry);
}
smartReplyContainer.setVisibility(View.VISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 7895a8e..3b407b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -18,10 +18,7 @@
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
-import static android.service.notification.NotificationListenerService.Ranking
- .USER_SENTIMENT_NEGATIVE;
-
-import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import android.app.INotificationManager;
import android.app.NotificationChannel;
@@ -43,7 +40,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.plugins.ActivityStarter;
@@ -188,13 +184,7 @@
} else if (gutsView instanceof AppOpsInfo) {
initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
} else if (gutsView instanceof NotificationInfo) {
- int action;
- if (item instanceof NotificationMenuRow.NotificationInfoMenuItem) {
- action = ((NotificationMenuRow.NotificationInfoMenuItem) item).mAction;
- } else {
- action = ACTION_NONE;
- }
- initializeNotificationInfo(row, (NotificationInfo) gutsView, action);
+ initializeNotificationInfo(row, (NotificationInfo) gutsView);
}
return true;
} catch (Exception e) {
@@ -253,13 +243,11 @@
* Sets up the {@link NotificationInfo} inside the notification row's guts.
* @param row view to set up the guts for
* @param notificationInfoView view to set up/bind within {@code row}
- * @param action The action to take immediately upon binding, if any.
*/
@VisibleForTesting
void initializeNotificationInfo(
final ExpandableNotificationRow row,
- NotificationInfo notificationInfoView,
- @NotificationInfo.NotificationInfoAction int action) throws Exception {
+ NotificationInfo notificationInfoView) throws Exception {
NotificationGuts guts = row.getGuts();
StatusBarNotification sbn = row.getStatusBarNotification();
String packageName = sbn.getPackageName();
@@ -303,8 +291,7 @@
isForBlockingHelper,
row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
row.getEntry().noisy,
- row.getEntry().importance,
- action);
+ row.getEntry().importance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 0d36d2c..213ac70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -187,14 +187,13 @@
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean isNoisy,
- int importance,
- @NotificationInfoAction int action)
+ int importance)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
- importance, action);
+ importance);
}
public void bindNotification(
@@ -212,8 +211,7 @@
boolean isForBlockingHelper,
boolean isUserSentimentNegative,
boolean isNoisy,
- int importance,
- @NotificationInfoAction int action)
+ int importance)
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -255,10 +253,6 @@
bindHeader();
bindPrompt();
bindButtons();
-
- if (action != ACTION_NONE) {
- swapContent(action, false /* don't animate */);
- }
}
private void bindHeader() throws RemoteException {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index b6ff6fc..948d2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -17,9 +17,6 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
-import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_BLOCK;
-import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
-import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_TOGGLE_SILENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -46,7 +43,6 @@
import com.android.systemui.statusbar.AlphaOptimizedImageView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.notification.row.NotificationInfo.NotificationInfoAction;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -73,7 +69,7 @@
private Context mContext;
private FrameLayout mMenuContainer;
- private NotificationInfoMenuItem mInfoItem;
+ private NotificationMenuItem mInfoItem;
private MenuItem mAppOpsItem;
private MenuItem mSnoozeItem;
private ArrayList<MenuItem> mLeftMenuItems;
@@ -248,36 +244,30 @@
if (!isForeground) {
// Only show snooze for non-foreground notifications
mSnoozeItem = createSnoozeItem(mContext);
- mLeftMenuItems.add(mSnoozeItem);
}
- mInfoItem = createInfoItem(mContext);
- if (!NotificationUtils.useNewInterruptionModel(mContext)) {
- mLeftMenuItems.add(mInfoItem);
- }
-
mAppOpsItem = createAppOpsItem(mContext);
- mLeftMenuItems.add(mAppOpsItem);
-
if (NotificationUtils.useNewInterruptionModel(mContext)) {
- if (!mParent.getIsNonblockable()) {
- mRightMenuItems.add(createBlockItem(mContext, mInfoItem.getGutsView()));
- }
- // TODO(kprevas): this is duplicated logic
- // but it's currently spread across NotificationGutsManager and NotificationInfo.
- // Try to consolidate and reuse here.
- boolean canToggleSilent = !mParent.getIsNonblockable()
- && !isForeground
- && mParent.getEntry().noisy;
- if (canToggleSilent) {
- int channelImportance = mParent.getEntry().channel.getImportance();
- int effectiveImportance =
- channelImportance == NotificationManager.IMPORTANCE_UNSPECIFIED
- ? mParent.getEntry().importance : channelImportance;
- mRightMenuItems.add(createToggleSilentItem(mContext, mInfoItem.getGutsView(),
- effectiveImportance < NotificationManager.IMPORTANCE_DEFAULT));
- }
+ int channelImportance = mParent.getEntry().channel.getImportance();
+ int effectiveImportance =
+ channelImportance == NotificationManager.IMPORTANCE_UNSPECIFIED
+ ? mParent.getEntry().importance : channelImportance;
+ mInfoItem = createInfoItem(mContext,
+ effectiveImportance < NotificationManager.IMPORTANCE_DEFAULT);
} else {
- mRightMenuItems.addAll(mLeftMenuItems);
+ mInfoItem = createInfoItem(mContext);
+ }
+
+ if (!NotificationUtils.useNewInterruptionModel(mContext)) {
+ if (!isForeground) {
+ mRightMenuItems.add(mSnoozeItem);
+ }
+ mRightMenuItems.add(mInfoItem);
+ mRightMenuItems.add(mAppOpsItem);
+ mLeftMenuItems.addAll(mRightMenuItems);
+ } else {
+ mRightMenuItems.add(mInfoItem);
+ mRightMenuItems.add(mAppOpsItem);
+ mRightMenuItems.add(mSnoozeItem);
}
populateMenuViews();
@@ -634,13 +624,24 @@
return snooze;
}
- static NotificationInfoMenuItem createInfoItem(Context context) {
+ static NotificationMenuItem createInfoItem(Context context) {
Resources res = context.getResources();
String infoDescription = res.getString(R.string.notification_menu_gear_description);
NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
R.layout.notification_info, null, false);
- return new NotificationInfoMenuItem(context, infoDescription, infoContent,
- R.drawable.ic_settings, ACTION_NONE);
+ return new NotificationMenuItem(context, infoDescription, infoContent,
+ R.drawable.ic_settings);
+ }
+
+ static NotificationMenuItem createInfoItem(Context context, boolean isCurrentlySilent) {
+ Resources res = context.getResources();
+ String infoDescription = res.getString(R.string.notification_menu_gear_description);
+ NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
+ R.layout.notification_info, null, false);
+ int iconResId = isCurrentlySilent
+ ? R.drawable.ic_notifications_alert
+ : R.drawable.ic_notifications_silence;
+ return new NotificationMenuItem(context, infoDescription, infoContent, iconResId);
}
static MenuItem createAppOpsItem(Context context) {
@@ -651,29 +652,6 @@
return info;
}
- private static MenuItem createBlockItem(Context context, NotificationInfo gutsView) {
- return new NotificationInfoMenuItem(
- context,
- context.getResources().getString(R.string.inline_stop_button),
- gutsView,
- R.drawable.ic_notification_block,
- ACTION_BLOCK);
- }
-
- private static MenuItem createToggleSilentItem(Context context, NotificationInfo gutsView,
- boolean isCurrentlySilent) {
- return new NotificationInfoMenuItem(
- context,
- isCurrentlySilent
- ? context.getResources().getString(R.string.inline_silent_button_alert)
- : context.getResources().getString(R.string.inline_silent_button_silent),
- gutsView,
- isCurrentlySilent
- ? R.drawable.ic_notifications_alert
- : R.drawable.ic_notifications_silence,
- ACTION_TOGGLE_SILENT);
- }
-
private void addMenuView(MenuItem item, ViewGroup parent) {
View menuView = item.getMenuView();
if (menuView != null) {
@@ -789,23 +767,4 @@
return mContentDescription;
}
}
-
- /** A {@link NotificationMenuItem} with an associated {@link NotificationInfoAction}. */
- public static class NotificationInfoMenuItem extends NotificationMenuItem {
-
- @NotificationInfoAction
- int mAction;
-
- public NotificationInfoMenuItem(Context context, String contentDescription,
- NotificationInfo content, int iconResId,
- @NotificationInfoAction int action) {
- super(context, contentDescription, content, iconResId);
- this.mAction = action;
- }
-
- @Override
- public NotificationInfo getGutsView() {
- return (NotificationInfo) super.getGutsView();
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
index 1002f9e..b83ebc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
-
import android.annotation.NonNull;
import android.hardware.input.InputManager;
import android.os.Handler;
@@ -35,10 +33,8 @@
*/
public class NavigationBackAction extends NavigationGestureAction {
- private static final String PULL_HOME_GO_BACK_PROP = "quickstepcontroller_homegoesback";
private static final String BACK_AFTER_END_PROP =
"quickstepcontroller_homegoesbackwhenend";
- private static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;
@@ -60,23 +56,13 @@
}
@Override
- public int requiresTouchDownHitTarget() {
- return HIT_TARGET_HOME;
- }
-
- @Override
- public boolean requiresDragWithHitTarget() {
- return true;
- }
-
- @Override
public boolean canPerformAction() {
return mProxySender.getBackButtonAlpha() > 0;
}
@Override
public boolean isEnabled() {
- return swipeHomeGoBackGestureEnabled();
+ return !getGlobalBoolean(NavigationPrototypeController.NAVBAR_EXPERIMENTS_DISABLED);
}
@Override
@@ -110,13 +96,8 @@
mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
- private boolean swipeHomeGoBackGestureEnabled() {
- return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
- && getGlobalBoolean(PULL_HOME_GO_BACK_PROP);
- }
-
private boolean shouldExecuteBackOnUp() {
- return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
+ return !getGlobalBoolean(NavigationPrototypeController.NAVBAR_EXPERIMENTS_DISABLED)
&& getGlobalBoolean(BACK_AFTER_END_PROP);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 5db43ea..33d022c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -77,6 +77,8 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.NavigationBarCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.phone.NavigationPrototypeController.GestureAction;
+import com.android.systemui.statusbar.phone.NavigationPrototypeController.OnPrototypeChangedListener;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -146,6 +148,8 @@
private RecentsOnboarding mRecentsOnboarding;
private NotificationPanelView mPanelView;
+ private NavigationPrototypeController mPrototypeController;
+ private NavigationGestureAction[] mDefaultGestureMap;
private QuickScrubAction mQuickScrubAction;
private QuickStepAction mQuickStepAction;
private NavigationBackAction mBackAction;
@@ -261,6 +265,18 @@
}
};
+ private OnPrototypeChangedListener mPrototypeListener = new OnPrototypeChangedListener() {
+ @Override
+ public void onGestureRemap(int[] actions) {
+ updateNavigationGestures();
+ }
+
+ @Override
+ public void onBackButtonVisibilityChanged(boolean visible) {
+ getBackButton().setVisibility(visible ? VISIBLE : GONE);
+ }
+ };
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -309,6 +325,14 @@
mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
mBackAction = new NavigationBackAction(this, mOverviewProxyService);
+ mDefaultGestureMap = new NavigationGestureAction[] {
+ mQuickStepAction, null /* swipeDownAction*/, null /* swipeLeftAction */,
+ mQuickScrubAction
+ };
+
+ mPrototypeController = new NavigationPrototypeController(mHandler, mContext);
+ mPrototypeController.register();
+ mPrototypeController.setOnPrototypeChangedListener(mPrototypeListener);
}
public BarTransitions getBarTransitions() {
@@ -323,8 +347,32 @@
mPanelView = panel;
if (mGestureHelper instanceof QuickStepController) {
((QuickStepController) mGestureHelper).setComponents(this);
- ((QuickStepController) mGestureHelper).setGestureActions(mQuickStepAction,
- null /* swipeDownAction*/, mBackAction, mQuickScrubAction);
+ updateNavigationGestures();
+ }
+ }
+
+ private void updateNavigationGestures() {
+ if (mGestureHelper instanceof QuickStepController) {
+ final int[] assignedMap = mPrototypeController.getGestureActionMap();
+ ((QuickStepController) mGestureHelper).setGestureActions(
+ getNavigationActionFromType(assignedMap[0], mDefaultGestureMap[0]),
+ getNavigationActionFromType(assignedMap[1], mDefaultGestureMap[1]),
+ getNavigationActionFromType(assignedMap[2], mDefaultGestureMap[2]),
+ getNavigationActionFromType(assignedMap[3], mDefaultGestureMap[3]));
+ }
+ }
+
+ private NavigationGestureAction getNavigationActionFromType(@GestureAction int actionType,
+ NavigationGestureAction defaultAction) {
+ switch(actionType) {
+ case NavigationPrototypeController.ACTION_QUICKSTEP:
+ return mQuickStepAction;
+ case NavigationPrototypeController.ACTION_QUICKSCRUB:
+ return mQuickScrubAction;
+ case NavigationPrototypeController.ACTION_BACK:
+ return mBackAction;
+ default:
+ return defaultAction;
}
}
@@ -1043,6 +1091,7 @@
if (mGestureHelper != null) {
mGestureHelper.destroy();
}
+ mPrototypeController.unregister();
setUpSwipeUpOnboarding(false);
for (int i = 0; i < mButtonDispatchers.size(); ++i) {
mButtonDispatchers.valueAt(i).onDestroy();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
new file mode 100644
index 0000000..e8c0bf1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+
+import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Coordinates with the prototype settings plugin app that uses Settings.Global to allow different
+ * prototypes to run in the system. The class will handle communication changes from the settings
+ * app and call back to listeners.
+ */
+public class NavigationPrototypeController extends ContentObserver {
+ private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback";
+
+ static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
+ private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK})
+ @interface GestureAction {}
+ static final int ACTION_DEFAULT = 0;
+ static final int ACTION_QUICKSTEP = 1;
+ static final int ACTION_QUICKSCRUB = 2;
+ static final int ACTION_BACK = 3;
+
+ private OnPrototypeChangedListener mListener;
+
+ /**
+ * Each index corresponds to a different action set in QuickStepController
+ * {@see updateSwipeLTRBackSetting}
+ */
+ private int[] mActionMap = new int[4];
+
+ private final Context mContext;
+
+ public NavigationPrototypeController(Handler handler, Context context) {
+ super(handler);
+ mContext = context;
+ updateSwipeLTRBackSetting();
+ }
+
+ public void setOnPrototypeChangedListener(OnPrototypeChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Observe all the settings to react to from prototype settings
+ */
+ public void register() {
+ registerObserver(HIDE_BACK_BUTTON_SETTING);
+ registerObserver(GESTURE_MATCH_SETTING);
+ }
+
+ /**
+ * Disable observing settings to react to from prototype settings
+ */
+ public void unregister() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ if (!selfChange && mListener != null) {
+ try {
+ final String path = uri.getPath();
+ if (path.endsWith(GESTURE_MATCH_SETTING)) {
+ // Get the settings gesture map corresponding to each action
+ // {@see updateSwipeLTRBackSetting}
+ updateSwipeLTRBackSetting();
+ mListener.onGestureRemap(mActionMap);
+ } else if (path.endsWith(HIDE_BACK_BUTTON_SETTING)) {
+ mListener.onBackButtonVisibilityChanged(
+ !getGlobalBool(HIDE_BACK_BUTTON_SETTING));
+ }
+ } catch (SettingNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Retrieve the action map to apply to the quick step controller
+ * @return an action map
+ */
+ int[] getGestureActionMap() {
+ return mActionMap;
+ }
+
+ /**
+ * Since Settings.Global cannot pass arrays, use a string to represent each character as a
+ * gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
+ * Number: [up] [down] [left] [right]
+ */
+ private void updateSwipeLTRBackSetting() {
+ String value = Settings.Global.getString(mContext.getContentResolver(),
+ GESTURE_MATCH_SETTING);
+ if (value != null) {
+ for (int i = 0; i < mActionMap.length; ++i) {
+ mActionMap[i] = Character.getNumericValue(value.charAt(i));
+ }
+ }
+ }
+
+ private boolean getGlobalBool(String name) throws SettingNotFoundException {
+ return Settings.Global.getInt(mContext.getContentResolver(), name) == 1;
+ }
+
+ private void registerObserver(String name) {
+ mContext.getContentResolver()
+ .registerContentObserver(Settings.Global.getUriFor(name), false, this);
+ }
+
+ public interface OnPrototypeChangedListener {
+ void onGestureRemap(@GestureAction int[] actions);
+ void onBackButtonVisibilityChanged(boolean visible);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 0eff4d4..497fdfb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -30,9 +30,9 @@
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.Rect;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
@@ -100,6 +100,7 @@
private NavigationGestureAction mCurrentAction;
private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES];
+ private final Rect mLastLayoutRect = new Rect();
private final OverviewProxyService mOverviewEventSender;
private final Context mContext;
private final StatusBar mStatusBar;
@@ -107,7 +108,6 @@
private final Matrix mTransformLocalMatrix = new Matrix();
public QuickStepController(Context context) {
- final Resources res = context.getResources();
mContext = context;
mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
mOverviewEventSender = Dependency.get(OverviewProxyService.class);
@@ -142,6 +142,8 @@
if (action != null) {
action.setBarState(true, mNavBarPosition, mDragHPositive, mDragVPositive);
action.onDarkIntensityChange(mDarkIntensity);
+ action.onLayout(true /* changed */, mLastLayoutRect.left, mLastLayoutRect.top,
+ mLastLayoutRect.right, mLastLayoutRect.bottom);
}
}
}
@@ -382,6 +384,7 @@
action.onLayout(changed, left, top, right, bottom);
}
}
+ mLastLayoutRect.set(left, top, right, bottom);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 82f9e03..2fc3adc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -196,7 +196,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -4324,7 +4323,14 @@
}, afterKeyguardGone);
}
+ @Override
public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+ startPendingIntentDismissingKeyguard(intent, null);
+ }
+
+ @Override
+ public void startPendingIntentDismissingKeyguard(
+ final PendingIntent intent, @Nullable final Runnable intentSentCallback) {
final boolean afterKeyguardGone = intent.isActivity()
&& PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
@@ -4343,6 +4349,9 @@
if (intent.isActivity()) {
mAssistManager.hideAssist();
}
+ if (intentSentCallback != null) {
+ intentSentCallback.run();
+ }
}, afterKeyguardGone);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 88ff078..f36066c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -208,12 +208,14 @@
* Add smart actions to be shown next to smart replies. Only the actions that fit into the
* notification are shown.
*/
- public void addSmartActions(SmartActions smartActions) {
+ public void addSmartActions(SmartActions smartActions,
+ SmartReplyController smartReplyController, NotificationData.Entry entry) {
int numSmartActions = smartActions.actions.size();
for (int n = 0; n < numSmartActions; n++) {
Notification.Action action = smartActions.actions.get(n);
if (action.actionIntent != null) {
- Button actionButton = inflateActionButton(getContext(), this, action);
+ Button actionButton = inflateActionButton(
+ getContext(), this, n, smartActions, smartReplyController, entry);
addView(actionButton);
}
}
@@ -270,7 +272,10 @@
}
@VisibleForTesting
- Button inflateActionButton(Context context, ViewGroup root, Notification.Action action) {
+ Button inflateActionButton(Context context, ViewGroup root, int actionIndex,
+ SmartActions smartActions, SmartReplyController smartReplyController,
+ NotificationData.Entry entry) {
+ Notification.Action action = smartActions.actions.get(actionIndex);
Button button = (Button) LayoutInflater.from(context).inflate(
R.layout.smart_action_button, root, false);
button.setText(action.title);
@@ -283,7 +288,10 @@
button.setCompoundDrawables(iconDrawable, null, null, null);
button.setOnClickListener(view ->
- getActivityStarter().startPendingIntentDismissingKeyguard(action.actionIntent));
+ getActivityStarter().startPendingIntentDismissingKeyguard(
+ action.actionIntent,
+ () -> smartReplyController.smartActionClicked(
+ entry, actionIndex, action, smartActions.fromAssistant)));
// TODO(b/119010281): handle accessibility
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index b3b45eb..f94ba95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -121,9 +121,9 @@
when(mEnvironment.isDeviceProvisioned()).thenReturn(true);
when(mEnvironment.isNotificationForCurrentProfiles(any())).thenReturn(true);
mNotificationData = new TestableNotificationData();
- Dependency.get(InitController.class).executePostInitTasks();
mNotificationData.updateRanking(mock(NotificationListenerService.RankingMap.class));
mRow = new NotificationTestHelper(getContext()).createRow();
+ Dependency.get(InitController.class).executePostInitTasks();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index 7fee0ee..f0fa788 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -18,7 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 2797969..84bfae6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -20,8 +20,7 @@
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking
- .USER_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -54,7 +53,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
-import android.util.Log;
import android.view.View;
import com.android.systemui.SysuiTestCase;
@@ -63,8 +61,7 @@
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager
- .OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -298,8 +295,7 @@
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_NONE);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -316,8 +312,7 @@
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0),
- eq(NotificationInfo.ACTION_NONE));
+ eq(0));
}
@Test
@@ -329,8 +324,7 @@
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_NONE);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -347,8 +341,7 @@
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0),
- eq(NotificationInfo.ACTION_NONE));
+ eq(0));
}
@Test
@@ -361,8 +354,7 @@
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_NONE);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -379,8 +371,7 @@
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(true) /*isNoisy */,
- eq(0),
- eq(NotificationInfo.ACTION_NONE));
+ eq(0));
}
@Test
@@ -393,8 +384,7 @@
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_NONE);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -411,8 +401,7 @@
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(IMPORTANCE_DEFAULT),
- eq(NotificationInfo.ACTION_NONE));
+ eq(IMPORTANCE_DEFAULT));
}
@Test
@@ -425,8 +414,7 @@
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_NONE);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -443,8 +431,7 @@
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0),
- eq(NotificationInfo.ACTION_NONE));
+ eq(0));
}
@Test
@@ -456,8 +443,7 @@
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView,
- NotificationInfo.ACTION_BLOCK);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -474,8 +460,7 @@
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0),
- eq(NotificationInfo.ACTION_BLOCK));
+ eq(0));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 985827a..3dd493f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -187,7 +187,7 @@
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -200,7 +200,7 @@
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -209,7 +209,7 @@
public void testBindNotification_noDelegate() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(GONE, nameView.getVisibility());
final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
@@ -228,7 +228,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(VISIBLE, nameView.getVisibility());
assertTrue(nameView.getText().toString().contains("Other"));
@@ -240,7 +240,7 @@
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -257,7 +257,7 @@
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -269,7 +269,7 @@
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -278,7 +278,7 @@
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -291,7 +291,7 @@
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -300,7 +300,7 @@
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -309,7 +309,7 @@
public void testBindNotification_BlockButton() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
@@ -323,7 +323,7 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -335,7 +335,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_LOW);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -347,7 +347,7 @@
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -360,7 +360,7 @@
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_LOW);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -372,7 +372,7 @@
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(GONE, block.getVisibility());
@@ -387,7 +387,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -399,7 +399,7 @@
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -411,7 +411,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
- }, null, false, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, null, false, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -420,11 +420,11 @@
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
- }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, null, true, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -433,7 +433,7 @@
public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
}
@@ -442,7 +442,7 @@
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
}
@@ -455,7 +455,7 @@
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -468,7 +468,7 @@
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -479,7 +479,7 @@
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ null, true, true, false, IMPORTANCE_DEFAULT);
final TextView blockView = mNotificationInfo.findViewById(R.id.block);
assertEquals(GONE, blockView.getVisibility());
}
@@ -488,7 +488,7 @@
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
- true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -498,7 +498,7 @@
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -509,7 +509,7 @@
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -520,7 +520,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -534,7 +534,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
mTestableLooper.processAllMessages();
@@ -548,7 +548,7 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
mTestableLooper.processAllMessages();
@@ -562,7 +562,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
mTestableLooper.processAllMessages();
@@ -576,7 +576,7 @@
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -591,7 +591,7 @@
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -609,8 +609,8 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT
+ );
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -631,8 +631,8 @@
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */,
- true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT
+ );
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -653,8 +653,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -682,8 +681,7 @@
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -712,7 +710,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
false /* isNonblockable */, true /* isForBlockingHelper */,
true, true /* isUserSentimentNegative */, false /* isNoisy */,
- IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
@@ -731,8 +729,7 @@
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -755,7 +752,7 @@
true /* isForBlockingHelper */,
true,
false /* isUserSentimentNegative */,
- false /* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false /* isNoisy */, IMPORTANCE_DEFAULT);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
@@ -770,7 +767,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -784,7 +781,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -817,7 +814,7 @@
false /* isNonblockable */,
true /* isForBlockingHelper */,
true /* isUserSentimentNegative */,
- false/* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false/* isNoisy */, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -839,7 +836,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -854,7 +851,7 @@
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -875,7 +872,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -893,7 +890,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -915,7 +912,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -937,7 +934,7 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -958,7 +955,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -980,7 +977,7 @@
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1002,7 +999,7 @@
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_LOW);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1023,7 +1020,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1039,7 +1036,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1056,7 +1053,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- }, null, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, null, null, true, true, false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -1074,8 +1071,8 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- }, null, null, true, false, false, IMPORTANCE_DEFAULT,
- NotificationInfo.ACTION_NONE);
+ }, null, null, true, false, false, IMPORTANCE_DEFAULT
+ );
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -1111,7 +1108,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -1139,7 +1136,7 @@
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ }, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -1158,7 +1155,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ null, true, false, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1179,7 +1176,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1202,7 +1199,7 @@
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, true, false, IMPORTANCE_DEFAULT);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1219,7 +1216,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1232,7 +1229,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1245,7 +1242,7 @@
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1259,7 +1256,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1273,7 +1270,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1285,7 +1282,7 @@
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+ false, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1293,60 +1290,4 @@
waitForStopButton();
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
}
-
- @Test
- public void testBindNotificationWithInitialBlockAction() throws Exception {
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_BLOCK);
- waitForUndoButton();
- mNotificationInfo.handleCloseControls(true, false);
-
- mTestableLooper.processAllMessages();
- ArgumentCaptor<NotificationChannel> updated =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), eq(TEST_UID), updated.capture());
- assertTrue((updated.getValue().getUserLockedFields()
- & USER_LOCKED_IMPORTANCE) != 0);
- assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
- }
-
- @Test
- public void testBindNotificationWithInitialSilenceAction() throws Exception {
- mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_TOGGLE_SILENT);
- waitForUndoButton();
- mNotificationInfo.handleCloseControls(true, false);
-
- mTestableLooper.processAllMessages();
- ArgumentCaptor<NotificationChannel> updated =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), eq(TEST_UID), updated.capture());
- assertTrue((updated.getValue().getUserLockedFields()
- & USER_LOCKED_IMPORTANCE) != 0);
- assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
- }
-
- @Test
- public void testBindNotificationWithInitialUnSilenceAction() throws Exception {
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW, NotificationInfo.ACTION_TOGGLE_SILENT);
- waitForUndoButton();
- mNotificationInfo.handleCloseControls(true, false);
-
- mTestableLooper.processAllMessages();
- ArgumentCaptor<NotificationChannel> updated =
- ArgumentCaptor.forClass(NotificationChannel.class);
- verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
- anyString(), eq(TEST_UID), updated.capture());
- assertTrue((updated.getValue().getUserLockedFields()
- & USER_LOCKED_IMPORTANCE) != 0);
- assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index b6e3fc1..df7aeab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -62,6 +62,7 @@
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -430,12 +431,18 @@
private void setSmartActions(String[] actionTitles) {
mView.resetSmartSuggestions(mContainer);
- mView.addSmartActions(new SmartReplyView.SmartActions(createActions(actionTitles), false));
+ mView.addSmartActions(
+ new SmartReplyView.SmartActions(createActions(actionTitles), false),
+ mLogger,
+ mEntry);
}
private void setSmartRepliesAndActions(CharSequence[] choices, String[] actionTitles) {
setSmartReplies(choices);
- mView.addSmartActions(new SmartReplyView.SmartActions(createActions(actionTitles), false));
+ mView.addSmartActions(
+ new SmartReplyView.SmartActions(createActions(actionTitles), false),
+ mLogger,
+ mEntry);
}
private ViewGroup buildExpectedView(CharSequence[] choices, int lineCount) {
@@ -553,7 +560,7 @@
mView.getChildAt(2).performClick();
- verify(mActivityStarter, times(1)).startPendingIntentDismissingKeyguard(any());
+ verify(mActivityStarter, times(1)).startPendingIntentDismissingKeyguard(any(), any());
}
@Test
@@ -738,7 +745,9 @@
}
private Button inflateActionButton(Notification.Action action) {
- return mView.inflateActionButton(getContext(), mView, action);
+ return mView.inflateActionButton(getContext(), mView, 0,
+ new SmartReplyView.SmartActions(Collections.singletonList(action), false),
+ mLogger, mEntry);
}
@Test
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
index 8d691ff..12e7376 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationGestureHandler.java
@@ -273,33 +273,6 @@
private void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
- if (DEBUG_ALL) Slog.i(LOG_TAG, "dispatchTransformedEvent(event = " + event + ")");
-
- // If the touchscreen event is within the magnified portion of the screen we have
- // to change its location to be where the user thinks he is poking the
- // UI which may have been magnified and panned.
- if (mMagnificationController.isMagnifying()
- && event.isFromSource(SOURCE_TOUCHSCREEN)
- && mMagnificationController.magnificationRegionContains(
- event.getX(), event.getY())) {
- final float scale = mMagnificationController.getScale();
- final float scaledOffsetX = mMagnificationController.getOffsetX();
- final float scaledOffsetY = mMagnificationController.getOffsetY();
- final int pointerCount = event.getPointerCount();
- PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
- PointerProperties[] properties = getTempPointerPropertiesWithMinSize(
- pointerCount);
- for (int i = 0; i < pointerCount; i++) {
- event.getPointerCoords(i, coords[i]);
- coords[i].x = (coords[i].x - scaledOffsetX) / scale;
- coords[i].y = (coords[i].y - scaledOffsetY) / scale;
- event.getPointerProperties(i, properties[i]);
- }
- event = MotionEvent.obtain(event.getDownTime(),
- event.getEventTime(), event.getAction(), pointerCount, properties,
- coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0, event.getSource(),
- event.getFlags());
- }
if (DEBUG_EVENT_STREAM) {
storeEventInto(mDebugOutputEventHistory, event);
try {
diff --git a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
index ab639c3..2bca34d 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentTimeoutParameters.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
import android.content.ContentResolver;
import android.os.Handler;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerConstants.java b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
index e3fa0dc..785d3ca 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerConstants.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerConstants.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
import android.app.AlarmManager;
import android.content.ContentResolver;
diff --git a/services/backup/java/com/android/server/backup/GlobalBackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
similarity index 98%
rename from services/backup/java/com/android/server/backup/GlobalBackupManagerService.java
rename to services/backup/java/com/android/server/backup/BackupManagerService.java
index 9a1662e..0b06f28 100644
--- a/services/backup/java/com/android/server/backup/GlobalBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -62,7 +62,7 @@
* incoming calls to the appropriate per-user {@link UserBackupManagerService} to handle the
* corresponding backup/restore operation.
*/
-public class GlobalBackupManagerService {
+public class BackupManagerService {
public static final String TAG = "BackupManagerService";
public static final boolean DEBUG = true;
public static final boolean MORE_DEBUG = false;
@@ -82,8 +82,8 @@
return sInstance;
}
- /** Helper to create the {@link GlobalBackupManagerService} instance. */
- public static GlobalBackupManagerService create(
+ /** Helper to create the {@link BackupManagerService} instance. */
+ public static BackupManagerService create(
Context context,
Trampoline parent,
HandlerThread backupThread) {
@@ -116,7 +116,7 @@
// This dir on /cache is managed directly in init.rc
File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
- return new GlobalBackupManagerService(
+ return new BackupManagerService(
context,
parent,
backupThread,
@@ -127,8 +127,8 @@
private UserBackupManagerService mUserBackupManagerService;
- /** Instantiate a new instance of {@link GlobalBackupManagerService}. */
- public GlobalBackupManagerService(
+ /** Instantiate a new instance of {@link BackupManagerService}. */
+ public BackupManagerService(
Context context,
Trampoline trampoline,
HandlerThread backupThread,
diff --git a/services/backup/java/com/android/server/backup/FileMetadata.java b/services/backup/java/com/android/server/backup/FileMetadata.java
index 84d987d..fe75041 100644
--- a/services/backup/java/com/android/server/backup/FileMetadata.java
+++ b/services/backup/java/com/android/server/backup/FileMetadata.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupAgent;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index ce02476..82638b4 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -61,7 +61,7 @@
@Override
public boolean onStartJob(JobParameters params) {
mParams = params;
- Trampoline service = GlobalBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
return service.beginFullBackup(this);
}
@@ -69,7 +69,7 @@
public boolean onStopJob(JobParameters params) {
if (mParams != null) {
mParams = null;
- Trampoline service = GlobalBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
service.endFullBackup();
}
return false;
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index 8156095..f2e7435 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
import android.app.AlarmManager;
import android.app.job.JobInfo;
@@ -118,7 +118,7 @@
}
// Time to run a key/value backup!
- Trampoline service = GlobalBackupManagerService.getInstance();
+ Trampoline service = BackupManagerService.getInstance();
try {
service.backupNow();
} catch (RemoteException e) {}
diff --git a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
index dd91381..edc2379 100644
--- a/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
+++ b/services/backup/java/com/android/server/backup/ProcessedPackagesJournal.java
@@ -46,7 +46,7 @@
final class ProcessedPackagesJournal {
private static final String TAG = "ProcessedPackagesJournal";
private static final String JOURNAL_FILE_NAME = "processed";
- private static final boolean DEBUG = GlobalBackupManagerService.DEBUG;
+ private static final boolean DEBUG = BackupManagerService.DEBUG;
// using HashSet instead of ArraySet since we expect 100-500 elements range
@GuardedBy("mProcessedPackages")
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 22edebc..59629aa 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -16,7 +16,7 @@
package com.android.server.backup;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
@@ -52,12 +52,12 @@
import java.io.PrintWriter;
/**
- * A proxy to the {@link GlobalBackupManagerService} implementation.
+ * A proxy to the {@link BackupManagerService} implementation.
*
- * <p>This is an external interface to the {@link GlobalBackupManagerService} which is being
- * accessed via published binder {@link GlobalBackupManagerService.Lifecycle}. This lets us turn
- * down the heavy implementation object on the fly without disturbing binders that have been cached
- * somewhere in the system.
+ * <p>This is an external interface to the {@link BackupManagerService} which is being accessed via
+ * published binder {@link BackupManagerService.Lifecycle}. This lets us turn down the heavy
+ * implementation object on the fly without disturbing binders that have been cached somewhere in
+ * the system.
*
* <p>Trampoline determines whether the backup service is available. It can be disabled in the
* following two ways:
@@ -89,7 +89,7 @@
private final boolean mGlobalDisable;
private final Object mStateLock = new Object();
- private volatile GlobalBackupManagerService mService;
+ private volatile BackupManagerService mService;
private HandlerThread mHandlerThread;
public Trampoline(Context context) {
@@ -116,12 +116,12 @@
return mContext;
}
- protected GlobalBackupManagerService createBackupManagerService() {
- return GlobalBackupManagerService.create(mContext, this, mHandlerThread);
+ protected BackupManagerService createBackupManagerService() {
+ return BackupManagerService.create(mContext, this, mHandlerThread);
}
/**
- * Initialize {@link GlobalBackupManagerService} if the backup service is not disabled. Only the
+ * Initialize {@link BackupManagerService} if the backup service is not disabled. Only the
* system user can initialize the service.
*/
/* package */ void initializeService(int userId) {
@@ -145,11 +145,10 @@
}
/**
- * Called from {@link GlobalBackupManagerService.Lifecycle} when the system user is unlocked.
- * Attempts to initialize {@link GlobalBackupManagerService} and set backup state for the system
- * user.
+ * Called from {@link BackupManagerService.Lifecycle} when the system user is unlocked. Attempts
+ * to initialize {@link BackupManagerService} and set backup state for the system user.
*
- * @see GlobalBackupManagerService#unlockSystemUser()
+ * @see BackupManagerService#unlockSystemUser()
*/
void unlockSystemUser() {
mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
@@ -162,7 +161,7 @@
initializeService(UserHandle.USER_SYSTEM);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- GlobalBackupManagerService service = mService;
+ BackupManagerService service = mService;
if (service != null) {
Slog.i(TAG, "Unlocking system user");
service.unlockSystemUser();
@@ -234,7 +233,7 @@
@Override
public void dataChanged(String packageName) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.dataChanged(packageName);
}
@@ -243,7 +242,7 @@
@Override
public void initializeTransports(String[] transportNames, IBackupObserver observer)
throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.initializeTransports(transportNames, observer);
}
@@ -252,7 +251,7 @@
@Override
public void clearBackupData(String transportName, String packageName)
throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.clearBackupData(transportName, packageName);
}
@@ -260,7 +259,7 @@
@Override
public void agentConnected(String packageName, IBinder agent) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.agentConnected(packageName, agent);
}
@@ -268,7 +267,7 @@
@Override
public void agentDisconnected(String packageName) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.agentDisconnected(packageName);
}
@@ -276,7 +275,7 @@
@Override
public void restoreAtInstall(String packageName, int token) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.restoreAtInstall(packageName, token);
}
@@ -284,7 +283,7 @@
@Override
public void setBackupEnabled(boolean isEnabled) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setBackupEnabled(isEnabled);
}
@@ -292,7 +291,7 @@
@Override
public void setAutoRestore(boolean doAutoRestore) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setAutoRestore(doAutoRestore);
}
@@ -300,7 +299,7 @@
@Override
public void setBackupProvisioned(boolean isProvisioned) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.setBackupProvisioned(isProvisioned);
}
@@ -308,25 +307,25 @@
@Override
public boolean isBackupEnabled() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.isBackupEnabled() : false;
}
@Override
public boolean setBackupPassword(String currentPw, String newPw) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.setBackupPassword(currentPw, newPw) : false;
}
@Override
public boolean hasBackupPassword() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.hasBackupPassword() : false;
}
@Override
public void backupNow() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.backupNow();
}
@@ -337,7 +336,7 @@
boolean includeShared, boolean doWidgets, boolean allApps,
boolean allIncludesSystem, boolean doCompress, boolean doKeyValue, String[] packageNames)
throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.adbBackup(fd, includeApks, includeObbs, includeShared, doWidgets,
allApps, allIncludesSystem, doCompress, doKeyValue, packageNames);
@@ -346,7 +345,7 @@
@Override
public void fullTransportBackup(String[] packageNames) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.fullTransportBackup(packageNames);
}
@@ -354,7 +353,7 @@
@Override
public void adbRestore(ParcelFileDescriptor fd) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.adbRestore(fd);
}
@@ -364,7 +363,7 @@
public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword,
String encryptionPassword, IFullBackupRestoreObserver observer)
throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.acknowledgeAdbBackupOrRestore(token, allow,
curPassword, encryptionPassword, observer);
@@ -373,7 +372,7 @@
@Override
public String getCurrentTransport() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getCurrentTransport() : null;
}
@@ -384,25 +383,25 @@
@Override
@Nullable
public ComponentName getCurrentTransportComponent() {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getCurrentTransportComponent() : null;
}
@Override
public String[] listAllTransports() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.listAllTransports() : null;
}
@Override
public ComponentName[] listAllTransportComponents() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.listAllTransportComponents() : null;
}
@Override
public String[] getTransportWhitelist() {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getTransportWhitelist() : null;
}
@@ -414,7 +413,7 @@
String currentDestinationString,
@Nullable Intent dataManagementIntent,
String dataManagementLabel) {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.updateTransportAttributes(
transportComponent,
@@ -428,14 +427,14 @@
@Override
public String selectBackupTransport(String transport) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.selectBackupTransport(transport) : null;
}
@Override
public void selectBackupTransportAsync(ComponentName transport,
ISelectBackupTransportCallback listener) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.selectBackupTransportAsync(transport, listener);
} else {
@@ -451,38 +450,38 @@
@Override
public Intent getConfigurationIntent(String transport) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getConfigurationIntent(transport) : null;
}
@Override
public String getDestinationString(String transport) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getDestinationString(transport) : null;
}
@Override
public Intent getDataManagementIntent(String transport) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getDataManagementIntent(transport) : null;
}
@Override
public String getDataManagementLabel(String transport) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getDataManagementLabel(transport) : null;
}
@Override
public IRestoreSession beginRestoreSession(String packageName, String transportID)
throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.beginRestoreSession(packageName, transportID) : null;
}
@Override
public void opComplete(int token, long result) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.opComplete(token, result);
}
@@ -490,26 +489,26 @@
@Override
public long getAvailableRestoreToken(String packageName) {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.getAvailableRestoreToken(packageName) : 0;
}
@Override
public boolean isAppEligibleForBackup(String packageName) {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.isAppEligibleForBackup(packageName) : false;
}
@Override
public String[] filterAppsEligibleForBackup(String[] packages) {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.filterAppsEligibleForBackup(packages) : null;
}
@Override
public int requestBackup(String[] packages, IBackupObserver observer,
IBackupManagerMonitor monitor, int flags) throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc == null) {
return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
}
@@ -518,7 +517,7 @@
@Override
public void cancelBackups() throws RemoteException {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.cancelBackups();
}
@@ -528,7 +527,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.dump(fd, pw, args);
} else {
@@ -539,12 +538,12 @@
// Full backup/restore entry points - non-Binder; called directly
// by the full-backup scheduled job
/* package */ boolean beginFullBackup(FullBackupJob scheduledJob) {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
return (svc != null) ? svc.beginFullBackup(scheduledJob) : false;
}
/* package */ void endFullBackup() {
- GlobalBackupManagerService svc = mService;
+ BackupManagerService svc = mService;
if (svc != null) {
svc.endFullBackup();
}
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 4855ae0..fe16afe 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -18,10 +18,10 @@
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG_SCHEDULING;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_FULL_CONFIRMATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_OP_COMPLETE;
@@ -2665,7 +2665,7 @@
boolean wasEnabled = mEnabled;
synchronized (this) {
// TODO(b/118520567): Clean up writing backup enabled logic.
- GlobalBackupManagerService.writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
+ BackupManagerService.writeBackupEnableState(enable, UserHandle.USER_SYSTEM);
mEnabled = enable;
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java b/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java
index 725bc74..bace1aa 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/AppMetadataBackupWriter.java
@@ -1,7 +1,7 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_MANIFEST_VERSION;
import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA_VERSION;
import static com.android.server.backup.UserBackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 9b484bc..5e92339 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -16,9 +16,9 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_MANIFEST_FILENAME;
import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA_FILENAME;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP_WAIT;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
index 24784ea..e142537 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupObbConnection.java
@@ -16,8 +16,8 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP_WAIT;
import android.app.backup.IBackupManager;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
index 0ed75bb..8f6923b 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupTask.java
@@ -16,7 +16,7 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.IFullBackupRestoreObserver;
import android.os.RemoteException;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 2f7687f..43a80c4 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -16,10 +16,10 @@
package com.android.server.backup.fullbackup;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_HEADER_MAGIC;
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_VERSION;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 0d14e7e..5b449c5 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -16,9 +16,9 @@
package com.android.server.backup.fullbackup;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG_SCHEDULING;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import static com.android.server.backup.UserBackupManagerService.OP_PENDING;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_BACKUP_WAIT;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index fd09466..ba153bf 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -16,9 +16,9 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.RestoreSet;
import android.content.Intent;
diff --git a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
index 2bad5fe..5ffa795 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformClearTask.java
@@ -16,7 +16,7 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.pm.PackageInfo;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index 1637e55..6b78fbf 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -16,7 +16,7 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
import android.app.AlarmManager;
diff --git a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
index eab8662..7e2ac796 100644
--- a/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
+++ b/services/backup/java/com/android/server/backup/internal/ProvisionedObserver.java
@@ -16,8 +16,8 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.database.ContentObserver;
import android.os.Handler;
diff --git a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
index d869f04..2a5d913 100644
--- a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
@@ -16,9 +16,9 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.RUN_BACKUP_ACTION;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP;
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 880e608..38870cb 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -16,8 +16,8 @@
package com.android.server.backup.internal;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.RUN_INITIALIZE_ACTION;
import android.content.BroadcastReceiver;
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
index 437abd2..535c7cb 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java
@@ -28,8 +28,8 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.EventLogTags;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.DataChangedJournal;
-import com.android.server.backup.GlobalBackupManagerService;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.remote.RemoteResult;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
@@ -54,8 +54,8 @@
@VisibleForTesting
public class KeyValueBackupReporter {
@VisibleForTesting static final String TAG = "KeyValueBackupTask";
- private static final boolean DEBUG = GlobalBackupManagerService.DEBUG;
- @VisibleForTesting static final boolean MORE_DEBUG = GlobalBackupManagerService.MORE_DEBUG;
+ private static final boolean DEBUG = BackupManagerService.DEBUG;
+ @VisibleForTesting static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG;
static void onNewThread(String threadName) {
if (DEBUG) {
diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
index 5c05371..e273b32 100644
--- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
+++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java
@@ -16,8 +16,8 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_GET_RESTORE_SETS;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
diff --git a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
index 8196e70..e4890e0 100644
--- a/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
+++ b/services/backup/java/com/android/server/backup/restore/AdbRestoreFinishedLatch.java
@@ -16,8 +16,8 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index ee08902..0d26ea5 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -16,9 +16,9 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_MANIFEST_FILENAME;
import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA_FILENAME;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_RESTORE_WAIT;
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 381252d..c904256 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -16,11 +16,11 @@
package com.android.server.backup.restore;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.BackupPasswordManager.PBKDF_CURRENT;
import static com.android.server.backup.BackupPasswordManager.PBKDF_FALLBACK;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_HEADER_MAGIC;
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_VERSION;
import static com.android.server.backup.UserBackupManagerService.SETTINGS_PACKAGE;
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 7530356..f7efad6 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -16,9 +16,9 @@
package com.android.server.backup.restore;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.KEY_WIDGET_STATE;
import static com.android.server.backup.UserBackupManagerService.OP_TYPE_RESTORE_WAIT;
import static com.android.server.backup.UserBackupManagerService.PACKAGE_MANAGER_SENTINEL;
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index 2452e48..e465c7e 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
import android.annotation.Nullable;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index 8b931d4..6f08376 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -18,8 +18,8 @@
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.Nullable;
import android.app.backup.BackupManagerMonitor;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
index 9674c3d..c0cf2ef 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.BackupProgress;
import android.app.backup.IBackupObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
index 92cdf0d..fa856ce 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
@@ -16,7 +16,7 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.IFullBackupRestoreObserver;
import android.os.RemoteException;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index a6fdbf0..dbe3cd9 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -16,7 +16,7 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
index 65adf4e..a7eb644 100644
--- a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
@@ -16,7 +16,7 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index 91567d7..df7e6d4 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -16,8 +16,8 @@
package com.android.server.backup.utils;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import android.content.Context;
import android.content.IIntentReceiver;
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index c295684..0f4b681 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -34,9 +34,9 @@
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
-import static com.android.server.backup.GlobalBackupManagerService.DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.MORE_DEBUG;
-import static com.android.server.backup.GlobalBackupManagerService.TAG;
+import static com.android.server.backup.BackupManagerService.DEBUG;
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
import static com.android.server.backup.UserBackupManagerService.BACKUP_MANIFEST_FILENAME;
import static com.android.server.backup.UserBackupManagerService.BACKUP_MANIFEST_VERSION;
import static com.android.server.backup.UserBackupManagerService.BACKUP_METADATA_FILENAME;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 6174300..784d398 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -32,6 +32,10 @@
"android.hardware.tv.cec-V1.0-java",
],
+ required: [
+ "gps_debug.conf",
+ ],
+
static_libs: [
"time_zone_distro",
"time_zone_distro_installer",
@@ -69,3 +73,9 @@
name: "services.core",
static_libs: ["services.core.priorityboosted"],
}
+
+
+prebuilt_etc {
+ name: "gps_debug.conf",
+ src: "java/com/android/server/location/gps_debug.conf",
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 60bbca8..bb3b9f7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2099,14 +2099,7 @@
return new MockableSystemProperties();
}
- // TODO: Replace nai and newLp with TcpBufferSizes and check default network before calling
- // this method.
- private void updateTcpBufferSizes(NetworkAgentInfo nai, LinkProperties newLp) {
- if (isDefaultNetwork(nai) == false) {
- return;
- }
-
- String tcpBufferSizes = newLp.getTcpBufferSizes();
+ private void updateTcpBufferSizes(String tcpBufferSizes) {
String[] values = null;
if (tcpBufferSizes != null) {
values = tcpBufferSizes.split(",");
@@ -4798,7 +4791,9 @@
// for (LinkProperties lp : newLp.getStackedLinks()) {
// updateMtu(lp, null);
// }
- updateTcpBufferSizes(networkAgent, newLp);
+ if (isDefaultNetwork(networkAgent)) {
+ updateTcpBufferSizes(newLp.getTcpBufferSizes());
+ }
updateRoutes(newLp, oldLp, netId);
updateDnses(newLp, oldLp, netId);
@@ -5289,7 +5284,7 @@
notifyLockdownVpn(newNetwork);
handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
- updateTcpBufferSizes(newNetwork, new LinkProperties(newNetwork.linkProperties));
+ updateTcpBufferSizes(newNetwork.linkProperties.getTcpBufferSizes());
mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
notifyIfacesChangedForNetworkStats();
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index d1b56e9..e80e9e1 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -105,6 +105,7 @@
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.graphics.allocator@2.0::IAllocator",
"android.hardware.graphics.composer@2.1::IComposer",
+ "android.hardware.health@2.0::IHealth",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
"android.hardware.sensors@1.0::ISensors",
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 5c77f0a..8571ae6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
+
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
@@ -26,8 +28,6 @@
import java.io.PrintWriter;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
-
/**
* Settings constants that can modify the activity manager's behavior.
*/
@@ -222,6 +222,10 @@
// Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
volatile boolean mFlagActivityStartsLoggingEnabled;
+ // Indicates whether the background activity starts is enabled.
+ // Controlled by Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED
+ volatile boolean mFlagBackgroundActivityStartsEnabled;
+
private final ActivityManagerService mService;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -256,6 +260,10 @@
private static final Uri ACTIVITY_STARTS_LOGGING_ENABLED_URI = Settings.Global.getUriFor(
Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED);
+ private static final Uri BACKGROUND_ACTIVITY_STARTS_ENABLED_URI =
+ Settings.Global.getUriFor(
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED);
+
public ActivityManagerConstants(ActivityManagerService service, Handler handler) {
super(handler);
mService = service;
@@ -266,8 +274,10 @@
mResolver = resolver;
mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this);
mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
+ mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_ENABLED_URI, false, this);
updateConstants();
updateActivityStartsLoggingEnabled();
+ updateBackgroundActivityStartsEnabled();
}
public void setOverrideMaxCachedProcesses(int value) {
@@ -290,6 +300,8 @@
updateConstants();
} else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) {
updateActivityStartsLoggingEnabled();
+ } else if (BACKGROUND_ACTIVITY_STARTS_ENABLED_URI.equals(uri)) {
+ updateBackgroundActivityStartsEnabled();
}
}
@@ -373,6 +385,11 @@
Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 0) == 1;
}
+ private void updateBackgroundActivityStartsEnabled() {
+ mFlagBackgroundActivityStartsEnabled = Settings.Global.getInt(mResolver,
+ Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1) == 1;
+ }
+
private void updateMaxCachedProcesses() {
CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0
? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 80e7313..b62f648 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19204,6 +19204,10 @@
return mConstants.mFlagActivityStartsLoggingEnabled;
}
+ public boolean isBackgroundActivityStartsEnabled() {
+ return mConstants.mFlagBackgroundActivityStartsEnabled;
+ }
+
public void reportCurKeyguardUsageEvent(boolean keyguardShowing) {
synchronized(ActivityManagerService.this) {
ActivityManagerService.this.reportGlobalUsageEventLocked(keyguardShowing
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index a5848ca..4c4a090 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -65,6 +65,7 @@
// permission in the corresponding .te file your feature belongs to.
@VisibleForTesting
static final String[] sGlobalSettings = new String[] {
+ Settings.Global.NATIVE_FLAGS_HEALTH_CHECK_ENABLED,
};
@VisibleForTesting
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index b817669..48b4145 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -1,17 +1,6 @@
{
"presubmit": [
{
- "name": "CtsActivityManagerDeviceTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.support.test.filters.FlakyTest"
- }
- ]
- },
- {
"name": "CtsActivityManagerDeviceSdk25TestCases",
"options": [
{
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 67d27c9..6cde4ad 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -649,6 +649,9 @@
private String mEnabledSurroundFormats;
private boolean mSurroundModeChanged;
+ @GuardedBy("mSettingsLock")
+ private int mAssistantUid;
+
// Intent "extra" data keys.
public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
public static final String CONNECT_INTENT_KEY_STATE = "state";
@@ -1079,6 +1082,10 @@
AudioSystem.setForceUse(AudioSystem.FOR_DOCK, forDock);
sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
sendEnabledSurroundFormats(mContentResolver, true);
+ updateAssistantUId(true);
+ }
+ synchronized (mAccessibilityServiceUidsLock) {
+ AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
}
synchronized (mHdmiClientLock) {
if (mHdmiManager != null && mHdmiTvClient != null) {
@@ -1404,6 +1411,39 @@
}
}
+ @GuardedBy("mSettingsLock")
+ private void updateAssistantUId(boolean forceUpdate) {
+ int assistantUid = 0;
+
+ // Consider assistants in the following order of priority:
+ // 1) voice interaction service
+ // 2) assistant
+ String assistantName = Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
+ if (TextUtils.isEmpty(assistantName)) {
+ assistantName = Settings.Secure.getStringForUser(
+ mContentResolver,
+ Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
+ }
+ if (!TextUtils.isEmpty(assistantName)) {
+ String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
+ if (!TextUtils.isEmpty(packageName)) {
+ try {
+ assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG,
+ "updateAssistantUId() could not find UID for package: " + packageName);
+ }
+ }
+ }
+
+ if (assistantUid != mAssistantUid || forceUpdate) {
+ AudioSystem.setAssistantUid(assistantUid);
+ mAssistantUid = assistantUid;
+ }
+ }
+
private void readPersistedSettings() {
final ContentResolver cr = mContentResolver;
@@ -1447,6 +1487,7 @@
readDockAudioSettings(cr);
sendEncodedSurroundMode(cr, "readPersistedSettings");
sendEnabledSurroundFormats(cr, true);
+ updateAssistantUId(true);
}
mMuteAffectedStreams = System.getIntForUser(cr,
@@ -5811,6 +5852,9 @@
mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
+
+ mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
}
@Override
@@ -5832,6 +5876,7 @@
updateMasterMono(mContentResolver);
updateEncodedSurroundOutput();
sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
+ updateAssistantUId(false);
}
}
@@ -7658,6 +7703,7 @@
mAccessibilityServiceUids = uids.toArray();
}
}
+ AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
}
}
}
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 33525fd..f2c539c 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -16,16 +16,7 @@
package com.android.server.display;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
import android.content.Context;
-import android.graphics.PixelFormat;
import android.graphics.SurfaceTexture;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
@@ -34,20 +25,29 @@
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
-import android.opengl.GLES20;
import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
import android.util.Slog;
import android.view.DisplayInfo;
-import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
-import libcore.io.Streams;
-
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
+import libcore.io.Streams;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
/**
* <p>
* Animates a screen transition from on to off or off to on by applying
@@ -569,37 +569,31 @@
mSurfaceSession = new SurfaceSession();
}
- SurfaceControl.openTransaction();
- try {
- if (mSurfaceControl == null) {
- try {
- int flags;
- if (mMode == MODE_FADE) {
- flags = SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN;
- } else {
- flags = SurfaceControl.OPAQUE | SurfaceControl.HIDDEN;
- }
- mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
- .setName("ColorFade")
- .setSize(mDisplayWidth, mDisplayHeight)
- .setFlags(flags)
- .build();
- } catch (OutOfResourcesException ex) {
- Slog.e(TAG, "Unable to create surface.", ex);
- return false;
+ if (mSurfaceControl == null) {
+ Transaction t = new Transaction();
+ try {
+ final SurfaceControl.Builder builder =
+ new SurfaceControl.Builder(mSurfaceSession).setName("ColorFade");
+ if (mMode == MODE_FADE) {
+ builder.setColorLayer(true);
+ } else {
+ builder.setBufferSize(mDisplayWidth, mDisplayHeight);
}
-
- mSurfaceControl.setLayerStack(mDisplayLayerStack);
- mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
- mSurface = new Surface();
- mSurface.copyFrom(mSurfaceControl);
-
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
- mDisplayId, mSurfaceControl);
- mSurfaceLayout.onDisplayTransaction();
+ mSurfaceControl = builder.build();
+ } catch (OutOfResourcesException ex) {
+ Slog.e(TAG, "Unable to create surface.", ex);
+ return false;
}
- } finally {
- SurfaceControl.closeTransaction();
+
+ t.setLayerStack(mSurfaceControl, mDisplayLayerStack);
+ t.setWindowCrop(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ mSurface = new Surface();
+ mSurface.copyFrom(mSurfaceControl);
+
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+ mDisplayId, mSurfaceControl);
+ mSurfaceLayout.onDisplayTransaction(t);
+ t.apply();
}
return true;
}
@@ -746,7 +740,7 @@
}
@Override
- public void onDisplayTransaction() {
+ public void onDisplayTransaction(Transaction t) {
synchronized (this) {
if (mSurfaceControl == null) {
return;
@@ -755,21 +749,21 @@
DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
switch (displayInfo.rotation) {
case Surface.ROTATION_0:
- mSurfaceControl.setPosition(0, 0);
- mSurfaceControl.setMatrix(1, 0, 0, 1);
+ t.setPosition(mSurfaceControl, 0, 0);
+ t.setMatrix(mSurfaceControl, 1, 0, 0, 1);
break;
case Surface.ROTATION_90:
- mSurfaceControl.setPosition(0, displayInfo.logicalHeight);
- mSurfaceControl.setMatrix(0, -1, 1, 0);
+ t.setPosition(mSurfaceControl, 0, displayInfo.logicalHeight);
+ t.setMatrix(mSurfaceControl, 0, -1, 1, 0);
break;
case Surface.ROTATION_180:
- mSurfaceControl.setPosition(displayInfo.logicalWidth,
+ t.setPosition(mSurfaceControl, displayInfo.logicalWidth,
displayInfo.logicalHeight);
- mSurfaceControl.setMatrix(-1, 0, 0, -1);
+ t.setMatrix(mSurfaceControl, -1, 0, 0, -1);
break;
case Surface.ROTATION_270:
- mSurfaceControl.setPosition(displayInfo.logicalWidth, 0);
- mSurfaceControl.setMatrix(0, 1, -1, 0);
+ t.setPosition(mSurfaceControl, displayInfo.logicalWidth, 0);
+ t.setMatrix(mSurfaceControl, 0, 1, -1, 0);
break;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d04fa23..360a7d1 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -497,7 +497,7 @@
// List is self-synchronized copy-on-write.
for (DisplayTransactionListener listener : mDisplayTransactionListeners) {
- listener.onDisplayTransaction();
+ listener.onDisplayTransaction(t);
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 3a31c9c..3339a49 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1443,25 +1443,10 @@
}
}
- public void setInputWindows(InputWindowHandle[] windowHandles, int displayId) {
- nativeSetInputWindows(mPtr, windowHandles, displayId);
- }
-
public void setFocusedApplication(int displayId, InputApplicationHandle application) {
nativeSetFocusedApplication(mPtr, displayId, application);
}
- public void setFocusedWindow(InputWindowHandle focusedWindowHandle) {
- final IWindow newFocusedWindow =
- focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
- if (mFocusedWindow != newFocusedWindow) {
- if (mFocusedWindowHasCapture) {
- setPointerCapture(false);
- }
- mFocusedWindow = newFocusedWindow;
- }
- }
-
public void setFocusedDisplay(int displayId) {
nativeSetFocusedDisplay(mPtr, displayId);
}
@@ -1799,11 +1784,22 @@
mWindowManagerCallbacks.notifyInputChannelBroken(token);
}
+ // Native callback
+ private void notifyFocusChanged(IBinder token) {
+ if (mFocusedWindow != token) {
+ if (mFocusedWindowHasCapture) {
+ setPointerCapture(false);
+ }
+ if (token instanceof IWindow) {
+ mFocusedWindow = (IWindow) token;
+ }
+ }
+ }
+
// Native callback.
- private long notifyANR(InputApplicationHandle inputApplicationHandle,
- IBinder token, String reason) {
+ private long notifyANR(IBinder token, String reason) {
return mWindowManagerCallbacks.notifyANR(
- inputApplicationHandle, token, reason);
+ token, reason);
}
// Native callback.
@@ -1834,14 +1830,12 @@
}
// Native callback.
- private long interceptKeyBeforeDispatching(IBinder focus,
- KeyEvent event, int policyFlags) {
+ private long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
}
// Native callback.
- private KeyEvent dispatchUnhandledKey(IBinder focus,
- KeyEvent event, int policyFlags) {
+ private KeyEvent dispatchUnhandledKey(IBinder focus, KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
}
@@ -1993,8 +1987,7 @@
public void notifyInputChannelBroken(IBinder token);
- public long notifyANR(InputApplicationHandle inputApplicationHandle,
- IBinder token, String reason);
+ public long notifyANR(IBinder token, String reason);
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
diff --git a/services/core/java/com/android/server/location/gps_debug.conf b/services/core/java/com/android/server/location/gps_debug.conf
new file mode 100644
index 0000000..34ce96f
--- /dev/null
+++ b/services/core/java/com/android/server/location/gps_debug.conf
@@ -0,0 +1,52 @@
+# Sample file for use for on device debug override only
+# Prefer frameworks/base/core/res/res/values/config.xml and
+# frameworks/base/core/res/res/values-mcc*-mnc*/config.xml
+
+################################
+##### AGPS server settings #####
+################################
+# FOR SUPL SUPPORT, set the following
+# SUPL_HOST=supl.google.com or IP
+# SUPL_PORT=7275
+
+# supl version 2.0
+# SUPL_VER=0x20000
+
+#SUPL_MODE is a bit mask set in config.xml per carrier by default.
+#If it is uncommented here, this value will overwrite the value from
+#config.xml.
+#MSA=0X2
+#MSB=0X1
+#SUPL_MODE=1
+
+# Emergency SUPL, 1=enable, 0=disable
+#SUPL_ES=0
+
+#Choose PDN for Emergency SUPL
+#1 - Use emergency PDN
+#0 - Use regular SUPL PDN for Emergency SUPL
+#USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=0
+
+####################################
+# LTE Positioning Profile Settings
+####################################
+# 0: Enable RRLP on LTE(Default)
+# 1: Enable LPP_User_Plane on LTE
+# 2: Enable LPP_Control_Plane
+# 3: Enable both LPP_User_Plane and LPP_Control_Plane
+#LPP_PROFILE = 2
+
+##################################################
+# Select Positioning Protocol on A-GLONASS system
+##################################################
+# 0x1: RRC CPlane
+# 0x2: RRLP UPlane
+# 0x4: LLP Uplane
+#A_GLONASS_POS_PROTOCOL_SELECT = 0
+
+# Below bit mask configures how GPS functionalities
+# should be locked when user turns off GPS on Settings
+# Set bit 0x1 if MO GPS functionalities are to be locked
+# Set bit 0x2 if NI GPS functionalities are to be locked
+# default - non is locked for backward compatibility
+#GPS_LOCK = 0
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 4f4b6bf..4bd8f45 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -64,6 +64,7 @@
private static final int EVENT_UID_FIREWALL_RULE_CHANGED = 11;
private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
+ private static final int EVENT_APP_IDLE_WL_CHANGED = 14;
static final int NTWK_BLOCKED_POWER = 0;
static final int NTWK_ALLOWED_NON_METERED = 1;
@@ -145,6 +146,13 @@
}
}
+ void appIdleWlChanged(int uid, boolean isWhitelisted) {
+ synchronized (mLock) {
+ if (LOGD) Slog.d(TAG, getAppIdleWlChangedLog(uid, isWhitelisted));
+ mEventsBuffer.appIdleWlChanged(uid, isWhitelisted);
+ }
+ }
+
void paroleStateChanged(boolean paroleOn) {
synchronized (mLock) {
if (LOGD) Slog.d(TAG, getParoleStateChanged(paroleOn));
@@ -259,6 +267,10 @@
return "App idle state of uid " + uid + ": " + idle;
}
+ private static String getAppIdleWlChangedLog(int uid, boolean isWhitelisted) {
+ return "App idle whitelist state of uid " + uid + ": " + isWhitelisted;
+ }
+
private static String getParoleStateChanged(boolean paroleOn) {
return "Parole state: " + paroleOn;
}
@@ -409,6 +421,17 @@
data.timeStamp = System.currentTimeMillis();
}
+ public void appIdleWlChanged(int uid, boolean isWhitelisted) {
+ final Data data = getNextSlot();
+ if (data == null) return;
+
+ data.reset();
+ data.type = EVENT_APP_IDLE_WL_CHANGED;
+ data.ifield1 = uid;
+ data.bfield1 = isWhitelisted;
+ data.timeStamp = System.currentTimeMillis();
+ }
+
public void paroleStateChanged(boolean paroleOn) {
final Data data = getNextSlot();
if (data == null) return;
@@ -487,6 +510,8 @@
return getDeviceIdleModeEnabled(data.bfield1);
case EVENT_APP_IDLE_STATE_CHANGED:
return getAppIdleChangedLog(data.ifield1, data.bfield1);
+ case EVENT_APP_IDLE_WL_CHANGED:
+ return getAppIdleWlChangedLog(data.ifield1, data.bfield1);
case EVENT_PAROLE_STATE_CHANGED:
return getParoleStateChanged(data.bfield1);
case EVENT_TEMP_POWER_SAVE_WL_CHANGED:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 099671d..7f650ee 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -105,6 +105,12 @@
public abstract void onAdminDataAvailable();
/**
+ * Control if a UID should be whitelisted even if it's in app idle mode. Other restrictions may
+ * still be in effect.
+ */
+ public abstract void setAppIdleWhitelist(int uid, boolean shouldWhitelist);
+
+ /**
* Sets a list of packages which are restricted by admin from accessing metered data.
*
* @param packageNames the list of restricted packages.
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d799642..9ed978f 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -464,6 +464,10 @@
@GuardedBy("mUidRulesFirstLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
+ // "Power save mode" is the concept used in the DeviceIdleController that includes various
+ // features including Doze and Battery Saver. It include Battery Saver, but "power save mode"
+ // and "battery saver" are not equivalent.
+
/**
* UIDs that have been white-listed to always be able to have network access
* in power save mode, except device idle (doze) still applies.
@@ -484,6 +488,13 @@
private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
/**
+ * UIDs that have been white-listed temporarily to be able to have network access despite being
+ * idle. Other power saving restrictions still apply.
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ private final SparseBooleanArray mAppIdleTempWhitelistAppIds = new SparseBooleanArray();
+
+ /**
* UIDs that have been initially white-listed by system to avoid restricted background.
*/
@GuardedBy("mUidRulesFirstLock")
@@ -543,7 +554,7 @@
final Handler mHandler;
@VisibleForTesting
- public final Handler mUidEventHandler;
+ final Handler mUidEventHandler;
private final ServiceThread mUidEventThread;
@@ -1454,7 +1465,7 @@
}
@VisibleForTesting
- public void updateNetworks() throws InterruptedException {
+ void updateNetworks() throws InterruptedException {
updateNetworksInternal();
final CountDownLatch latch = new CountDownLatch(1);
mHandler.post(() -> {
@@ -1499,7 +1510,7 @@
* @return cycleDay to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
+ int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
int fallbackCycleDay) {
if (config == null) {
return fallbackCycleDay;
@@ -1531,7 +1542,7 @@
* @return warningBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackWarningBytes) {
if (config == null) {
return fallbackWarningBytes;
@@ -1564,7 +1575,7 @@
* @return limitBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackLimitBytes) {
if (config == null) {
return fallbackLimitBytes;
@@ -2028,7 +2039,7 @@
}
@VisibleForTesting
- public NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
+ NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final RecurrenceRule cycleRule = NetworkPolicy
.buildRule(ZonedDateTime.now().getDayOfMonth(), ZoneId.systemDefault());
@@ -3372,6 +3383,20 @@
fout.decreaseIndent();
}
+ size = mAppIdleTempWhitelistAppIds.size();
+ if (size > 0) {
+ fout.println("App idle whitelist app ids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mAppIdleTempWhitelistAppIds.keyAt(i));
+ fout.print(": ");
+ fout.print(mAppIdleTempWhitelistAppIds.valueAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
size = mDefaultRestrictBackgroundWhitelistUids.size();
if (size > 0) {
fout.println("Default restrict background whitelist uids:");
@@ -3464,7 +3489,7 @@
}
@VisibleForTesting
- public boolean isUidForeground(int uid) {
+ boolean isUidForeground(int uid) {
synchronized (mUidRulesFirstLock) {
return isUidStateForeground(
mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
@@ -3640,12 +3665,15 @@
}
/**
+ * Returns whether a uid is whitelisted from power saving restrictions (eg: Battery Saver, Doze
+ * mode, and app idle).
+ *
* @param deviceIdleMode if true then we don't consider
* {@link #mPowerSaveWhitelistExceptIdleAppIds} for checking if the {@param uid} is
* whitelisted.
*/
@GuardedBy("mUidRulesFirstLock")
- private boolean isWhitelistedBatterySaverUL(int uid, boolean deviceIdleMode) {
+ private boolean isWhitelistedFromPowerSaveUL(int uid, boolean deviceIdleMode) {
final int appId = UserHandle.getAppId(uid);
boolean isWhitelisted = mPowerSaveTempWhitelistAppIds.get(appId)
|| mPowerSaveWhitelistAppIds.get(appId);
@@ -3660,7 +3688,7 @@
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) {
if (enabled) {
- final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid,
+ final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid,
chain == FIREWALL_CHAIN_DOZABLE);
if (isWhitelisted || isUidForegroundOnRestrictPowerUL(uid)) {
setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
@@ -3712,8 +3740,10 @@
if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
&& !isUidForegroundOnRestrictPowerUL(uid)) {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
+ if (LOGD) Log.d(TAG, "updateRuleForAppIdleUL DENY " + uid);
} else {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
+ if (LOGD) Log.d(TAG, "updateRuleForAppIdleUL " + uid + " to DEFAULT");
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
@@ -3896,7 +3926,59 @@
return UserHandle.isApp(uid) && hasInternetPermissions(uid);
}
- private boolean isUidIdle(int uid) {
+ /**
+ * Set whether or not an app should be whitelisted for network access while in app idle. Other
+ * power saving restrictions may still apply.
+ */
+ @VisibleForTesting
+ void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+ synchronized (mUidRulesFirstLock) {
+ if (mAppIdleTempWhitelistAppIds.get(uid) == shouldWhitelist) {
+ // No change.
+ return;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mLogger.appIdleWlChanged(uid, shouldWhitelist);
+ if (shouldWhitelist) {
+ mAppIdleTempWhitelistAppIds.put(uid, true);
+ } else {
+ mAppIdleTempWhitelistAppIds.delete(uid);
+ }
+ updateRuleForAppIdleUL(uid);
+ updateRulesForPowerRestrictionsUL(uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ /** Return the list of UIDs currently in the app idle whitelist. */
+ @VisibleForTesting
+ int[] getAppIdleWhitelist() {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
+ synchronized (mUidRulesFirstLock) {
+ final int len = mAppIdleTempWhitelistAppIds.size();
+ int[] uids = new int[len];
+ for (int i = 0; i < len; ++i) {
+ uids[i] = mAppIdleTempWhitelistAppIds.keyAt(i);
+ }
+ return uids;
+ }
+ }
+
+ /** Returns if the UID is currently considered idle. */
+ @VisibleForTesting
+ boolean isUidIdle(int uid) {
+ synchronized (mUidRulesFirstLock) {
+ if (mAppIdleTempWhitelistAppIds.get(uid)) {
+ // UID is temporarily whitelisted.
+ return false;
+ }
+ }
+
final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
final int userId = UserHandle.getUserId(uid);
@@ -3940,6 +4022,7 @@
mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
mPowerSaveWhitelistAppIds.delete(uid);
mPowerSaveTempWhitelistAppIds.delete(uid);
+ mAppIdleTempWhitelistAppIds.delete(uid);
// ...then update iptables asynchronously.
mHandler.obtainMessage(MSG_RESET_FIREWALL_RULES_BY_UID, uid, 0).sendToTarget();
@@ -3984,7 +4067,7 @@
* <li>@{code bw_happy_box}: UIDs added to this chain have access (whitelist), unless they're
* also blacklisted.
* <li>@{code bw_data_saver}: when enabled (through {@link #setRestrictBackground(boolean)}),
- * no UIDs other those whitelisted will have access.
+ * no UIDs other than those whitelisted will have access.
* <ul>
*
* <p>The @{code bw_penalty_box} and @{code bw_happy_box} are primarily managed through the
@@ -4194,7 +4277,7 @@
final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
- final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid, mDeviceIdleMode);
+ final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
int newRule = RULE_NONE;
@@ -4761,13 +4844,13 @@
}
@VisibleForTesting
- public void addIdleHandler(IdleHandler handler) {
+ void addIdleHandler(IdleHandler handler) {
mHandler.getLooper().getQueue().addIdleHandler(handler);
}
@GuardedBy("mUidRulesFirstLock")
@VisibleForTesting
- public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
+ void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
mRestrictBackgroundPowerState = result;
boolean restrictBackground = result.batterySaverEnabled;
@@ -5023,6 +5106,11 @@
}
@Override
+ public void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+ NetworkPolicyManagerService.this.setAppIdleWhitelist(uid, shouldWhitelist);
+ }
+
+ @Override
public void setMeteredRestrictedPackages(Set<String> packageNames, int userId) {
setMeteredRestrictedPackagesInternal(packageNames, userId);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
index 56d41c5..156c01d 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerShellCommand.java
@@ -78,6 +78,8 @@
pw.println(" Adds a UID to the whitelist for restrict background usage.");
pw.println(" add restrict-background-blacklist UID");
pw.println(" Adds a UID to the blacklist for restrict background usage.");
+ pw.println(" add app-idle-whitelist UID");
+ pw.println(" Adds a UID to the temporary app idle whitelist.");
pw.println(" get restrict-background");
pw.println(" Gets the global restrict background usage status.");
pw.println(" list wifi-networks [true|false]");
@@ -92,6 +94,8 @@
pw.println(" Removes a UID from the whitelist for restrict background usage.");
pw.println(" remove restrict-background-blacklist UID");
pw.println(" Removes a UID from the blacklist for restrict background usage.");
+ pw.println(" remove app-idle-whitelist UID");
+ pw.println(" Removes a UID from the temporary app idle whitelist.");
pw.println(" set metered-network ID [undefined|true|false]");
pw.println(" Toggles whether the given wi-fi network is metered.");
pw.println(" set restrict-background BOOLEAN");
@@ -142,6 +146,8 @@
return -1;
}
switch(type) {
+ case "app-idle-whitelist":
+ return listAppIdleWhitelist();
case "wifi-networks":
return listWifiNetworks();
case "restrict-background-whitelist":
@@ -165,6 +171,8 @@
return addRestrictBackgroundWhitelist();
case "restrict-background-blacklist":
return addRestrictBackgroundBlacklist();
+ case "app-idle-whitelist":
+ return addAppIdleWhitelist();
}
pw.println("Error: unknown add type '" + type + "'");
return -1;
@@ -182,14 +190,20 @@
return removeRestrictBackgroundWhitelist();
case "restrict-background-blacklist":
return removeRestrictBackgroundBlacklist();
+ case "app-idle-whitelist":
+ return removeAppIdleWhitelist();
}
pw.println("Error: unknown remove type '" + type + "'");
return -1;
}
private int listUidPolicies(String msg, int policy) throws RemoteException {
- final PrintWriter pw = getOutPrintWriter();
final int[] uids = mInterface.getUidsWithPolicy(policy);
+ return listUidList(msg, uids);
+ }
+
+ private int listUidList(String msg, int[] uids) {
+ final PrintWriter pw = getOutPrintWriter();
pw.print(msg); pw.print(": ");
if (uids.length == 0) {
pw.println("none");
@@ -214,6 +228,12 @@
POLICY_REJECT_METERED_BACKGROUND);
}
+ private int listAppIdleWhitelist() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final int[] uids = mInterface.getAppIdleWhitelist();
+ return listUidList("App Idle whitelisted UIDs", uids);
+ }
+
private int getRestrictBackground() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
pw.print("Restrict background status: ");
@@ -277,6 +297,23 @@
return resetUidPolicy("not blacklisted", POLICY_REJECT_METERED_BACKGROUND);
}
+ private int setAppIdleWhitelist(boolean isWhitelisted) {
+ final int uid = getUidFromNextArg();
+ if (uid < 0) {
+ return uid;
+ }
+ mInterface.setAppIdleWhitelist(uid, isWhitelisted);
+ return 0;
+ }
+
+ private int addAppIdleWhitelist() throws RemoteException {
+ return setAppIdleWhitelist(true);
+ }
+
+ private int removeAppIdleWhitelist() throws RemoteException {
+ return setAppIdleWhitelist(false);
+ }
+
private int listWifiNetworks() {
final PrintWriter pw = getOutPrintWriter();
final String arg = getNextArg();
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 9222740..84bb13e 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import android.app.Notification;
import android.service.notification.NotificationStats;
import com.android.internal.statusbar.NotificationVisibility;
@@ -26,7 +27,7 @@
void onNotificationClick(int callingUid, int callingPid, String key,
NotificationVisibility nv);
void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex,
- NotificationVisibility nv);
+ Notification.Action action, NotificationVisibility nv, boolean generatedByAssistant);
void onNotificationClear(int callingUid, int callingPid,
String pkg, String tag, int id, int userId, String key,
@NotificationStats.DismissalSurface int dismissalSurface,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6005872..ae27d0c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -752,7 +752,8 @@
@Override
public void onNotificationActionClick(int callingUid, int callingPid, String key,
- int actionIndex, NotificationVisibility nv) {
+ int actionIndex, Notification.Action action, NotificationVisibility nv,
+ boolean generatedByAssistant) {
exitIdle();
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
@@ -772,6 +773,8 @@
nv.rank, nv.count);
nv.recycle();
reportUserInteraction(r);
+ mAssistants.notifyAssistantActionClicked(
+ r.sbn, actionIndex, action, generatedByAssistant);
}
}
@@ -6923,6 +6926,27 @@
});
}
+ @GuardedBy("mNotificationLock")
+ void notifyAssistantActionClicked(
+ final StatusBarNotification sbn, int actionIndex, Notification.Action action,
+ boolean generatedByAssistant) {
+ final String key = sbn.getKey();
+ notifyAssistantLocked(
+ sbn,
+ false /* sameUserOnly */,
+ (assistant, sbnHolder) -> {
+ try {
+ assistant.onActionClicked(
+ key,
+ action,
+ generatedByAssistant
+ ? NotificationAssistantService.SOURCE_FROM_ASSISTANT
+ : NotificationAssistantService.SOURCE_FROM_APP);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "unable to notify assistant (snoozed): " + assistant, ex);
+ }
+ });
+ }
/**
* asynchronously notify the assistant that a notification has been snoozed until a
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f279af0..94d276c 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -309,6 +309,7 @@
newConfig = mConfig.copy();
ZenRule rule = new ZenRule();
populateZenRule(automaticZenRule, rule, true);
+ newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, rule.component, true)) {
return rule.id;
} else {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b490381..7f1fb6c 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -310,7 +310,7 @@
.setPackage(packageName),
user);
if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 0) == 0) {
+ Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) {
return launcherActivities;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 14682f3..1045289 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -53,7 +53,6 @@
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY;
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
@@ -15191,8 +15190,11 @@
}
}
private static class ReconcileFailure extends PackageManagerException {
- public ReconcileFailure(String message) {
- super("Invalid reconcile request: " + message);
+ ReconcileFailure(String message) {
+ super("Reconcile failed: " + message);
+ }
+ ReconcileFailure(int reason, String message) {
+ super(reason, "Reconcile failed: " + message);
}
}
@@ -15211,10 +15213,12 @@
@PackageManager.InstallFlags
public final int installFlags;
public final InstallArgs installArgs;
+ public final DeletePackageAction deletePackageAction;
private ReconciledPackage(InstallArgs installArgs, PackageSetting pkgSetting,
UserHandle installForUser, PackageInstalledInfo installResult, int installFlags,
- String volumeUuid, PrepareResult prepareResult, ScanResult scanResult) {
+ String volumeUuid, PrepareResult prepareResult, ScanResult scanResult,
+ DeletePackageAction deletePackageAction) {
this.installArgs = installArgs;
this.pkgSetting = pkgSetting;
this.installForUser = installForUser;
@@ -15223,6 +15227,7 @@
this.volumeUuid = volumeUuid;
this.prepareResult = prepareResult;
this.scanResult = scanResult;
+ this.deletePackageAction = deletePackageAction;
}
}
@@ -15235,14 +15240,29 @@
final ScanResult scanResult = request.scannedPackages.get(installPackageName);
final InstallArgs installArgs = request.installArgs.get(installPackageName);
final PackageInstalledInfo res = request.installResults.get(installPackageName);
+ final PrepareResult prepareResult = request.preparedPackages.get(installPackageName);
if (scanResult == null || installArgs == null || res == null) {
throw new ReconcileFailure(
"inputs not balanced; missing argument for " + installPackageName);
}
+ final DeletePackageAction deletePackageAction;
+ if (prepareResult.replace) {
+ deletePackageAction = mayDeletePackageLocked(res.removedInfo,
+ prepareResult.originalPs, prepareResult.disabledPs,
+ prepareResult.childPackageSettings);
+ if (deletePackageAction == null) {
+ throw new ReconcileFailure(
+ PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE,
+ "May not delete " + installPackageName + " to replace");
+ }
+ } else {
+ deletePackageAction = null;
+ }
result.put(installPackageName,
new ReconciledPackage(installArgs, scanResult.pkgSetting, installArgs.getUser(),
res, installArgs.installFlags, installArgs.volumeUuid,
- request.preparedPackages.get(installPackageName), scanResult));
+ request.preparedPackages.get(installPackageName), scanResult,
+ deletePackageAction));
}
return result;
}
@@ -15314,29 +15334,29 @@
final boolean killApp = (scanRequest.scanFlags & SCAN_DONT_KILL_APP) == 0;
final int deleteFlags = PackageManager.DELETE_KEEP_DATA
| (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
- // First delete the existing package while retaining the data directory
- if (!deletePackageLIF(packageName, null, true, request.mAllUsers, deleteFlags,
- res.removedInfo, true, pkg)) {
- // If the existing package wasn't successfully deleted
- res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE,
- "replaceNonSystemPackageLI");
- return false;
- } else {
- // Successfully deleted the old package; proceed with replace.
-
- // If deleted package lived in a container, give users a chance to
- // relinquish resources before killing.
- if (oldPackage.isForwardLocked() || isExternal(oldPackage)) {
- if (DEBUG_INSTALL) {
- Slog.i(TAG, "upgrading pkg " + oldPackage
- + " is ASEC-hosted -> UNAVAILABLE");
- }
- final int[] uidArray = new int[]{oldPackage.applicationInfo.uid};
- final ArrayList<String> pkgList = new ArrayList<>(1);
- pkgList.add(oldPackage.applicationInfo.packageName);
- sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
+ try {
+ executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName,
+ null, true, request.mAllUsers, deleteFlags, true, pkg);
+ } catch (SystemDeleteException e) {
+ if (Build.IS_ENG) {
+ throw new RuntimeException("Unexpected failure", e);
+ // ignore; not possible for non-system app
}
}
+ // Successfully deleted the old package; proceed with replace.
+
+ // If deleted package lived in a container, give users a chance to
+ // relinquish resources before killing.
+ if (oldPackage.isForwardLocked() || isExternal(oldPackage)) {
+ if (DEBUG_INSTALL) {
+ Slog.i(TAG, "upgrading pkg " + oldPackage
+ + " is ASEC-hosted -> UNAVAILABLE");
+ }
+ final int[] uidArray = new int[]{oldPackage.applicationInfo.uid};
+ final ArrayList<String> pkgList = new ArrayList<>(1);
+ pkgList.add(oldPackage.applicationInfo.packageName);
+ sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
+ }
// Update the in-memory copy of the previous code paths.
PackageSetting ps1 = mSettings.mPackages.get(
@@ -15744,13 +15764,16 @@
@Nullable
public final String renamedPackage;
public final PackageFreezer freezer;
+ public final PackageSetting originalPs;
+ public final PackageSetting disabledPs;
+ public final PackageSetting[] childPackageSettings;
private PrepareResult(int installReason, String volumeUuid,
String installerPackageName, UserHandle user, boolean replace, int scanFlags,
int parseFlags, PackageParser.Package existingPackage,
PackageParser.Package packageToScan, boolean clearCodeCache, boolean system,
- String renamedPackage,
- PackageFreezer freezer) {
+ String renamedPackage, PackageFreezer freezer, PackageSetting originalPs,
+ PackageSetting disabledPs, PackageSetting[] childPackageSettings) {
this.installReason = installReason;
this.volumeUuid = volumeUuid;
this.installerPackageName = installerPackageName;
@@ -15764,6 +15787,9 @@
this.system = system;
this.renamedPackage = renamedPackage;
this.freezer = freezer;
+ this.originalPs = originalPs;
+ this.disabledPs = disabledPs;
+ this.childPackageSettings = childPackageSettings;
}
}
@@ -16267,7 +16293,9 @@
String targetVolumeUuid = volumeUuid;
int targetScanFlags = scanFlags;
int targetParseFlags = parseFlags;
-
+ final PackageSetting ps;
+ final PackageSetting disabledPs;
+ final PackageSetting[] childPackages;
if (replace) {
targetVolumeUuid = null;
if (pkg.applicationInfo.isStaticSharedLibrary()) {
@@ -16287,7 +16315,6 @@
final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
final PackageParser.Package oldPackage;
- final PackageSetting ps;
final String pkgName11 = pkg.packageName;
final int[] allUsers;
final int[] installedUsers;
@@ -16314,6 +16341,7 @@
}
ps = mSettings.mPackages.get(pkgName11);
+ disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
// verify signatures are valid
final KeySetManagerService ksms = mSettings.mKeySetManagerService;
@@ -16410,49 +16438,52 @@
res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
}
- final int childCount = (oldPackage.childPackages != null)
- ? oldPackage.childPackages.size() : 0;
- for (int i = 0; i < childCount; i++) {
- boolean childPackageUpdated = false;
- PackageParser.Package childPkg = oldPackage.childPackages.get(i);
- final PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
- if (res.addedChildPackages != null) {
- PackageInstalledInfo childRes = res.addedChildPackages.get(
- childPkg.packageName);
- if (childRes != null) {
- childRes.removedInfo.uid = childPkg.applicationInfo.uid;
- childRes.removedInfo.removedPackage = childPkg.packageName;
- if (childPs != null) {
- childRes.removedInfo.installerPackageName =
- childPs.installerPackageName;
- }
- childRes.removedInfo.isUpdate = true;
- childRes.removedInfo.installReasons = res.removedInfo.installReasons;
- childPackageUpdated = true;
- }
- }
- if (!childPackageUpdated) {
- PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
- childRemovedRes.removedPackage = childPkg.packageName;
- if (childPs != null) {
- childRemovedRes.installerPackageName = childPs.installerPackageName;
- }
- childRemovedRes.isUpdate = false;
- childRemovedRes.dataRemoved = true;
- synchronized (mPackages) {
- if (childPs != null) {
- childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers,
- true);
+ childPackages = mSettings.getChildSettingsLPr(ps);
+ if (childPackages != null) {
+ for (PackageSetting childPs : childPackages) {
+ boolean childPackageUpdated = false;
+ PackageParser.Package childPkg = (childPs == null) ? null : childPs.pkg;
+ if (res.addedChildPackages != null) {
+ PackageInstalledInfo childRes = res.addedChildPackages.get(
+ childPkg.packageName);
+ if (childRes != null) {
+ childRes.removedInfo.uid = childPkg.applicationInfo.uid;
+ childRes.removedInfo.removedPackage = childPkg.packageName;
+ if (childPs != null) {
+ childRes.removedInfo.installerPackageName =
+ childPs.installerPackageName;
+ }
+ childRes.removedInfo.isUpdate = true;
+ childRes.removedInfo.installReasons =
+ res.removedInfo.installReasons;
+ childPackageUpdated = true;
}
}
- if (res.removedInfo.removedChildPackages == null) {
- res.removedInfo.removedChildPackages = new ArrayMap<>();
+ if (!childPackageUpdated) {
+ PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
+ childRemovedRes.removedPackage = childPkg.packageName;
+ if (childPs != null) {
+ childRemovedRes.installerPackageName = childPs.installerPackageName;
+ }
+ childRemovedRes.isUpdate = false;
+ childRemovedRes.dataRemoved = true;
+ synchronized (mPackages) {
+ if (childPs != null) {
+ childRemovedRes.origUsers = childPs.queryInstalledUsers(
+ allUsers,
+ true);
+ }
+ }
+ if (res.removedInfo.removedChildPackages == null) {
+ res.removedInfo.removedChildPackages = new ArrayMap<>();
+ }
+ res.removedInfo.removedChildPackages.put(childPkg.packageName,
+ childRemovedRes);
}
- res.removedInfo.removedChildPackages.put(childPkg.packageName,
- childRemovedRes);
}
}
+
sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
// Set the system/privileged/oem/vendor/product flags as needed
@@ -16495,6 +16526,9 @@
}
} else { // new package install
+ ps = null;
+ childPackages = null;
+ disabledPs = null;
replace = false;
existingPackage = null;
// Remember this for later, in case we need to rollback this install
@@ -16525,9 +16559,11 @@
}
// we're passing the freezer back to be closed in a later phase of install
shouldCloseFreezerBeforeReturn = false;
+
return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
- replace /* clearCodeCache */, sysPkg, renamedPackage, freezer);
+ replace /* clearCodeCache */, sysPkg, renamedPackage, freezer,
+ ps, disabledPs, childPackages);
} finally {
if (shouldCloseFreezerBeforeReturn) {
freezer.close();
@@ -17477,34 +17513,20 @@
/*
* Tries to delete system package.
*/
- private boolean deleteSystemPackageLIF(PackageParser.Package deletedPkg,
- PackageSetting deletedPs, int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
- boolean writeSettings) {
- if (deletedPs.parentPackageName != null) {
- Slog.w(TAG, "Attempt to delete child system package " + deletedPkg.packageName);
- return false;
- }
-
+ private void deleteSystemPackageLIF(DeletePackageAction action,
+ PackageParser.Package deletedPkg, PackageSetting deletedPs, int[] allUserHandles,
+ int flags, PackageRemovedInfo outInfo, boolean writeSettings)
+ throws SystemDeleteException {
final boolean applyUserRestrictions
= (allUserHandles != null) && (outInfo.origUsers != null);
- final PackageSetting disabledPs;
// Confirm if the system package has been updated
// An updated system app can be deleted. This will also have to restore
// the system pkg from system partition
// reader
- synchronized (mPackages) {
- disabledPs = mSettings.getDisabledSystemPkgLPr(deletedPs.name);
- }
-
+ final PackageSetting disabledPs = action.disabledPs;
if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName
+ " disabledPs=" + disabledPs);
-
- if (disabledPs == null) {
- Slog.w(TAG, "Attempt to delete unknown system package "+ deletedPkg.packageName);
- return false;
- } else if (DEBUG_REMOVE) {
- Slog.d(TAG, "Deleting system pkg from data partition");
- }
+ Slog.d(TAG, "Deleting system pkg from data partition");
if (DEBUG_REMOVE) {
if (applyUserRestrictions) {
@@ -17542,11 +17564,8 @@
flags |= PackageManager.DELETE_KEEP_DATA;
}
- boolean ret = deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles,
+ deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles,
outInfo, writeSettings, disabledPs.pkg);
- if (!ret) {
- return false;
- }
// writer
synchronized (mPackages) {
@@ -17563,25 +17582,25 @@
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
try {
- installPackageFromSystemLIF(disabledPs.codePathString, false, allUserHandles,
+ installPackageFromSystemLIF(disabledPs.codePathString, allUserHandles,
outInfo.origUsers, deletedPs.getPermissionsState(), writeSettings);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": "
+ e.getMessage());
- return false;
+ // TODO(patb): can we avoid this; throw would come from scan...
+ throw new SystemDeleteException(e);
} finally {
if (disabledPs.pkg.isStub) {
mSettings.disableSystemPackageLPw(disabledPs.name, true /*replaced*/);
}
}
- return true;
}
/**
* Installs a package that's already on the system partition.
*/
private PackageParser.Package installPackageFromSystemLIF(@NonNull String codePathString,
- boolean isPrivileged, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles,
+ @Nullable int[] allUserHandles, @Nullable int[] origUserHandles,
@Nullable PermissionsState origPermissionState, boolean writeSettings)
throws PackageManagerException {
@ParseFlags int parseFlags =
@@ -17589,7 +17608,7 @@
| PackageParser.PARSE_MUST_BE_APK
| PackageParser.PARSE_IS_SYSTEM_DIR;
@ScanFlags int scanFlags = SCAN_AS_SYSTEM;
- if (isPrivileged || locationIsPrivileged(codePathString)) {
+ if (locationIsPrivileged(codePathString)) {
scanFlags |= SCAN_AS_PRIVILEGED;
}
if (locationIsOem(codePathString)) {
@@ -17665,7 +17684,7 @@
return pkg;
}
- private boolean deleteInstalledPackageLIF(PackageSetting ps,
+ private void deleteInstalledPackageLIF(PackageSetting ps,
boolean deleteCodeAndResources, int flags, int[] allUserHandles,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
@@ -17680,9 +17699,6 @@
for (int i = 0; i < childCount; i++) {
String childPackageName = ps.childPackageNames.get(i);
PackageSetting childPs = mSettings.mPackages.get(childPackageName);
- if (childPs == null) {
- return false;
- }
PackageRemovedInfo childInfo = outInfo.removedChildPackages.get(
childPackageName);
if (childInfo != null) {
@@ -17723,8 +17739,6 @@
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
}
-
- return true;
}
@Override
@@ -17780,26 +17794,59 @@
private static class DeletePackageAction {
public final PackageSetting deletingPs;
+ public final PackageSetting disabledPs;
+ public final PackageRemovedInfo outInfo;
- private DeletePackageAction(PackageSetting deletingPs) {
+ private DeletePackageAction(PackageSetting deletingPs, PackageSetting disabledPs,
+ PackageRemovedInfo outInfo) {
this.deletingPs = deletingPs;
+ this.disabledPs = disabledPs;
+ this.outInfo = outInfo;
}
}
/**
- * @return a {@link DeletePackageAction} if the provided package may be deleted, {@code null}
- * otherwise.
+ * @return a {@link DeletePackageAction} if the provided package and related state may be
+ * deleted, {@code null} otherwise.
*/
@Nullable
- private DeletePackageAction mayDeletePackageLIF(@NonNull String packageName) {
- synchronized (mPackages) {
- final PackageSetting ps;
- ps = mSettings.mPackages.get(packageName);
- if (ps == null) {
+ @GuardedBy("mPackages")
+ private static DeletePackageAction mayDeletePackageLocked(
+ PackageRemovedInfo outInfo, PackageSetting ps, @Nullable PackageSetting disabledPs,
+ @Nullable PackageSetting[] children) {
+ if (ps == null) {
+ return null;
+ }
+ if (isSystemApp(ps)) {
+ if (ps.parentPackageName == null) {
+ Slog.w(TAG, "Attempt to delete child system package " + ps.pkg.packageName);
return null;
}
- return new DeletePackageAction(ps);
+
+ // Confirm if the system package has been updated
+ // An updated system app can be deleted. This will also have to restore
+ // the system pkg from system partition
+ // reader
+ if (disabledPs == null) {
+ Slog.w(TAG,
+ "Attempt to delete unknown system package " + ps.pkg.packageName);
+ return null;
+ }
}
+ final int parentReferenceCount =
+ (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
+ final int childCount = children != null ? children.length : 0;
+ if (childCount != parentReferenceCount) {
+ return null;
+ }
+ if (childCount != 0 && outInfo != null && outInfo.removedChildPackages != null) {
+ for (PackageSetting child : children) {
+ if (child == null || !ps.childPackageNames.contains(child.name)) {
+ return null;
+ }
+ }
+ }
+ return new DeletePackageAction(ps, disabledPs, outInfo);
}
/*
@@ -17809,22 +17856,43 @@
boolean deleteCodeAndResources, int[] allUserHandles, int flags,
PackageRemovedInfo outInfo, boolean writeSettings,
PackageParser.Package replacingPackage) {
- final DeletePackageAction action = mayDeletePackageLIF(packageName);
+ final DeletePackageAction action;
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps);
+ PackageSetting[] children = mSettings.getChildSettingsLPr(ps);
+ action = mayDeletePackageLocked(outInfo, ps, disabledPs, children);
+ }
if (null == action) {
return false;
}
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
- return executeDeletePackageLIF(action, packageName, user, deleteCodeAndResources,
- allUserHandles, flags, outInfo, writeSettings, replacingPackage);
+ try {
+ executeDeletePackageLIF(action, packageName, user, deleteCodeAndResources,
+ allUserHandles, flags, writeSettings, replacingPackage);
+ } catch (SystemDeleteException e) {
+ return false;
+ }
+ return true;
}
- private boolean executeDeletePackageLIF(DeletePackageAction action,
+ private static class SystemDeleteException extends Exception {
+ public final PackageManagerException reason;
+
+ private SystemDeleteException(PackageManagerException reason) {
+ this.reason = reason;
+ }
+ }
+
+ /** Deletes a package. Only throws when install of a disabled package fails. */
+ private void executeDeletePackageLIF(DeletePackageAction action,
String packageName, UserHandle user, boolean deleteCodeAndResources,
- int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
- boolean writeSettings, PackageParser.Package replacingPackage) {
+ int[] allUserHandles, int flags, boolean writeSettings,
+ PackageParser.Package replacingPackage) throws SystemDeleteException {
final PackageSetting ps = action.deletingPs;
+ final PackageRemovedInfo outInfo = action.outInfo;
final boolean systemApp = isSystemApp(ps);
synchronized (mPackages) {
@@ -17840,7 +17908,7 @@
clearPackageStateForUserLIF(ps, removedUserId, outInfo);
markPackageUninstalledForUserLPw(ps, user);
scheduleWritePackageRestrictionsLocked(user);
- return true;
+ return;
}
}
@@ -17869,7 +17937,7 @@
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
scheduleWritePackageRestrictionsLocked(user);
- return true;
+ return;
} else {
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
@@ -17885,7 +17953,7 @@
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
scheduleWritePackageRestrictionsLocked(user);
- return true;
+ return;
}
}
@@ -17910,15 +17978,15 @@
}
// TODO(b/109941548): break reasons for ret = false out into mayDelete method
- final boolean ret;
if (systemApp) {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
// When an updated system application is deleted we delete the existing resources
// as well and fall back to existing code in system partition
- ret = deleteSystemPackageLIF(ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
+ deleteSystemPackageLIF(
+ action, ps.pkg, ps, allUserHandles, flags, outInfo, writeSettings);
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
- ret = deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
+ deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}
@@ -17967,8 +18035,6 @@
}
}
}
-
- return ret;
}
@GuardedBy("mPackages")
@@ -19694,7 +19760,7 @@
enableSystemPackageLPw(deletedPkg);
}
installPackageFromSystemLIF(deletedPkg.codePath,
- false /*isPrivileged*/, null /*allUserHandles*/,
+ /*isPrivileged*/ null /*allUserHandles*/,
null /*origUserHandles*/, null /*origPermissionsState*/,
true /*writeSettings*/);
} catch (PackageManagerException pme) {
@@ -23528,6 +23594,30 @@
return mProtectedPackages.isPackageStateProtected(userId, packageName);
}
+ @Override
+ public void sendDeviceCustomizationReadyBroadcast() {
+ mContext.enforceCallingPermission(Manifest.permission.SEND_DEVICE_CUSTOMIZATION_READY,
+ "sendDeviceCustomizationReadyBroadcast");
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final Intent intent = new Intent(Intent.ACTION_DEVICE_CUSTOMIZATION_READY);
+ intent.setFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ final IActivityManager am = ActivityManager.getService();
+ final String[] requiredPermissions = {
+ Manifest.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY,
+ };
+ try {
+ am.broadcastIntent(null, intent, null, null, 0, null, null, requiredPermissions,
+ android.app.AppOpsManager.OP_NONE, null, false, false, UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
static class ActiveInstallSession {
private final String mPackageName;
private final File mStagedDir;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 9e5a4c6..c524dba 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4255,11 +4255,48 @@
return false;
}
+ /**
+ * Returns the disabled {@link PackageSetting} for the provided package name if one exists,
+ * {@code null} otherwise.
+ */
+ @Nullable
public PackageSetting getDisabledSystemPkgLPr(String name) {
PackageSetting ps = mDisabledSysPackages.get(name);
return ps;
}
+ /**
+ * Returns the disabled {@link PackageSetting} for the provided enabled {@link PackageSetting}
+ * if one exists, {@code null} otherwise.
+ */
+ @Nullable
+ public PackageSetting getDisabledSystemPkgLPr(PackageSetting enabledPackageSetting) {
+ if (enabledPackageSetting == null) {
+ return null;
+ }
+ return getDisabledSystemPkgLPr(enabledPackageSetting.name);
+ }
+
+ /**
+ * Fetches an array of the child {@link PackageSetting}s for all child package names referenced
+ * by the provided parent {@link PackageSetting} or {@code null} if no children are referenced.
+ *
+ * Note: Any child packages not found will be null in the returned array.
+ */
+ @Nullable
+ public PackageSetting[] getChildSettingsLPr(PackageSetting parentPackageSetting) {
+ if (parentPackageSetting == null || !parentPackageSetting.hasChildPackages()) {
+ return null;
+ }
+ final int childCount = parentPackageSetting.childPackageNames.size();
+ PackageSetting[] children =
+ new PackageSetting[childCount];
+ for (int i = 0; i < childCount; i++) {
+ children[i] = mPackages.get(parentPackageSetting.childPackageNames.get(i));
+ }
+ return children;
+ }
+
boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) {
final PackageSetting ps = mPackages.get(componentInfo.packageName);
if (ps == null) return false;
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 4124210..b390eeb 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -30,6 +30,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
@@ -42,6 +44,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -334,5 +337,13 @@
return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
false, true, name, null);
}
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new RoleManagerShellCommand(this)).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerShellCommand.java b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
new file mode 100644
index 0000000..e1977ef
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleManagerShellCommand.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.role;
+
+import android.app.role.IRoleManager;
+import android.app.role.IRoleManagerCallback;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+class RoleManagerShellCommand extends ShellCommand {
+ private final IRoleManager mRoleManager;
+
+ RoleManagerShellCommand(IRoleManager roleManager) {
+ mRoleManager = roleManager;
+ }
+
+ private class Callback extends IRoleManagerCallback.Stub {
+ private final CompletableFuture<Void> mResult = new CompletableFuture<>();
+
+ public int waitForResult() {
+ try {
+ mResult.get(5, TimeUnit.SECONDS);
+ return 0;
+ } catch (Exception e) {
+ getErrPrintWriter().println("Error: " + e.toString());
+ return -1;
+ }
+ }
+
+ @Override
+ public void onSuccess() {
+ mResult.complete(null);
+ }
+
+ @Override
+ public void onFailure() {
+ mResult.completeExceptionally(new RuntimeException("Failed"));
+ }
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ PrintWriter pw = getOutPrintWriter();
+ try {
+ switch (cmd) {
+ case "add-role-holder":
+ return runAddRoleHolder();
+ case "remove-role-holder":
+ return runRemoveRoleHolder();
+ case "clear-role-holders":
+ return runClearRoleHolders();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int getUserIdMaybe() {
+ int userId = UserHandle.USER_SYSTEM;
+ String option = getNextOption();
+ if (option != null && option.equals("--user")) {
+ userId = UserHandle.parseUserArg(getNextArgRequired());
+ }
+ return userId;
+ }
+
+ private int runAddRoleHolder() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+ String packageName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.addRoleHolderAsUser(roleName, packageName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ private int runRemoveRoleHolder() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+ String packageName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.removeRoleHolderAsUser(roleName, packageName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ private int runClearRoleHolders() throws RemoteException {
+ int userId = getUserIdMaybe();
+ String roleName = getNextArgRequired();
+
+ Callback callback = new Callback();
+ mRoleManager.clearRoleHoldersAsUser(roleName, userId, callback);
+ return callback.waitForResult();
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Role manager (role) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println();
+ pw.println(" add-role-holder [--user USER_ID] ROLE PACKAGE");
+ pw.println(" remove-role-holder [--user USER_ID] ROLE PACKAGE");
+ pw.println(" clear-role-holders [--user USER_ID] ROLE");
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 361622f..0d66a2c8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -19,6 +19,7 @@
import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
import android.app.ActivityThread;
+import android.app.Notification;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
@@ -1080,14 +1081,16 @@
}
@Override
- public void onNotificationActionClick(String key, int actionIndex, NotificationVisibility nv) {
+ public void onNotificationActionClick(
+ String key, int actionIndex, Notification.Action action, NotificationVisibility nv,
+ boolean generatedByAssistant) {
enforceStatusBarService();
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key,
- actionIndex, nv);
+ actionIndex, action, nv, generatedByAssistant);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index da0a794..4b413e5 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -49,7 +49,7 @@
import libcore.icu.ICU;
import libcore.timezone.TzDataSetVersion;
import libcore.timezone.TimeZoneFinder;
-import libcore.util.ZoneInfoDB;
+import libcore.timezone.ZoneInfoDB;
import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index e4d1cfe..fe0b5c2 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -16,9 +16,9 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -706,7 +706,7 @@
mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
surfaceControl = mService.getDefaultDisplayContentLocked().makeOverlay()
.setName(SURFACE_TITLE)
- .setSize(mTempPoint.x, mTempPoint.y) // not a typo
+ .setBufferSize(mTempPoint.x, mTempPoint.y) // not a typo
.setFormat(PixelFormat.TRANSLUCENT)
.build();
} catch (OutOfResourcesException oore) {
@@ -784,7 +784,7 @@
public void updateSize() {
synchronized (mService.mGlobalLock) {
mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
- mSurfaceControl.setSize(mTempPoint.x, mTempPoint.y);
+ mSurfaceControl.setBufferSize(mTempPoint.x, mTempPoint.y);
invalidate(mDirtyRect);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index ed36645..84750b3 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -39,8 +39,6 @@
import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult;
-import static com.android.server.wm.ActivityStackSupervisor.TAG_STATES;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
@@ -48,6 +46,8 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.RootActivityContainer.FindTaskResult;
+import static com.android.server.wm.RootActivityContainer.TAG_STATES;
import android.annotation.Nullable;
import android.app.ActivityOptions;
@@ -84,7 +84,8 @@
*/
private static int sNextFreeStackId = 0;
- private ActivityStackSupervisor mSupervisor;
+ private ActivityTaskManagerService mService;
+ private RootActivityContainer mRootActivityContainer;
/** Actual Display this object tracks. */
int mDisplayId;
Display mDisplay;
@@ -141,8 +142,9 @@
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
- ActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
- mSupervisor = supervisor;
+ ActivityDisplay(RootActivityContainer root, Display display) {
+ mRootActivityContainer = root;
+ mService = root.mService;
mDisplayId = display.getDisplayId();
mDisplay = display;
mWindowContainerController = createWindowContainerController();
@@ -168,7 +170,7 @@
if (displayId != DEFAULT_DISPLAY) {
final int displayState = mDisplay.getState();
if (displayState == Display.STATE_OFF && mOffToken == null) {
- mOffToken = mSupervisor.mService.acquireSleepToken("Display-off", displayId);
+ mOffToken = mService.acquireSleepToken("Display-off", displayId);
} else if (displayState == Display.STATE_ON && mOffToken != null) {
mOffToken.release();
mOffToken = null;
@@ -179,6 +181,11 @@
mWindowContainerController.onDisplayChanged();
}
+ @Override
+ public void onInitializeOverrideConfiguration(Configuration config) {
+ getOverrideConfiguration().updateFrom(config);
+ }
+
void addChild(ActivityStack stack, int position) {
if (position == POSITION_BOTTOM) {
position = 0;
@@ -189,7 +196,7 @@
+ " to displayId=" + mDisplayId + " position=" + position);
addStackReferenceIfNeeded(stack);
positionChildAt(stack, position);
- mSupervisor.mService.updateSleepIfNeededLocked();
+ mService.updateSleepIfNeededLocked();
}
void removeChild(ActivityStack stack) {
@@ -201,7 +208,7 @@
}
removeStackReferenceIfNeeded(stack);
releaseSelfIfNeeded();
- mSupervisor.mService.updateSleepIfNeededLocked();
+ mService.updateSleepIfNeededLocked();
onStackOrderChanged();
}
@@ -252,7 +259,7 @@
final ActivityStack currentFocusedStack = getFocusedStack();
if (currentFocusedStack != prevFocusedStack) {
mLastFocusedStack = prevFocusedStack;
- EventLogTags.writeAmFocusedStack(mSupervisor.mCurrentUser, mDisplayId,
+ EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
updateLastFocusedStackReason);
@@ -409,10 +416,10 @@
}
}
- final ActivityTaskManagerService service = mSupervisor.mService;
- if (!isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow,
- service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement,
- service.mSupportsPictureInPicture, activityType)) {
+ if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
+ mService.mSupportsSplitScreenMultiWindow,
+ mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
+ activityType)) {
throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
+ windowingMode);
}
@@ -425,10 +432,12 @@
<T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
int stackId, boolean onTop) {
if (windowingMode == WINDOWING_MODE_PINNED) {
- return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop);
+ return (T) new PinnedActivityStack(this, stackId,
+ mRootActivityContainer.mStackSupervisor, onTop);
}
- return (T) new ActivityStack(
- this, stackId, mSupervisor, windowingMode, activityType, onTop);
+ return (T) new ActivityStack(this, stackId,
+ mRootActivityContainer.mStackSupervisor, windowingMode, activityType,
+ onTop);
}
/**
@@ -543,7 +552,7 @@
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
// TODO(b/111541062): Check if resumed activity on this display instead
- if (!mSupervisor.isTopDisplayFocusedStack(stack)
+ if (!mRootActivityContainer.isTopDisplayFocusedStack(stack)
&& stack.getResumedActivity() != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.getResumedActivity());
@@ -608,7 +617,7 @@
if (stack.getWindowingMode() != windowingMode) {
continue;
}
- mSupervisor.removeStack(stack);
+ mRootActivityContainer.mStackSupervisor.removeStack(stack);
}
}
}
@@ -623,7 +632,7 @@
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
- mSupervisor.removeStack(stack);
+ mRootActivityContainer.mStackSupervisor.removeStack(stack);
}
}
}
@@ -685,7 +694,7 @@
}
private void onSplitScreenModeDismissed() {
- mSupervisor.mWindowManager.deferSurfaceLayout();
+ mRootActivityContainer.mWindowManager.deferSurfaceLayout();
try {
// Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -709,12 +718,12 @@
mHomeStack.moveToFront("onSplitScreenModeDismissed");
topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
}
- mSupervisor.mWindowManager.continueSurfaceLayout();
+ mRootActivityContainer.mWindowManager.continueSurfaceLayout();
}
}
private void onSplitScreenModeActivated() {
- mSupervisor.mWindowManager.deferSurfaceLayout();
+ mRootActivityContainer.mWindowManager.deferSurfaceLayout();
try {
// Adjust the windowing mode of any affected by split-screen to split-screen secondary.
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -729,7 +738,7 @@
false /* creating */);
}
} finally {
- mSupervisor.mWindowManager.continueSurfaceLayout();
+ mRootActivityContainer.mWindowManager.continueSurfaceLayout();
}
}
@@ -824,11 +833,10 @@
int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r,
@Nullable TaskRecord task, int activityType) {
// Make sure the windowing mode we are trying to use makes sense for what is supported.
- final ActivityTaskManagerService service = mSupervisor.mService;
- boolean supportsMultiWindow = service.mSupportsMultiWindow;
- boolean supportsSplitScreen = service.mSupportsSplitScreenMultiWindow;
- boolean supportsFreeform = service.mSupportsFreeformWindowManagement;
- boolean supportsPip = service.mSupportsPictureInPicture;
+ boolean supportsMultiWindow = mService.mSupportsMultiWindow;
+ boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
+ boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
+ boolean supportsPip = mService.mSupportsPictureInPicture;
if (supportsMultiWindow) {
if (task != null) {
supportsMultiWindow = task.isResizeable();
@@ -932,7 +940,7 @@
// This activity can be considered the top running activity if we are not considering
// the locked state, the keyguard isn't locked, or we can show when locked.
if (topRunning != null && considerKeyguardState
- && mSupervisor.getKeyguardController().isKeyguardLocked()
+ && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked()
&& !topRunning.canShowWhenLocked()) {
return null;
}
@@ -1010,7 +1018,7 @@
@Override
protected ConfigurationContainer getParent() {
- return mSupervisor;
+ return mRootActivityContainer;
}
boolean isPrivate() {
@@ -1043,8 +1051,8 @@
// released (no more ActivityStack). But, we cannot release it at that moment or the
// related WindowContainer and WindowContainerController will also be removed. So, we
// set display as removed after reparenting stack finished.
- final ActivityDisplay toDisplay = mSupervisor.getDefaultDisplay();
- mSupervisor.beginDeferResume();
+ final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
+ mRootActivityContainer.mStackSupervisor.beginDeferResume();
try {
int numStacks = mStacks.size();
// Keep the order from bottom to top.
@@ -1070,7 +1078,7 @@
numStacks = mStacks.size();
}
} finally {
- mSupervisor.endDeferResume();
+ mRootActivityContainer.mStackSupervisor.endDeferResume();
}
mRemoved = true;
@@ -1082,9 +1090,9 @@
releaseSelfIfNeeded();
if (!mAllSleepTokens.isEmpty()) {
- mSupervisor.mSleepTokens.removeAll(mAllSleepTokens);
+ mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
mAllSleepTokens.clear();
- mSupervisor.mService.updateSleepIfNeededLocked();
+ mService.updateSleepIfNeededLocked();
}
}
@@ -1092,8 +1100,9 @@
if (mStacks.isEmpty() && mRemoved) {
mWindowContainerController.removeContainer();
mWindowContainerController = null;
- mSupervisor.removeChild(this);
- mSupervisor.getKeyguardController().onDisplayRemoved(mDisplayId);
+ mRootActivityContainer.removeChild(this);
+ mRootActivityContainer.mStackSupervisor
+ .getKeyguardController().onDisplayRemoved(mDisplayId);
}
}
@@ -1122,7 +1131,7 @@
boolean shouldSleep() {
return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
- && (mSupervisor.mService.mRunningVoice == null);
+ && (mService.mRunningVoice == null);
}
void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
@@ -1213,7 +1222,7 @@
@Nullable
ActivityRecord getHomeActivity() {
- return getHomeActivityForUser(mSupervisor.mCurrentUser);
+ return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
}
@Nullable
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 1c08d03..416e133 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -277,7 +277,8 @@
mLastLogTimeSecs = now;
mWindowState = WINDOW_STATE_INVALID;
- ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
+ ActivityStack stack =
+ mSupervisor.mRootActivityContainer.getTopDisplayFocusedStack();
if (stack == null) {
return;
}
@@ -289,7 +290,7 @@
@WindowingMode int windowingMode = stack.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {
- stack = mSupervisor.findStackBehind(stack);
+ stack = mSupervisor.mRootActivityContainer.findStackBehind(stack);
windowingMode = stack.getWindowingMode();
}
switch (windowingMode) {
@@ -850,9 +851,10 @@
builder.addTaggedData(FIELD_TARGET_UID_HAS_ANY_VISIBLE_WINDOW,
targetUidHasAnyVisibleWindow ? 1 : 0);
builder.addTaggedData(FIELD_TARGET_WHITELIST_TAG, targetWhitelistTag);
- builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName);
builder.addTaggedData(FIELD_COMING_FROM_PENDING_INTENT, comingFromPendingIntent ? 1 : 0);
- builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction());
+ if (intent != null) {
+ builder.addTaggedData(FIELD_INTENT_ACTION, intent.getAction());
+ }
if (callerApp != null) {
builder.addTaggedData(FIELD_PROCESS_RECORD_PROCESS_NAME, callerApp.mName);
builder.addTaggedData(FIELD_PROCESS_RECORD_CUR_PROC_STATE,
@@ -881,29 +883,34 @@
(nowUptime - callerApp.getWhenUnimportant()));
}
}
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY, r.realActivity.toShortString());
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0);
- if (r.lastVisibleTime != 0) {
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE,
- (nowUptime - r.lastVisibleTime));
- }
- if (r.resultTo != null) {
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME, r.resultTo.packageName);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME,
- r.resultTo.shortComponentName);
- }
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0);
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD,
- r.visibleIgnoringKeyguard ? 1 : 0);
- if (r.lastLaunchTime != 0) {
- builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH,
- (nowUptime - r.lastLaunchTime));
+ if (r != null) {
+ builder.addTaggedData(FIELD_TARGET_SHORT_COMPONENT_NAME, r.shortComponentName);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_LAUNCH_MODE, r.info.launchMode);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY,
+ r.realActivity.toShortString());
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_NO_DISPLAY, r.noDisplay ? 1 : 0);
+ if (r.lastVisibleTime != 0) {
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_VISIBLE,
+ (nowUptime - r.lastVisibleTime));
+ }
+ if (r.resultTo != null) {
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_PKG_NAME,
+ r.resultTo.packageName);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_RESULT_TO_SHORT_COMPONENT_NAME,
+ r.resultTo.shortComponentName);
+ }
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE, r.visible ? 1 : 0);
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_VISIBLE_IGNORING_KEYGUARD,
+ r.visibleIgnoringKeyguard ? 1 : 0);
+ if (r.lastLaunchTime != 0) {
+ builder.addTaggedData(FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH,
+ (nowUptime - r.lastLaunchTime));
+ }
}
mMetricsLogger.write(builder);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5e92b9e..b4aec35 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -18,7 +18,17 @@
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
+import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
+import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_NONE;
+import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
+import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
+import static android.app.ActivityOptions.ANIM_SCALE_UP;
import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
+import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -63,6 +73,7 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.res.Configuration.EMPTY;
@@ -111,12 +122,18 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
-import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.ActivityTaskManagerService
+ .RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.TaskPersister.DEBUG;
import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -147,6 +164,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Build;
@@ -167,11 +185,14 @@
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import android.view.AppTransitionAnimationSpec;
+import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IApplicationToken;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.util.XmlUtils;
@@ -200,7 +221,7 @@
/**
* An entry in the history stack, representing an activity.
*/
-final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
+final class ActivityRecord extends ConfigurationContainer {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
@@ -225,7 +246,9 @@
final ActivityTaskManagerService service; // owner
final IApplicationToken.Stub appToken; // window manager token
- AppWindowContainerController mWindowContainerController;
+ // TODO: Remove after unification
+ AppWindowToken mAppWindowToken;
+
final ActivityInfo info; // all about me
// TODO: This is duplicated state already contained in info.applicationInfo - remove
ApplicationInfo appInfo; // information about activity's app
@@ -322,6 +345,7 @@
private boolean inHistory; // are we in the history stack?
final ActivityStackSupervisor mStackSupervisor;
+ final RootActivityContainer mRootActivityContainer;
static final int STARTING_WINDOW_NOT_SHOWN = 0;
static final int STARTING_WINDOW_SHOWN = 1;
@@ -769,10 +793,16 @@
}
/**
- * See {@link AppWindowContainerController#setWillCloseOrEnterPip(boolean)}
+ * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
+ * This information helps AWT know that the app is in the process of pausing before it gets the
+ * signal on the WM side.
*/
void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
- getWindowContainerController().setWillCloseOrEnterPip(willCloseOrEnterPip);
+ if (mAppWindowToken == null) {
+ return;
+ }
+
+ mAppWindowToken.setWillCloseOrEnterPip(willCloseOrEnterPip);
}
static class Token extends IApplicationToken.Stub {
@@ -844,6 +874,7 @@
boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
ActivityOptions options, ActivityRecord sourceRecord) {
service = _service;
+ mRootActivityContainer = _service.mRootActivityContainer;
appToken = new Token(this, _intent);
info = aInfo;
launchedFromPid = _launchedFromPid;
@@ -991,13 +1022,9 @@
return hasProcess() && app.hasThread();
}
- AppWindowContainerController getWindowContainerController() {
- return mWindowContainerController;
- }
-
- void createWindowContainer() {
- if (mWindowContainerController != null) {
- throw new IllegalArgumentException("Window container=" + mWindowContainerController
+ void createAppWindowToken() {
+ if (mAppWindowToken != null) {
+ throw new IllegalArgumentException("App Window Token=" + mAppWindowToken
+ " already created for r=" + this);
}
@@ -1010,12 +1037,31 @@
// Make sure override configuration is up-to-date before using to create window controller.
updateOverrideConfiguration();
- mWindowContainerController = new AppWindowContainerController(taskController, appToken,
- realActivity, this, Integer.MAX_VALUE /* add on top */, info.screenOrientation,
- fullscreen, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
- task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
- appInfo.targetSdkVersion, mRotationAnimationHint,
- ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
+ // TODO: remove after unification
+ mAppWindowToken = service.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
+ if (mAppWindowToken != null) {
+ // TODO: Should this throw an exception instead?
+ Slog.w(TAG, "Attempted to add existing app token: " + appToken);
+ } else {
+ final Task container = taskController.mContainer;
+ if (container == null) {
+ throw new IllegalArgumentException("AppWindowContainerController: invalid "
+ + " controller=" + taskController);
+ }
+ mAppWindowToken = createAppWindow(service.mWindowManager, appToken,
+ task.voiceSession != null, container.getDisplayContent(),
+ ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
+ * 1000000L, fullscreen,
+ (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, appInfo.targetSdkVersion,
+ info.screenOrientation, mRotationAnimationHint, info.configChanges,
+ mLaunchTaskBehind, isAlwaysFocusable());
+ if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) {
+ Slog.v(TAG, "addAppToken: "
+ + mAppWindowToken + " controller=" + taskController + " at "
+ + Integer.MAX_VALUE);
+ }
+ container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
+ }
task.addActivityToTop(this);
@@ -1026,17 +1072,51 @@
mLastReportedPictureInPictureMode = inPinnedWindowingMode();
}
+ boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
+ CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
+ IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "setAppStartingWindow: token=" + appToken
+ + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
+ + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
+ + " allowTaskSnapshot=" + allowTaskSnapshot);
+ }
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
+ return false;
+ }
+ return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
+ labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
+ processRunning, allowTaskSnapshot, activityCreated, fromRecents);
+ }
+
+ // TODO: Remove after unification
+ @VisibleForTesting
+ AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+ boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+ boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+ int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+ boolean alwaysFocusable) {
+ return new AppWindowToken(service, token, realActivity, voiceInteraction, dc,
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
+ rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+ this);
+ }
+
void removeWindowContainer() {
- // Do not try to remove a window container if we have already removed it.
- if (mWindowContainerController == null) {
+ if (service.mWindowManager.mRoot == null) return;
+
+ final DisplayContent dc = service.mWindowManager.mRoot.getDisplayContent(
+ getDisplayId());
+ if (dc == null) {
+ Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
+ + appToken + " from non-existing displayId=" + getDisplayId());
return;
}
-
// Resume key dispatching if it is currently paused before we remove the container.
resumeKeyDispatchingLocked();
-
- mWindowContainerController.removeContainer(getDisplayId());
- mWindowContainerController = null;
+ dc.removeAppToken(appToken.asBinder());
}
/**
@@ -1044,6 +1124,10 @@
* should ensure that the {@param newTask} is not already the parent of this activity.
*/
void reparent(TaskRecord newTask, int position, String reason) {
+ if (mAppWindowToken == null) {
+ Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
+ return;
+ }
final TaskRecord prevTask = task;
if (prevTask == newTask) {
throw new IllegalArgumentException(reason + ": task=" + newTask
@@ -1059,8 +1143,7 @@
+ " r=" + this + " (" + prevTask.getStackId() + ")");
}
- // Must reparent first in window manager
- mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
+ mAppWindowToken.reparent(newTask.getWindowContainerController(), position);
// Reparenting prevents informing the parent stack of activity removal in the case that
// the new stack has the same parent. we must manually signal here if this is not the case.
@@ -1200,7 +1283,7 @@
}
boolean isFocusable() {
- return mStackSupervisor.isFocusable(this, isAlwaysFocusable());
+ return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
}
boolean isResizeable() {
@@ -1353,7 +1436,7 @@
return false;
}
- if (mStackSupervisor.getTopResumedActivity() == this) {
+ if (mRootActivityContainer.getTopResumedActivity() == this) {
if (DEBUG_FOCUS) {
Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
}
@@ -1366,7 +1449,7 @@
stack.moveToFront(reason, task);
// Report top activity change to tracking services and WM
- if (mStackSupervisor.getTopResumedActivity() == this) {
+ if (mRootActivityContainer.getTopResumedActivity() == this) {
// TODO(b/111361570): Support multiple focused apps in WM
service.setResumedActivityUncheckLocked(this, reason);
}
@@ -1490,7 +1573,7 @@
void applyOptionsLocked() {
if (pendingOptions != null
&& pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
- mWindowContainerController.applyOptionsLocked(pendingOptions, intent);
+ applyOptionsLocked(pendingOptions, intent);
if (task == null) {
clearOptionsLocked(false /* withAbort */);
} else {
@@ -1500,6 +1583,104 @@
}
}
+ /**
+ * Apply override app transition base on options & animation type.
+ */
+ void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
+ final int animationType = pendingOptions.getAnimationType();
+ final DisplayContent displayContent = mAppWindowToken.getDisplayContent();
+ switch (animationType) {
+ case ANIM_CUSTOM:
+ displayContent.mAppTransition.overridePendingAppTransition(
+ pendingOptions.getPackageName(),
+ pendingOptions.getCustomEnterResId(),
+ pendingOptions.getCustomExitResId(),
+ pendingOptions.getOnAnimationStartListener());
+ break;
+ case ANIM_CLIP_REVEAL:
+ displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight());
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX() + pendingOptions.getWidth(),
+ pendingOptions.getStartY() + pendingOptions.getHeight()));
+ }
+ break;
+ case ANIM_SCALE_UP:
+ displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight());
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX() + pendingOptions.getWidth(),
+ pendingOptions.getStartY() + pendingOptions.getHeight()));
+ }
+ break;
+ case ANIM_THUMBNAIL_SCALE_UP:
+ case ANIM_THUMBNAIL_SCALE_DOWN:
+ final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
+ final GraphicBuffer buffer = pendingOptions.getThumbnail();
+ displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getOnAnimationStartListener(),
+ scaleUp);
+ if (intent.getSourceBounds() == null && buffer != null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX() + buffer.getWidth(),
+ pendingOptions.getStartY() + buffer.getHeight()));
+ }
+ break;
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
+ final IAppTransitionAnimationSpecsFuture specsFuture =
+ pendingOptions.getSpecsFuture();
+ if (specsFuture != null) {
+ // TODO(multidisplay): Shouldn't be really used anymore from next CL.
+ displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
+ specsFuture, pendingOptions.getOnAnimationStartListener(),
+ animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
+ } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
+ && specs != null) {
+ displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
+ specs, pendingOptions.getOnAnimationStartListener(),
+ pendingOptions.getAnimationFinishedListener(), false);
+ } else {
+ displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
+ pendingOptions.getThumbnail(),
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight(),
+ pendingOptions.getOnAnimationStartListener(),
+ (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX() + pendingOptions.getWidth(),
+ pendingOptions.getStartY() + pendingOptions.getHeight()));
+ }
+ }
+ break;
+ case ANIM_OPEN_CROSS_PROFILE_APPS:
+ displayContent.mAppTransition
+ .overridePendingAppTransitionStartCrossProfileApps();
+ break;
+ case ANIM_REMOTE_ANIMATION:
+ // TODO(multidisplay): Will pass displayId and adjust dependencies from next CL.
+ displayContent.mAppTransition.overridePendingAppTransitionRemote(
+ pendingOptions.getRemoteAnimationAdapter());
+ break;
+ case ANIM_NONE:
+ break;
+ default:
+ Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
+ break;
+ }
+ }
+
ActivityOptions getOptionsForTargetActivityLocked() {
return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
}
@@ -1532,8 +1713,11 @@
if (!keysPaused) {
keysPaused = true;
- if (mWindowContainerController != null) {
- mWindowContainerController.pauseKeyDispatching();
+ // TODO: remove the check after unification with AppWindowToken. The DC check is not
+ // needed after no mock mAppWindowToken in tests.
+ if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
+ mAppWindowToken.getDisplayContent().getInputMonitor().pauseDispatchingLw(
+ mAppWindowToken);
}
}
}
@@ -1542,8 +1726,11 @@
if (keysPaused) {
keysPaused = false;
- if (mWindowContainerController != null) {
- mWindowContainerController.resumeKeyDispatching();
+ // TODO: remove the check after unification with AppWindowToken. The DC check is not
+ // needed after no mock mAppWindowToken in tests.
+ if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
+ mAppWindowToken.getDisplayContent().getInputMonitor().resumeDispatchingLw(
+ mAppWindowToken);
}
}
}
@@ -1565,11 +1752,16 @@
}
void setVisibility(boolean visible) {
- mWindowContainerController.setVisibility(visible, mDeferHidingClient);
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
+ + appToken);
+ return;
+ }
+ mAppWindowToken.setVisibility(visible, mDeferHidingClient);
mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
}
- // TODO: Look into merging with #setVisibility()
+ // TODO: Look into merging with #commitVisibility()
void setVisible(boolean newVisible) {
visible = newVisible;
mDeferHidingClient = !visible && mDeferHidingClient;
@@ -1599,7 +1791,12 @@
// 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();
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
+ + appToken);
+ return;
+ }
+ mAppWindowToken.detachChildren();
}
}
@@ -1637,7 +1834,12 @@
}
void notifyAppResumed(boolean wasStopped) {
- mWindowContainerController.notifyAppResumed(wasStopped);
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
+ + appToken);
+ return;
+ }
+ mAppWindowToken.notifyAppResumed(wasStopped);
}
void notifyUnknownVisibilityLaunched() {
@@ -1645,7 +1847,10 @@
// No display activities never add a window, so there is no point in waiting them for
// relayout.
if (!noDisplay) {
- mWindowContainerController.notifyUnknownVisibilityLaunched();
+ if (mAppWindowToken != null) {
+ mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
+ .notifyLaunched(mAppWindowToken);
+ }
}
}
@@ -1857,16 +2062,18 @@
stopped = true;
setState(STOPPED, "activityStoppedLocked");
- mWindowContainerController.notifyAppStopped();
+ if (mAppWindowToken != null) {
+ mAppWindowToken.notifyAppStopped();
+ }
if (finishing) {
clearOptionsLocked();
} else {
if (deferRelaunchUntilPaused) {
stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
} else {
- mStackSupervisor.updatePreviousProcessLocked(this);
+ mRootActivityContainer.updatePreviousProcess(this);
}
}
}
@@ -1918,14 +2125,33 @@
public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
if (mayFreezeScreenLocked(app)) {
- mWindowContainerController.startFreezingScreen(configChanges);
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM,
+ "Attempted to freeze screen with non-existing app token: " + appToken);
+ return;
+ }
+
+ if (configChanges == 0 && mAppWindowToken.okToDisplay()) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + appToken);
+ return;
+ }
+
+ mAppWindowToken.startFreezingScreen();
}
}
public void stopFreezingScreenLocked(boolean force) {
if (force || frozenBeforeDestroy) {
frozenBeforeDestroy = false;
- mWindowContainerController.stopFreezingScreen(force);
+ if (mAppWindowToken == null) {
+ return;
+ }
+ if (DEBUG_ORIENTATION) {
+ Slog.v(TAG_WM, "Clear freezing of " + appToken + ": hidden="
+ + mAppWindowToken.isHidden() + " freezing="
+ + mAppWindowToken.isFreezingScreen());
+ }
+ mAppWindowToken.stopFreezingScreen(true, force);
}
}
@@ -1937,7 +2163,10 @@
info.windowsFullyDrawnDelayMs);
}
}
- @Override
+
+ /**
+ * Called when the starting window for this container is drawn.
+ */
public void onStartingWindowDrawn(long timestamp) {
synchronized (service.mGlobalLock) {
mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
@@ -1945,7 +2174,7 @@
}
}
- @Override
+ /** Called when the windows associated app window container are drawn. */
public void onWindowsDrawn(boolean drawn, long timestamp) {
synchronized (service.mGlobalLock) {
mDrawn = drawn;
@@ -1965,7 +2194,7 @@
}
}
- @Override
+ /** Called when the windows associated app window container are visible. */
public void onWindowsVisible() {
synchronized (service.mGlobalLock) {
mStackSupervisor.reportActivityVisibleLocked(this);
@@ -1999,7 +2228,7 @@
}
}
- @Override
+ /** Called when the windows associated app window container are no longer visible. */
public void onWindowsGone() {
synchronized (service.mGlobalLock) {
if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
@@ -2007,7 +2236,14 @@
}
}
- @Override
+ /**
+ * Called when the key dispatching to a window associated with the app window container
+ * timed-out.
+ *
+ * @param reason The reason for the key dispatching time out.
+ * @param windowPid The pid of the window key dispatching timed out on.
+ * @return True if input dispatching should be aborted.
+ */
public boolean keyDispatchingTimedOut(String reason, int windowPid) {
ActivityRecord anrActivity;
WindowProcessController anrApp;
@@ -2036,7 +2272,7 @@
// another activity to start or has stopped, then the key dispatching
// timeout should not be caused by this.
if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
- final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
// Try to use the one which is closest to top.
ActivityRecord r = stack.getResumedActivity();
if (r == null) {
@@ -2183,7 +2419,7 @@
void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
boolean fromRecents) {
- if (mWindowContainerController == null) {
+ if (mAppWindowToken == null) {
return;
}
if (mTaskOverlay) {
@@ -2198,7 +2434,7 @@
final CompatibilityInfo compatInfo =
service.compatibilityInfoForPackageLocked(info.applicationInfo);
- final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
+ final boolean shown = addStartingWindow(packageName, theme,
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
allowTaskSnapshot(),
@@ -2213,34 +2449,62 @@
if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
mStartingWindowState = STARTING_WINDOW_REMOVED;
- mWindowContainerController.removeStartingWindow();
+ mAppWindowToken.removeStartingWindow();
}
}
int getRequestedOrientation() {
- return mWindowContainerController.getOrientation();
+ return getOrientation();
}
void setRequestedOrientation(int requestedOrientation) {
final int displayId = getDisplayId();
final Configuration displayConfig =
- mStackSupervisor.getDisplayOverrideConfiguration(displayId);
+ mRootActivityContainer.getDisplayOverrideConfiguration(displayId);
- final Configuration config = mWindowContainerController.setOrientation(requestedOrientation,
+ final Configuration config = setOrientation(requestedOrientation,
displayId, displayConfig, mayFreezeScreenLocked(app));
if (config != null) {
frozenBeforeDestroy = true;
if (!service.updateDisplayOverrideConfigurationLocked(config, this,
false /* deferResume */, displayId)) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
service.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
task.taskId, requestedOrientation);
}
+ Configuration setOrientation(int requestedOrientation, int displayId,
+ Configuration displayConfig, boolean freezeScreenIfNeeded) {
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM,
+ "Attempted to set orientation of non-existing app token: " + appToken);
+ return null;
+ }
+
+ mAppWindowToken.setOrientation(requestedOrientation);
+
+ final IBinder binder = freezeScreenIfNeeded ? appToken.asBinder() : null;
+ return service.mWindowManager.updateOrientationFromAppTokens(displayConfig, binder,
+ displayId);
+ }
+
+ int getOrientation() {
+ if (mAppWindowToken == null) {
+ return SCREEN_ORIENTATION_UNSPECIFIED;
+ }
+
+ return mAppWindowToken.getOrientationIgnoreVisibility();
+ }
+
void setDisablePreviewScreenshots(boolean disable) {
- mWindowContainerController.setDisablePreviewScreenshots(disable);
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
+ + " token: " + appToken);
+ return;
+ }
+ mAppWindowToken.setDisablePreviewScreenshots(disable);
}
/**
@@ -2288,8 +2552,8 @@
/** Returns true if the configuration is compatible with this activity. */
boolean isConfigurationCompatible(Configuration config) {
- final int orientation = mWindowContainerController != null
- ? mWindowContainerController.getOrientation() : info.screenOrientation;
+ final int orientation = mAppWindowToken != null
+ ? getOrientation() : info.screenOrientation;
if (isFixedOrientationPortrait(orientation)
&& config.orientation != ORIENTATION_PORTRAIT) {
return false;
@@ -2867,7 +3131,7 @@
void setShowWhenLocked(boolean showWhenLocked) {
mShowWhenLocked = showWhenLocked;
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0 /* configChanges */,
+ mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */,
false /* preserveWindows */);
}
@@ -2905,7 +3169,7 @@
}
boolean isTopRunningActivity() {
- return mStackSupervisor.topRunningActivityLocked() == this;
+ return mRootActivityContainer.topRunningActivity() == this;
}
/**
@@ -2918,7 +3182,12 @@
}
void registerRemoteAnimations(RemoteAnimationDefinition definition) {
- mWindowContainerController.registerRemoteAnimations(definition);
+ if (mAppWindowToken == null) {
+ Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
+ + " token: " + appToken);
+ return;
+ }
+ mAppWindowToken.registerRemoteAnimations(definition);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index bd3e43c..9fbeaf8 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -63,7 +63,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -103,6 +102,7 @@
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+import static com.android.server.wm.RootActivityContainer.FindTaskResult;
import static java.lang.Integer.MAX_VALUE;
@@ -267,7 +267,7 @@
mStackSupervisor.resizeDockedStackLocked(
getOverrideBounds(), mTmpRect2, mTmpRect2, null, null, PRESERVE_WINDOWS);
}
- mStackSupervisor.updateUIDsPresentOnDisplay();
+ mRootActivityContainer.updateUIDsPresentOnDisplay();
}
enum ActivityState {
@@ -390,6 +390,7 @@
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
+ protected final RootActivityContainer mRootActivityContainer;
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -489,6 +490,7 @@
int windowingMode, int activityType, boolean onTop) {
mStackSupervisor = supervisor;
mService = supervisor.mService;
+ mRootActivityContainer = mService.mRootActivityContainer;
mHandler = new ActivityStackHandler(supervisor.mLooper);
mWindowManager = mService.mWindowManager;
mStackId = stackId;
@@ -508,7 +510,7 @@
T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds,
- mStackSupervisor.mWindowManager);
+ mRootActivityContainer.mWindowManager);
}
T getWindowContainerController() {
@@ -532,7 +534,7 @@
if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
+ reason);
setResumedActivity(record, reason + " - onActivityStateChanged");
- if (record == mStackSupervisor.getTopResumedActivity()) {
+ if (record == mRootActivityContainer.getTopResumedActivity()) {
// TODO(b/111361570): Support multiple focused apps in WM
mService.setResumedActivityUncheckLocked(record, reason);
}
@@ -622,7 +624,7 @@
display.onStackWindowingModeChanged(this);
}
if (hasNewOverrideBounds) {
- mStackSupervisor.resizeStackLocked(this, mTmpRect2, null, null, PRESERVE_WINDOWS,
+ mRootActivityContainer.resizeStack(this, mTmpRect2, null, null, PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, true /* deferResume */);
}
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -819,8 +821,8 @@
}
if (!deferEnsuringVisibility) {
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
@@ -854,10 +856,10 @@
/** Resume next focusable stack after reparenting to another display. */
void postReparent() {
adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
// Update visibility of activities before notifying WM. This way it won't try to resize
// windows that are no longer visible.
- mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
+ mRootActivityContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
!PRESERVE_WINDOWS);
}
@@ -882,7 +884,7 @@
}
ActivityDisplay getDisplay() {
- return mStackSupervisor.getActivityDisplay(mDisplayId);
+ return mRootActivityContainer.getActivityDisplay(mDisplayId);
}
/**
@@ -1034,7 +1036,7 @@
}
/**
- * This is a simplified version of topRunningActivityLocked that provides a number of
+ * This is a simplified version of topRunningActivity that provides a number of
* optional skip-over modes. It is intended for use with the ActivityController hook only.
*
* @param token If non-null, any history records matching this token will be skipped.
@@ -1236,7 +1238,7 @@
boolean isFocusable() {
final ActivityRecord r = topRunningActivityLocked();
- return mStackSupervisor.isFocusable(this, r != null && r.isFocusable());
+ return mRootActivityContainer.isFocusable(this, r != null && r.isFocusable());
}
boolean isFocusableAndVisible() {
@@ -1398,7 +1400,7 @@
final TaskRecord task = mTaskHistory.get(i);
if (task.okToShowLocked()) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() +
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() +
" moving " + task + " to top");
mTaskHistory.remove(i);
mTaskHistory.add(task);
@@ -1587,7 +1589,7 @@
if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return false;
}
@@ -1665,7 +1667,7 @@
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
if (resuming == null) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return false;
}
@@ -1704,7 +1706,7 @@
}
}
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
@@ -1757,9 +1759,9 @@
}
if (resumeNext) {
- final ActivityStack topStack = mStackSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
if (!topStack.shouldSleepOrShutDownActivities()) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(topStack, prev, null);
+ mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null);
} else {
checkReadyForSleep();
ActivityRecord top = topStack.topRunningActivityLocked();
@@ -1768,7 +1770,7 @@
// something. Also if the top activity on the stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -1799,7 +1801,7 @@
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
- mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
@@ -2011,7 +2013,7 @@
/**
* Ensure visibility with an option to also update the configuration of visible activities.
* @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
- * @see ActivityStackSupervisor#ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
+ * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
*/
// TODO: Should be re-worked based on the fact that each task as a stack in most cases.
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
@@ -2032,7 +2034,7 @@
boolean aboveTop = top != null;
final boolean stackShouldBeVisible = shouldBeVisible(starting);
boolean behindFullscreenActivity = !stackShouldBeVisible;
- boolean resumeNextActivity = mStackSupervisor.isTopDisplayFocusedStack(this)
+ boolean resumeNextActivity = mRootActivityContainer.isTopDisplayFocusedStack(this)
&& (isInStackLocked(starting) == null);
final boolean isTopNotPinnedStack =
isAttached() && getDisplay().isTopNotPinnedStack(this);
@@ -2443,7 +2445,7 @@
*
* NOTE: It is not safe to call this method directly as it can cause an activity in a
* non-focused stack to be resumed.
- * Use {@link ActivityStackSupervisor#resumeFocusedStacksTopActivitiesLocked} to resume the
+ * Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the
* right activity for the current system state.
*/
@GuardedBy("mService")
@@ -2513,7 +2515,7 @@
return false;
}
- mStackSupervisor.cancelInitializingActivities();
+ mRootActivityContainer.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
@@ -2536,7 +2538,6 @@
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
@@ -2544,7 +2545,7 @@
// activity is paused, well that is the state we want.
if (shouldSleepOrShutDownActivities()
&& mLastPausedActivity == next
- && mStackSupervisor.allPausedActivitiesComplete()) {
+ && mRootActivityContainer.allPausedActivitiesComplete()) {
// If the current top activity may be able to occlude keyguard but the occluded state
// has not been set, update visibility and check again if we should continue to resume.
boolean nothingToResume = true;
@@ -2565,7 +2566,6 @@
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
}
@@ -2576,7 +2576,6 @@
if (!mService.mAmInternal.hasStartedUserState(next.userId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.userId + " is stopped");
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
@@ -2590,10 +2589,9 @@
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything until that is done.
- if (!mStackSupervisor.allPausedActivitiesComplete()) {
+ if (!mRootActivityContainer.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
@@ -2640,7 +2638,6 @@
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
true /* updateLru */, true /* activityChange */, false /* updateOomAdj */);
}
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (lastResumed != null) {
lastResumed.setWillCloseOrEnterPip(true);
}
@@ -2655,7 +2652,6 @@
executeAppTransition(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
@@ -2673,7 +2669,7 @@
if (prev != null && prev != next) {
if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
- && next != null && !next.nowVisible) {
+ && !next.nowVisible) {
mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Resuming top, waiting visible to hide: " + prev);
@@ -2814,7 +2810,7 @@
// result of invisible window resize.
// TODO: Remove this once visibilities are set correctly immediately when
// starting an activity.
- notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+ notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
@@ -2836,7 +2832,6 @@
next.setVisibility(true);
}
next.completeResumeLocked();
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
@@ -2899,7 +2894,6 @@
false /* taskSwitch */);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
@@ -2913,7 +2907,6 @@
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
} else {
@@ -2931,7 +2924,6 @@
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
@@ -2942,7 +2934,7 @@
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display (with no home
// stack).
- return mStackSupervisor.resumeFocusedStacksTopActivitiesLocked(nextFocusedStack, prev,
+ return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, prev,
null /* targetOptions */);
}
@@ -2950,8 +2942,7 @@
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityInNextFocusableStack: " + reason + ", go home");
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return mStackSupervisor.resumeHomeActivity(prev, reason, mDisplayId);
+ return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId);
}
/** Returns the position the input task should be placed in this stack. */
@@ -3043,7 +3034,7 @@
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
- r.createWindowContainer();
+ r.createAppWindowToken();
ActivityOptions.abort(options);
return;
}
@@ -3073,9 +3064,10 @@
// TODO: Need to investigate if it is okay for the controller to already be created by the
// time we get to this point. I think it is, but need to double check.
// Use test in b/34179495 to trace the call path.
- if (r.getWindowContainerController() == null) {
- r.createWindowContainer();
+ if (r.mAppWindowToken == null) {
+ r.createAppWindowToken();
}
+
task.setFrontOfTask();
if (!isHomeOrRecentsStack() || numActivities() > 0) {
@@ -3536,7 +3528,7 @@
}
private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
- if (!mStackSupervisor.isTopDisplayFocusedStack(this) ||
+ if (!mRootActivityContainer.isTopDisplayFocusedStack(this) ||
((mResumedActivity != r) && (mResumedActivity != null))) {
return;
}
@@ -3545,7 +3537,7 @@
final String myReason = reason + " adjustFocus";
if (next == r) {
- final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+ final ActivityRecord top = mRootActivityContainer.topRunningActivity();
if (top != null) {
top.moveFocusableActivityToTop(myReason);
}
@@ -3569,7 +3561,7 @@
final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason);
if (nextFocusableStack != null) {
final ActivityRecord top = nextFocusableStack.topRunningActivityLocked();
- if (top != null && top == mStackSupervisor.getTopResumedActivity()) {
+ if (top != null && top == mRootActivityContainer.getTopResumedActivity()) {
// TODO(b/111361570): Remove this and update focused app per-display in
// WindowManager every time an activity becomes resumed in
// ActivityTaskManagerService#setResumedActivityUncheckLocked().
@@ -3597,7 +3589,7 @@
*/
private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
final ActivityStack stack =
- mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf);
+ mRootActivityContainer.getNextFocusableStack(this, !allowFocusSelf);
final String myReason = reason + " adjustFocusToNextFocusableStack";
if (stack == null) {
return null;
@@ -4018,11 +4010,11 @@
// stack, need to make something visible in its place. Also if the display does not
// have running activity, the configuration may need to be updated for restoring
// original orientation of the display.
- mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+ mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"destroyActivityLocked: finishCurrentActivityLocked r=" + r +
@@ -4035,7 +4027,7 @@
if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
mStackSupervisor.mFinishingActivities.add(r);
r.resumeKeyDispatchingLocked();
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
return r;
}
@@ -4377,7 +4369,7 @@
}
}
if (activityRemoved) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
@@ -4568,7 +4560,7 @@
}
}
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
@@ -4712,7 +4704,7 @@
task.mLastTimeMoved *= -1;
}
}
- mStackSupervisor.invalidateTaskLayers();
+ mRootActivityContainer.invalidateTaskLayers();
}
final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
@@ -4788,7 +4780,7 @@
topActivity.supportsEnterPipOnTaskSwitch = true;
}
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.taskId);
@@ -4860,7 +4852,7 @@
return true;
}
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
return true;
}
@@ -4907,7 +4899,7 @@
if (updatedConfig) {
// Ensure the resumed state of the focus activity if we updated the configuration of
// any activity.
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
@@ -5099,7 +5091,7 @@
*/
void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType,
@WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) {
- boolean focusedStack = mStackSupervisor.getTopDisplayFocusedStack() == this;
+ boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this;
boolean topTask = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
@@ -5164,7 +5156,7 @@
return removeHistoryRecordsForAppLocked(app);
}
- void handleAppCrashLocked(WindowProcessController app) {
+ void handleAppCrash(WindowProcessController app) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -5311,7 +5303,7 @@
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP
- && mStackSupervisor.isTopDisplayFocusedStack(this)) {
+ && mRootActivityContainer.isTopDisplayFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
getDisplay().moveHomeStackToFront(myReason);
@@ -5417,7 +5409,7 @@
// The task might have already been running and its visibility needs to be synchronized with
// the visibility of the stack / windows.
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
@@ -5484,7 +5476,7 @@
moveToFront(reason);
// If the original state is resumed, there is no state change to update focused app.
// So here makes sure the activity focus is set if it is the top.
- if (origState == RESUMED && r == mStackSupervisor.getTopResumedActivity()) {
+ if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) {
// TODO(b/111361570): Support multiple focused apps in WM
mService.setResumedActivityUncheckLocked(r, reason);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index c517bd7..3162ee3 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -25,28 +25,18 @@
import static android.app.ActivityManager.START_FLAG_NATIVE_DEBUGGING;
import static android.app.ActivityManager.START_FLAG_TRACK_ALLOCATION;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WaitResult.INVALID_DELAY;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.app.WindowConfiguration.activityTypeToString;
-import static android.app.WindowConfiguration.windowingModeToString;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
-import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -59,26 +49,13 @@
import static android.view.Display.TYPE_VIRTUAL;
import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
-import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
-import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
-import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
-import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
-import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -86,9 +63,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
@@ -96,6 +71,10 @@
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.android.server.wm.RootActivityContainer.TAG_STATES;
import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
@@ -103,20 +82,11 @@
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
-import static java.lang.Integer.MAX_VALUE;
-
import android.Manifest;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
-import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
@@ -139,17 +109,11 @@
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
-import android.hardware.display.DisplayManagerInternal;
-import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
-import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -163,20 +127,13 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.MediaStore;
-import android.service.voice.IVoiceInteractionSession;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.DisplayMetrics;
import android.util.EventLog;
-import android.util.IntArray;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
-import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-import android.view.Display;
-import android.view.DisplayInfo;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -185,34 +142,28 @@
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.function.pooled.PooledLambda;
-import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService;
-import com.android.server.am.AppTimeTracker;
import com.android.server.am.EventLogTags;
import com.android.server.am.UserState;
-import com.android.server.wm.ActivityStack.ActivityState;
-import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
-import java.util.Set;
-public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
- RecentTasks.Callbacks, RootWindowContainerListener {
+// TODO: This class has become a dumping ground. Let's
+// - Move things relating to the hierarchy to RootWindowContainer
+// - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler
+// - Move interface things to ActivityTaskManagerService.
+// - All other little things to other files.
+public class ActivityStackSupervisor implements RecentTasks.Callbacks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_ATM;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
- private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
- static final String TAG_STATES = TAG + POSTFIX_STATES;
static final String TAG_TASKS = TAG + POSTFIX_TASKS;
/** How long we wait until giving up on the last activity telling us it is idle. */
@@ -233,12 +184,6 @@
static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;
- private static final String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
-
- // Used to indicate if an object (e.g. stack) that we are trying to get
- // should be created if it doesn't exist already.
- static final boolean CREATE_IF_NEEDED = true;
-
// Used to indicate that windows of activities should be preserved during the resize.
static final boolean PRESERVE_WINDOWS = true;
@@ -270,25 +215,6 @@
private Rect mPendingTempOtherTaskBounds;
private Rect mPendingTempOtherTaskInsetBounds;
- /**
- * The modes which affect which tasks are returned when calling
- * {@link ActivityStackSupervisor#anyTaskForIdLocked(int)}.
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- MATCH_TASK_IN_STACKS_ONLY,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- })
- public @interface AnyTaskForIdMatchTaskMode {}
- // Match only tasks in the current stacks
- static final int MATCH_TASK_IN_STACKS_ONLY = 0;
- // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
- static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
- // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
- // provided stack id
- static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
-
// Activity actions an app cannot start if it uses a permission which is not granted.
private static final ArrayMap<String, String> ACTION_TO_RUNTIME_PERMISSION =
new ArrayMap<>();
@@ -316,19 +242,19 @@
private static final int MAX_TASK_IDS_PER_USER = UserHandle.PER_USER_RANGE;
final ActivityTaskManagerService mService;
+ RootActivityContainer mRootActivityContainer;
/** The historial list of recent tasks including inactive tasks */
RecentTasks mRecentTasks;
/** Helper class to abstract out logic for fetching the set of currently running tasks */
- private RunningTasks mRunningTasks;
+ RunningTasks mRunningTasks;
final ActivityStackSupervisorHandler mHandler;
final Looper mLooper;
/** Short cut */
WindowManagerService mWindowManager;
- DisplayManager mDisplayManager;
/** Common synchronization logic used to save things to disks. */
PersisterQueue mPersisterQueue;
@@ -341,9 +267,6 @@
*/
private final SparseIntArray mCurTaskIdForUser = new SparseIntArray(20);
- /** The current user */
- int mCurrentUser;
-
/** List of activities that are waiting for a new activity to become visible before completing
* whatever operation they are supposed to do. */
// TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from
@@ -392,9 +315,6 @@
* is being brought in front of us. */
boolean mUserLeaving = false;
- /** Set when a power hint has started, but not ended. */
- private boolean mPowerHintSent;
-
/**
* We don't want to allow the device to go to sleep while in the process
* of launching an activity. This is primarily to allow alarm intent
@@ -410,29 +330,6 @@
*/
PowerManager.WakeLock mGoingToSleep;
- /**
- * A list of tokens that cause the top activity to be put to sleep.
- * They are used by components that may hide and block interaction with underlying
- * activities.
- */
- final ArrayList<SleepToken> mSleepTokens = new ArrayList<>();
-
- /** Stack id of the front stack when user switched, indexed by userId. */
- SparseIntArray mUserStackInFront = new SparseIntArray(2);
-
- /** Reference to default display so we can quickly look it up. */
- private ActivityDisplay mDefaultDisplay;
-
- /**
- * List of displays which contain activities, sorted by z-order.
- * The last entry in the list is the topmost.
- */
- private final ArrayList<ActivityDisplay> mActivityDisplays = new ArrayList<>();
-
- private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
-
- private DisplayManagerInternal mDisplayManagerInternal;
-
/** Used to keep resumeTopActivityUncheckedLocked() from being entered recursively */
boolean inResumeTopActivity;
@@ -443,50 +340,8 @@
private final Rect tempRect = new Rect();
private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
- // The default minimal size that will be used if the activity doesn't specify its minimal size.
- // It will be calculated when the default display gets added.
- int mDefaultMinSizeOfResizeableTaskDp = -1;
-
- // Whether tasks have moved and we need to rank the tasks before next OOM scoring
- private boolean mTaskLayersChanged = true;
-
private ActivityMetricsLogger mActivityMetricsLogger;
- private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>();
-
- @Override
- protected int getChildCount() {
- return mActivityDisplays.size();
- }
-
- @Override
- protected ActivityDisplay getChildAt(int index) {
- return mActivityDisplays.get(index);
- }
-
- @Override
- protected ConfigurationContainer getParent() {
- return null;
- }
-
- Configuration getDisplayOverrideConfiguration(int displayId) {
- final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
- if (activityDisplay == null) {
- throw new IllegalArgumentException("No display found with id: " + displayId);
- }
-
- return activityDisplay.getOverrideConfiguration();
- }
-
- void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
- final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
- if (activityDisplay == null) {
- throw new IllegalArgumentException("No display found with id: " + displayId);
- }
-
- activityDisplay.onOverrideConfigurationChanged(overrideConfiguration);
- }
-
/** Check if placing task or activity on specified display is allowed. */
boolean canPlaceEntityOnDisplay(int displayId, int callingPid, int callingUid,
ActivityInfo activityInfo) {
@@ -508,44 +363,6 @@
}
/**
- * Check if configuration of specified display matches current global config.
- * Used to check if we can put a non-resizeable activity on a secondary display and it will get
- * the same config as on the default display.
- * @param displayId Id of the display to check.
- * @return {@code true} if configuration matches.
- */
- private boolean displayConfigMatchesGlobal(int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- return true;
- }
- if (displayId == INVALID_DISPLAY) {
- return false;
- }
- final ActivityDisplay targetDisplay = getActivityDisplayOrCreateLocked(displayId);
- if (targetDisplay == null) {
- throw new IllegalArgumentException("No display found with id: " + displayId);
- }
- return getConfiguration().equals(targetDisplay.getConfiguration());
- }
-
- static class FindTaskResult {
- ActivityRecord mRecord;
- boolean mIdealMatch;
-
- void clear() {
- mRecord = null;
- mIdealMatch = false;
- }
-
- void setTo(FindTaskResult result) {
- mRecord = result.mRecord;
- mIdealMatch = result.mIdealMatch;
- }
- }
-
- private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
-
- /**
* Used to keep track whether app visibilities got changed since the last pause. Useful to
* determine whether to invoke the task stack change listener after pausing.
*/
@@ -565,11 +382,6 @@
*/
private boolean mAllowDockedStackResize = true;
- /**
- * Is dock currently minimized.
- */
- boolean mIsDockMinimized;
-
private KeyguardController mKeyguardController;
private PowerManager mPowerManager;
@@ -577,8 +389,6 @@
private boolean mInitialized;
- private RootWindowContainerController mWindowContainerController;
-
/**
* Description of a request to start a new activity, which has been held
* due to app switches being disabled.
@@ -617,11 +427,6 @@
mHandler = new ActivityStackSupervisorHandler(looper);
}
- @VisibleForTesting
- void setWindowContainerController(RootWindowContainerController controller) {
- mWindowContainerController = controller;
- }
-
public void initialize() {
if (mInitialized) {
return;
@@ -676,321 +481,16 @@
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
getKeyguardController().setWindowManager(wm);
- setWindowContainerController(new RootWindowContainerController(this));
-
- mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
- mDisplayManager.registerDisplayListener(this, mHandler);
- mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-
- final Display[] displays = mDisplayManager.getDisplays();
- for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
- final Display display = displays[displayNdx];
- final ActivityDisplay activityDisplay = new ActivityDisplay(this, display);
- if (activityDisplay.mDisplayId == DEFAULT_DISPLAY) {
- mDefaultDisplay = activityDisplay;
- }
- addChild(activityDisplay, ActivityDisplay.POSITION_TOP);
- }
- calculateDefaultMinimalSizeOfResizeableTasks();
-
- final ActivityDisplay defaultDisplay = getDefaultDisplay();
-
- defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
- positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP);
- }
-
- /** Change the z-order of the given display. */
- private void positionChildAt(ActivityDisplay display, int position) {
- if (position >= mActivityDisplays.size()) {
- position = mActivityDisplays.size() - 1;
- } else if (position < 0) {
- position = 0;
- }
-
- if (mActivityDisplays.isEmpty()) {
- mActivityDisplays.add(display);
- } else if (mActivityDisplays.get(position) != display) {
- mActivityDisplays.remove(display);
- mActivityDisplays.add(position, display);
- }
- }
-
- @Override
- public void onChildPositionChanged(DisplayWindowController childController, int position) {
- // Assume AM lock is held from positionChildAt of controller in each hierarchy.
- final ActivityDisplay display = getActivityDisplay(childController.getDisplayId());
- if (display != null) {
- positionChildAt(display, position);
- }
- }
-
- ActivityStack getTopDisplayFocusedStack() {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack();
- if (focusedStack != null) {
- return focusedStack;
- }
- }
- return null;
- }
-
- ActivityRecord getTopResumedActivity() {
- final ActivityStack focusedStack = getTopDisplayFocusedStack();
- if (focusedStack == null) {
- return null;
- }
- final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
- if (resumedActivity != null && resumedActivity.app != null) {
- return resumedActivity;
- }
- // The top focused stack might not have a resumed activity yet - look on all displays in
- // focus order.
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
- if (resumedActivityOnDisplay != null) {
- return resumedActivityOnDisplay;
- }
- }
- return null;
- }
-
- boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
- if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) {
- return false;
- }
-
- return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
- }
-
- boolean isTopDisplayFocusedStack(ActivityStack stack) {
- return stack != null && stack == getTopDisplayFocusedStack();
}
void moveRecentsStackToFront(String reason) {
- final ActivityStack recentsStack = getDefaultDisplay().getStack(
+ final ActivityStack recentsStack = mRootActivityContainer.getDefaultDisplay().getStack(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
if (recentsStack != null) {
recentsStack.moveToFront(reason);
}
}
- boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
- if (!mService.isBooting() && !mService.isBooted()) {
- // Not ready yet!
- return false;
- }
-
- if (displayId == INVALID_DISPLAY) {
- displayId = DEFAULT_DISPLAY;
- }
-
- final ActivityRecord r = getActivityDisplay(displayId).getHomeActivity();
- final String myReason = reason + " resumeHomeActivity";
-
- // Only resume home activity if isn't finishing.
- if (r != null && !r.finishing) {
- r.moveFocusableActivityToTop(myReason);
- return resumeFocusedStacksTopActivitiesLocked(r.getStack(), prev, null);
- }
- return startHomeOnDisplay(mCurrentUser, myReason, displayId);
- }
-
- /**
- * Check if home activity start should be allowed on a display.
- * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
- * @param displayId The id of the target display.
- * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
- * @return {@code true} if allow to launch, {@code false} otherwise.
- */
- boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
- boolean allowInstrumenting) {
- if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
- && mService.mTopAction == null) {
- // We are running in factory test mode, but unable to find the factory test app, so
- // just sit around displaying the error message and don't try to start anything.
- return false;
- }
-
- final WindowProcessController app =
- mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
- if (!allowInstrumenting && app != null && app.isInstrumenting()) {
- // Don't do this if the home app is currently being instrumented.
- return false;
- }
-
- if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
- && displayId == mService.mVr2dDisplayId)) {
- // No restrictions to default display or vr 2d display.
- return true;
- }
-
- final ActivityDisplay display = getActivityDisplay(displayId);
- if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) {
- // Can't launch home on display that doesn't support system decorations.
- return false;
- }
-
- final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
- && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE
- && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
- if (!supportMultipleInstance) {
- // Can't launch home on other displays if it requested to be single instance. Also we
- // don't allow home applications that target before Q to have multiple home activity
- // instances because they may not be expected to have multiple home scenario and
- // haven't explicitly request for single instance.
- return false;
- }
-
- return true;
- }
-
- TaskRecord anyTaskForIdLocked(int id) {
- return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
- }
-
- TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode) {
- return anyTaskForIdLocked(id, matchMode, null, !ON_TOP);
- }
-
- /**
- * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
- * @param id Id of the task we would like returned.
- * @param matchMode The mode to match the given task id in.
- * @param aOptions The activity options to use for restoration. Can be null.
- * @param onTop If the stack for the task should be the topmost on the display.
- */
- TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode,
- @Nullable ActivityOptions aOptions, boolean onTop) {
- // If options are set, ensure that we are attempting to actually restore a task
- if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
- throw new IllegalArgumentException("Should not specify activity options for non-restore"
- + " lookup");
- }
-
- int numDisplays = mActivityDisplays.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final TaskRecord task = stack.taskForIdLocked(id);
- if (task == null) {
- continue;
- }
- if (aOptions != null) {
- // Resolve the stack the task should be placed in now based on options
- // and reparent if needed.
- final ActivityStack launchStack = getLaunchStack(null, aOptions, task, onTop);
- if (launchStack != null && stack != launchStack) {
- final int reparentMode = onTop
- ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE;
- task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME,
- "anyTaskForIdLocked");
- }
- }
- return task;
- }
- }
-
- // If we are matching stack tasks only, return now
- if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
- return null;
- }
-
- // Otherwise, check the recent tasks and return if we find it there and we are not restoring
- // the task from recents
- if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- final TaskRecord task = mRecentTasks.getTask(id);
-
- if (task == null) {
- if (DEBUG_RECENTS) {
- Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
- }
-
- return null;
- }
-
- if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
- return task;
- }
-
- // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- if (!restoreRecentTaskLocked(task, aOptions, onTop)) {
- if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
- "Couldn't restore task id=" + id + " found in recents");
- return null;
- }
- if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
- return task;
- }
-
- ActivityRecord isInAnyStackLocked(IBinder token) {
- int numDisplays = mActivityDisplays.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.isInStackLocked(token);
- if (r != null) {
- return r;
- }
- }
- }
- return null;
- }
-
- /**
- * Detects whether we should show a lock screen in front of this task for a locked user.
- * <p>
- * We'll do this if either of the following holds:
- * <ul>
- * <li>The top activity explicitly belongs to {@param userId}.</li>
- * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
- * </ul>
- *
- * @return {@code true} if the top activity looks like it belongs to {@param userId}.
- */
- private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) {
- // To handle the case that work app is in the task but just is not the top one.
- final ActivityRecord activityRecord = task.getTopActivity();
- final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
-
- return (activityRecord != null && activityRecord.userId == userId)
- || (resultTo != null && resultTo.userId == userId);
- }
-
- /**
- * Find all visible task stacks containing {@param userId} and intercept them with an activity
- * to block out the contents and possibly start a credential-confirming intent.
- *
- * @param userId user handle for the locked managed profile.
- */
- void lockAllProfileTasks(@UserIdInt int userId) {
- mWindowManager.deferSurfaceLayout();
- try {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final List<TaskRecord> tasks = stack.getAllTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
- final TaskRecord task = tasks.get(taskNdx);
-
- // Check the task for a top activity belonging to userId, or returning a
- // result to an activity belonging to userId. Example case: a document
- // picker for personal files, opened by a work app, should still get locked.
- if (taskTopActivityIsUser(task, userId)) {
- mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
- task.taskId, userId);
- }
- }
- }
- }
- } finally {
- mWindowManager.continueSurfaceLayout();
- }
- }
-
void setNextTaskIdForUserLocked(int taskId, int userId) {
final int currentTaskId = mCurTaskIdForUser.get(userId, -1);
if (taskId > currentTaskId) {
@@ -1014,7 +514,7 @@
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
while (mRecentTasks.containsTaskId(candidateTaskId, userId)
- || anyTaskForIdLocked(
+ || mRootActivityContainer.anyTaskForId(
candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
if (candidateTaskId == currentTaskId) {
@@ -1029,142 +529,6 @@
return candidateTaskId;
}
- boolean attachApplicationLocked(WindowProcessController app) throws RemoteException {
- final String processName = app.mName;
- boolean didSomething = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- final ActivityStack stack = display.getFocusedStack();
- if (stack != null) {
- stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
- final ActivityRecord top = stack.topRunningActivityLocked();
- final int size = mTmpActivityList.size();
- for (int i = 0; i < size; i++) {
- final ActivityRecord activity = mTmpActivityList.get(i);
- if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
- && processName.equals(activity.processName)) {
- try {
- if (realStartActivityLocked(activity, app,
- top == activity /* andResume */, true /* checkConfig */)) {
- didSomething = true;
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception in new application when starting activity "
- + top.intent.getComponent().flattenToShortString(), e);
- throw e;
- }
- }
- }
- }
- }
- if (!didSomething) {
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- }
- return didSomething;
- }
-
- boolean allResumedActivitiesIdle() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- // TODO(b/117135575): Check resumed activities on all visible stacks.
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- if (display.isSleeping()) {
- // No resumed activities while display is sleeping.
- continue;
- }
-
- // If the focused stack is not null or not empty, there should have some activities
- // resuming or resumed. Make sure these activities are idle.
- final ActivityStack stack = display.getFocusedStack();
- if (stack == null || stack.numActivities() == 0) {
- continue;
- }
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity == null || !resumedActivity.idle) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
- + stack.mStackId + " " + resumedActivity + " not idle");
- }
- return false;
- }
- }
- // Send launch end powerhint when idle
- sendPowerHintForLaunchEndIfNeeded();
- return true;
- }
-
- private boolean allResumedActivitiesVisible() {
- boolean foundResumed = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.getResumedActivity();
- if (r != null) {
- if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
- return false;
- }
- foundResumed = true;
- }
- }
- }
- return foundResumed;
- }
-
- private void executeAppTransitionForAllDisplay() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- display.getWindowContainerController().executeAppTransition();
- }
- }
-
- /**
- * Pause all activities in either all of the stacks or just the back stacks.
- * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
- * @param resuming The resuming activity.
- * @param dontWait The resuming activity isn't going to wait for all activities to be paused
- * before resuming.
- * @return true if any activity was paused as a result of this call.
- */
- boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
- boolean someActivityPaused = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- someActivityPaused |= mActivityDisplays.get(displayNdx)
- .pauseBackStacks(userLeaving, resuming, dontWait);
- }
- return someActivityPaused;
- }
-
- boolean allPausedActivitiesComplete() {
- boolean pausing = true;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.mPausingActivity;
- if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
- if (DEBUG_STATES) {
- Slog.d(TAG_STATES,
- "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
- pausing = false;
- } else {
- return false;
- }
- }
- }
- }
- return pausing;
- }
-
- void cancelInitializingActivities() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.cancelInitializingActivities();
- }
- }
- }
-
void waitActivityVisible(ComponentName name, WaitResult result, long startTimeMs) {
final WaitInfo waitInfo = new WaitInfo(name, result, startTimeMs);
mWaitingForActivityVisible.add(waitInfo);
@@ -1255,24 +619,6 @@
}
}
- ActivityRecord topRunningActivityLocked() {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity();
- if (topActivity != null) {
- return topActivity;
- }
- }
- return null;
- }
-
- @VisibleForTesting
- void getRunningTasks(int maxNum, List<RunningTaskInfo> list,
- @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode,
- int callingUid, boolean allowed) {
- mRunningTasks.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode,
- mActivityDisplays, callingUid, allowed);
- }
-
ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
ProfilerInfo profilerInfo) {
final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
@@ -1352,10 +698,10 @@
return resolveActivity(intent, rInfo, startFlags, profilerInfo);
}
- private boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
+ boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
- if (!allPausedActivitiesComplete()) {
+ if (!mRootActivityContainer.allPausedActivitiesComplete()) {
// While there are activities pausing we skipping starting any new activities until
// pauses are complete. NOTE: that we also do this for activities that are starting in
// the paused state because they will first be resumed then paused on the client side.
@@ -1390,7 +736,7 @@
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
- ensureVisibilityAndConfig(r, r.getDisplayId(),
+ mRootActivityContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
@@ -1560,7 +906,7 @@
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
- if (isTopDisplayFocusedStack(stack)) {
+ if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
mService.getActivityStartController().startSetupActivity();
}
@@ -1573,47 +919,6 @@
return true;
}
- /**
- * Ensure all activities visibility, update orientation and configuration.
- *
- * @param starting The currently starting activity or {@code null} if there is none.
- * @param displayId The id of the display where operation is executed.
- * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
- * {@code true} if config changed.
- * @param deferResume Whether to defer resume while updating config.
- * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
- * because of configuration update.
- */
- boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
- boolean markFrozenIfConfigChanged, boolean deferResume) {
- // First ensure visibility without updating the config just yet. We need this to know what
- // activities are affecting configuration now.
- // Passing null here for 'starting' param value, so that visibility of actual starting
- // activity will be properly updated.
- ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */, false /* notifyClients */);
-
- if (displayId == INVALID_DISPLAY) {
- // The caller didn't provide a valid display id, skip updating config.
- return true;
- }
-
- // Force-update the orientation from the WindowManager, since we need the true configuration
- // to send to the client now.
- final Configuration config = mWindowManager.updateOrientationFromAppTokens(
- getDisplayOverrideConfiguration(displayId),
- starting != null && starting.mayFreezeScreenLocked(starting.app)
- ? starting.appToken : null,
- displayId, true /* forceUpdate */);
- if (starting != null && markFrozenIfConfigChanged && config != null) {
- starting.frozenBeforeDestroy = true;
- }
-
- // Update the configuration of the activities on the display.
- return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
- displayId);
- }
-
private void logIfTransactionTooLarge(Intent intent, Bundle icicle) {
int extrasSize = 0;
if (intent != null) {
@@ -1669,47 +974,6 @@
mService.mH.sendMessage(msg);
}
- void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
- boolean sendHint = forceSend;
-
- if (!sendHint) {
- // Send power hint if we don't know what we're launching yet
- sendHint = targetActivity == null || targetActivity.app == null;
- }
-
- if (!sendHint) { // targetActivity != null
- // Send power hint when the activity's process is different than the current resumed
- // activity on all displays, or if there are no resumed activities in the system.
- boolean noResumedActivities = true;
- boolean allFocusedProcessesDiffer = true;
- for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
- final ActivityRecord resumedActivity = activityDisplay.getResumedActivity();
- final WindowProcessController resumedActivityProcess =
- resumedActivity == null ? null : resumedActivity.app;
-
- noResumedActivities &= resumedActivityProcess == null;
- if (resumedActivityProcess != null) {
- allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
- }
- }
- sendHint = noResumedActivities || allFocusedProcessesDiffer;
- }
-
- if (sendHint && mService.mPowerManagerInternal != null) {
- mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1);
- mPowerHintSent = true;
- }
- }
-
- void sendPowerHintForLaunchEndIfNeeded() {
- // Trigger launch power hint if activity is launched
- if (mPowerHintSent && mService.mPowerManagerInternal != null) {
- mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0);
- mPowerHintSent = false;
- }
- }
-
boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho,
int requestCode, int callingPid, int callingUid, String callingPackage,
boolean ignoreTargetSecurity, boolean launchingInTask,
@@ -1788,7 +1052,8 @@
return true;
}
- final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(launchDisplayId);
+ final ActivityDisplay activityDisplay =
+ mRootActivityContainer.getActivityDisplayOrCreate(launchDisplayId);
if (activityDisplay == null || activityDisplay.isRemoved()) {
Slog.w(TAG, "Launch on display check: display not found");
return false;
@@ -1850,21 +1115,6 @@
return false;
}
- /** Update lists of UIDs that are present on displays and have access to them. */
- void updateUIDsPresentOnDisplay() {
- mDisplayAccessUIDs.clear();
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
- // Only bother calculating the whitelist for private displays
- if (activityDisplay.isPrivate()) {
- mDisplayAccessUIDs.append(
- activityDisplay.mDisplayId, activityDisplay.getPresentUIDs());
- }
- }
- // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
- mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
- }
-
UserInfo getUserInfo(int userId) {
final long identity = Binder.clearCallingIdentity();
try {
@@ -2016,7 +1266,8 @@
// Check if able to finish booting when device is booting and all resumed activities
// are idle.
- if ((mService.isBooting() && allResumedActivitiesIdle()) || fromTimeout) {
+ if ((mService.isBooting() && mRootActivityContainer.allResumedActivitiesIdle())
+ || fromTimeout) {
booting = checkFinishBootingLocked();
}
@@ -2025,7 +1276,7 @@
r.mRelaunchReason = RELAUNCH_REASON_NONE;
}
- if (allResumedActivitiesIdle()) {
+ if (mRootActivityContainer.allResumedActivitiesIdle()) {
if (r != null) {
mService.scheduleAppGcsLocked();
}
@@ -2038,7 +1289,7 @@
}
mLaunchingActivity.release();
}
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
// Atomically retrieve all of the other things to do.
@@ -2094,186 +1345,13 @@
//mWindowManager.dump();
if (activityRemoved) {
- resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return r;
}
- boolean handleAppDiedLocked(WindowProcessController app) {
- boolean hasVisibleActivities = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- hasVisibleActivities |= stack.handleAppDiedLocked(app);
- }
- }
- return hasVisibleActivities;
- }
-
- void closeSystemDialogsLocked() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.closeSystemDialogsLocked();
- }
- }
- }
-
- void removeUserLocked(int userId) {
- mUserStackInFront.delete(userId);
- }
-
- /**
- * Update the last used stack id for non-current user (current user's last
- * used stack is the focused stack)
- */
- void updateUserStackLocked(int userId, ActivityStack stack) {
- if (userId != mCurrentUser) {
- mUserStackInFront.put(userId, stack != null ? stack.getStackId()
- : getDefaultDisplay().getHomeStack().mStackId);
- }
- }
-
- /**
- * @return true if some activity was finished (or would have finished if doit were true).
- */
- boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
- boolean doit, boolean evenPersistent, int userId) {
- boolean didSomething = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (stack.finishDisabledPackageActivitiesLocked(
- packageName, filterByClasses, doit, evenPersistent, userId)) {
- didSomething = true;
- }
- }
- }
- return didSomething;
- }
-
- void updatePreviousProcessLocked(ActivityRecord r) {
- // Now that this process has stopped, we may want to consider
- // it to be the previous app to try to keep around in case
- // the user wants to return to it.
-
- // First, found out what is currently the foreground app, so that
- // we don't blow away the previous app if this activity is being
- // hosted by the process that is actually still the foreground.
- WindowProcessController fgApp = null;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (isTopDisplayFocusedStack(stack)) {
- final ActivityRecord resumedActivity = stack.getResumedActivity();
- if (resumedActivity != null) {
- fgApp = resumedActivity.app;
- } else if (stack.mPausingActivity != null) {
- fgApp = stack.mPausingActivity.app;
- }
- break;
- }
- }
- }
-
- // Now set this one as the previous process, only if that really
- // makes sense to.
- if (r.hasProcess() && fgApp != null && r.app != fgApp
- && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
- && r.app != mService.mHomeProcess) {
- mService.mPreviousProcess = r.app;
- mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
- }
- }
-
- boolean resumeFocusedStacksTopActivitiesLocked() {
- return resumeFocusedStacksTopActivitiesLocked(null, null, null);
- }
-
- boolean resumeFocusedStacksTopActivitiesLocked(
- ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
-
- if (!readyToResume()) {
- return false;
- }
-
- if (targetStack != null && (targetStack.isTopStackOnDisplay()
- || getTopDisplayFocusedStack() == targetStack)) {
- return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
- }
-
- // Resume all top activities in focused stacks on all displays.
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- final ActivityStack focusedStack = display.getFocusedStack();
- if (focusedStack == null) {
- continue;
- }
- final ActivityRecord r = focusedStack.topRunningActivityLocked();
- if (r == null || !r.isState(RESUMED)) {
- focusedStack.resumeTopActivityUncheckedLocked(null, null);
- } else if (r.isState(RESUMED)) {
- // Kick off any lingering app transitions form the MoveTaskToFront operation.
- focusedStack.executeAppTransition(targetOptions);
- }
- }
-
- return false;
- }
-
- void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.updateActivityApplicationInfoLocked(aInfo);
- }
- }
- }
-
- /**
- * Finish the topmost activities in all stacks that belong to the crashed app.
- * @param app The app that crashed.
- * @param reason Reason to perform this action.
- * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
- */
- int finishTopCrashedActivitiesLocked(WindowProcessController app, String reason) {
- TaskRecord finishedTask = null;
- ActivityStack focusedStack = getTopDisplayFocusedStack();
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- // It is possible that request to finish activity might also remove its task and stack,
- // so we need to be careful with indexes in the loop and check child count every time.
- for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason);
- if (stack == focusedStack || finishedTask == null) {
- finishedTask = t;
- }
- }
- }
- return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID;
- }
-
- void finishVoiceTask(IVoiceInteractionSession session) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- final int numStacks = display.getChildCount();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.finishVoiceTask(session);
- }
- }
- }
-
- /**
- * This doesn't just find a task, it also moves the task to front.
- */
+ /** This doesn't just find a task, it also moves the task to front. */
void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason,
boolean forceNonResizeable) {
ActivityStack currentStack = task.getStack();
@@ -2293,7 +1371,8 @@
final Rect bounds = options.getLaunchBounds();
task.updateOverrideConfiguration(bounds);
- ActivityStack stack = getLaunchStack(null, options, task, ON_TOP);
+ ActivityStack stack =
+ mRootActivityContainer.getLaunchStack(null, options, task, ON_TOP);
if (stack != currentStack) {
moveHomeStackToFrontIfNeeded(flags, stack.getDisplay(), reason);
@@ -2305,7 +1384,7 @@
// still need moveTaskToFrontLocked() below for any transition settings.
}
if (stack.resizeStackWithLaunchBounds()) {
- resizeStackLocked(stack, bounds, null /* tempTaskBounds */,
+ mRootActivityContainer.resizeStack(stack, bounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
} else {
@@ -2358,388 +1437,22 @@
return mLaunchParamsController;
}
- protected <T extends ActivityStack> T getStack(int stackId) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final T stack = mActivityDisplays.get(i).getStack(stackId);
- if (stack != null) {
- return stack;
- }
- }
- return null;
+ private void deferUpdateRecentsHomeStackBounds() {
+ mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_RECENTS);
+ mRootActivityContainer.deferUpdateBounds(ACTIVITY_TYPE_HOME);
}
- /** @see ActivityDisplay#getStack(int, int) */
- private <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
- int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
- @Nullable TaskRecord task) {
- // Preference is given to the activity type for the activity then the task since the type
- // once set shouldn't change.
- int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
- if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
- activityType = task.getActivityType();
- }
- if (activityType != ACTIVITY_TYPE_UNDEFINED) {
- return activityType;
- }
- if (options != null) {
- activityType = options.getLaunchActivityType();
- }
- return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
- }
-
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
- @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
- return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */);
- }
-
- /**
- * Returns the right stack to use for launching factoring in all the input parameters.
- *
- * @param r The activity we are trying to launch. Can be null.
- * @param options The activity options used to the launch. Can be null.
- * @param candidateTask The possible task the activity might be launched in. Can be null.
- * @params launchParams The resolved launch params to use.
- *
- * @return The stack to use for the launch or INVALID_STACK_ID.
- */
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
- @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
- @Nullable LaunchParamsController.LaunchParams launchParams) {
- int taskId = INVALID_TASK_ID;
- int displayId = INVALID_DISPLAY;
- //Rect bounds = null;
-
- // We give preference to the launch preference in activity options.
- if (options != null) {
- taskId = options.getLaunchTaskId();
- displayId = options.getLaunchDisplayId();
- }
-
- // First preference for stack goes to the task Id set in the activity options. Use the stack
- // associated with that if possible.
- if (taskId != INVALID_TASK_ID) {
- // Temporarily set the task id to invalid in case in re-entry.
- options.setLaunchTaskId(INVALID_TASK_ID);
- final TaskRecord task = anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
- options.setLaunchTaskId(taskId);
- if (task != null) {
- return task.getStack();
- }
- }
-
- final int activityType = resolveActivityType(r, options, candidateTask);
- T stack;
-
- // Next preference for stack goes to the display Id set the candidate display.
- if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
- displayId = launchParams.mPreferredDisplayId;
- }
- if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
- if (r != null) {
- stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
- launchParams);
- if (stack != null) {
- return stack;
- }
- }
- final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
- if (display != null) {
- stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
- if (stack != null) {
- return stack;
- }
- }
- }
-
- // Give preference to the stack and display of the input task and activity if they match the
- // mode we want to launch into.
- stack = null;
- ActivityDisplay display = null;
- if (candidateTask != null) {
- stack = candidateTask.getStack();
- }
- if (stack == null && r != null) {
- stack = r.getStack();
- }
- if (stack != null) {
- display = stack.getDisplay();
- if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
- int windowingMode = launchParams != null ? launchParams.mWindowingMode
- : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
- if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- windowingMode = display.resolveWindowingMode(r, options, candidateTask,
- activityType);
- }
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
- if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
- && display.getSplitScreenPrimaryStack() == stack
- && candidateTask == stack.topTask()) {
- // This is a special case when we try to launch an activity that is currently on
- // top of split-screen primary stack, but is targeting split-screen secondary.
- // In this case we don't want to move it to another stack.
- // TODO(b/78788972): Remove after differentiating between preferred and required
- // launch options.
- return stack;
- }
- }
- }
-
- if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
- display = getDefaultDisplay();
- }
-
- return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
- }
-
- /** @return true if activity record is null or can be launched on provided display. */
- private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
- if (r == null) {
- return true;
- }
- return r.canBeLaunchedOnDisplay(displayId);
- }
-
- /**
- * Get a topmost stack on the display, that is a valid launch stack for specified activity.
- * If there is no such stack, new dynamic stack can be created.
- * @param displayId Target display.
- * @param r Activity that should be launched there.
- * @param candidateTask The possible task the activity might be put in.
- * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
- */
- private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
- @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options,
- @Nullable LaunchParamsController.LaunchParams launchParams) {
- final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
- if (activityDisplay == null) {
- throw new IllegalArgumentException(
- "Display with displayId=" + displayId + " not found.");
- }
-
- if (!r.canBeLaunchedOnDisplay(displayId)) {
- return null;
- }
-
- // If {@code r} is already in target display and its task is the same as the candidate task,
- // the intention should be getting a launch stack for the reusable activity, so we can use
- // the existing stack.
- if (r.getDisplayId() == displayId && r.getTask() == candidateTask) {
- return candidateTask.getStack();
- }
-
- // Return the topmost valid stack on the display.
- for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
- final ActivityStack stack = activityDisplay.getChildAt(i);
- if (isValidLaunchStack(stack, displayId, r)) {
- return stack;
- }
- }
-
- // If there is no valid stack on the external display - check if new dynamic stack will do.
- if (displayId != DEFAULT_DISPLAY) {
- final int windowingMode;
- if (launchParams != null) {
- // When launch params is not null, we always defer to its windowing mode. Sometimes
- // it could be unspecified, which indicates it should inherit windowing mode from
- // display.
- windowingMode = launchParams.mWindowingMode;
- } else {
- windowingMode = options != null ? options.getLaunchWindowingMode()
- : r.getWindowingMode();
- }
- final int activityType =
- options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
- ? options.getLaunchActivityType() : r.getActivityType();
- return activityDisplay.createStack(windowingMode, activityType, true /*onTop*/);
- }
-
- Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId);
- return null;
- }
-
- ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
- @Nullable ActivityOptions options,
- @Nullable LaunchParamsController.LaunchParams launchParams) {
- return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
- launchParams);
- }
-
- // TODO: Can probably be consolidated into getLaunchStack()...
- private boolean isValidLaunchStack(ActivityStack stack, int displayId, ActivityRecord r) {
- switch (stack.getActivityType()) {
- case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
- case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
- case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
- }
- // There is a 1-to-1 relationship between stack and task when not in
- // primary split-windowing mode.
- if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- return false;
- } else {
- return r.supportsSplitScreenWindowingMode();
- }
- }
-
- /**
- * Get next focusable stack in the system. This will search through the stack on the same
- * display as the current focused stack, looking for a focusable and visible stack, different
- * from the target stack. If no valid candidates will be found, it will then go through all
- * displays and stacks in last-focused order.
- *
- * @param currentFocus The stack that previously had focus.
- * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
- * candidate.
- * @return Next focusable {@link ActivityStack}, {@code null} if not found.
- */
- ActivityStack getNextFocusableStackLocked(@NonNull ActivityStack currentFocus,
- boolean ignoreCurrent) {
- // First look for next focusable stack on the same display
- final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
- final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
- currentFocus, ignoreCurrent);
- if (preferredFocusableStack != null) {
- return preferredFocusableStack;
- }
- if (preferredDisplay.supportsSystemDecorations()) {
- // Stop looking for focusable stack on other displays because the preferred display
- // supports system decorations. Home activity would be launched on the same display if
- // no focusable stack found.
- return null;
- }
-
- // Now look through all displays
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- if (display == preferredDisplay) {
- // We've already checked this one
- continue;
- }
- final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
- ignoreCurrent);
- if (nextFocusableStack != null) {
- return nextFocusableStack;
- }
- }
-
- return null;
- }
-
- /**
- * Get next valid stack for launching provided activity in the system. This will search across
- * displays and stacks in last-focused order for a focusable and visible stack, except those
- * that are on a currently focused display.
- *
- * @param r The activity that is being launched.
- * @param currentFocus The display that previously had focus and thus needs to be ignored when
- * searching for the next candidate.
- * @return Next valid {@link ActivityStack}, null if not found.
- */
- ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- if (display.mDisplayId == currentFocus) {
- continue;
- }
- final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
- null /* options */, null /* launchParams */);
- if (stack != null) {
- return stack;
- }
- }
- return null;
- }
-
- ActivityRecord getDefaultDisplayHomeActivity() {
- return getDefaultDisplayHomeActivityForUser(mCurrentUser);
- }
-
- ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
- return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
- }
-
- void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
- Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode,
- boolean deferResume) {
-
- if (stack.inSplitScreenPrimaryWindowingMode()) {
- resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
- preserveWindows, deferResume);
- return;
- }
-
- final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack();
- if (!allowResizeInDockedMode
- && !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) {
- // If the docked stack exists, don't resize non-floating stacks independently of the
- // size computed from the docked stack size (otherwise they will be out of sync)
- return;
- }
-
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId);
- mWindowManager.deferSurfaceLayout();
- try {
- if (stack.affectedBySplitScreenResize()) {
- if (bounds == null && stack.inSplitScreenWindowingMode()) {
- // null bounds = fullscreen windowing mode...at least for now.
- stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- } else if (splitScreenActive) {
- // If we are in split-screen mode and this stack support split-screen, then
- // it should be split-screen secondary mode. i.e. adjacent to the docked stack.
- stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- }
- }
- stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds);
- if (!deferResume) {
- stack.ensureVisibleActivitiesConfigurationLocked(
- stack.topRunningActivityLocked(), preserveWindows);
- }
- } finally {
- mWindowManager.continueSurfaceLayout();
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
- }
- }
-
- void deferUpdateRecentsHomeStackBounds() {
- deferUpdateBounds(ACTIVITY_TYPE_RECENTS);
- deferUpdateBounds(ACTIVITY_TYPE_HOME);
- }
-
- void deferUpdateBounds(int activityType) {
- final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
- if (stack != null) {
- stack.deferUpdateBounds();
- }
- }
-
- void continueUpdateRecentsHomeStackBounds() {
- continueUpdateBounds(ACTIVITY_TYPE_RECENTS);
- continueUpdateBounds(ACTIVITY_TYPE_HOME);
- }
-
- void continueUpdateBounds(int activityType) {
- final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
- if (stack != null) {
- stack.continueUpdateBounds();
- }
+ private void continueUpdateRecentsHomeStackBounds() {
+ mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_RECENTS);
+ mRootActivityContainer.continueUpdateBounds(ACTIVITY_TYPE_HOME);
}
void notifyAppTransitionDone() {
continueUpdateRecentsHomeStackBounds();
for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) {
final int taskId = mResizingTasksDuringAnimation.valueAt(i);
- final TaskRecord task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY);
+ final TaskRecord task =
+ mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_ONLY);
if (task != null) {
task.setTaskDockedResizing(false);
}
@@ -2758,7 +1471,8 @@
try {
final int windowingMode = fromStack.getWindowingMode();
final boolean inPinnedWindowingMode = windowingMode == WINDOWING_MODE_PINNED;
- final ActivityDisplay toDisplay = getActivityDisplay(toDisplayId);
+ final ActivityDisplay toDisplay =
+ mRootActivityContainer.getActivityDisplay(toDisplayId);
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// Tell the display we are exiting split-screen mode.
@@ -2815,8 +1529,8 @@
}
}
- ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
- resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
} finally {
mAllowDockedStackResize = true;
mWindowManager.continueSurfaceLayout();
@@ -2862,7 +1576,7 @@
false /* deferResume */);
}
- private void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
+ void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
boolean preserveWindows, boolean deferResume) {
@@ -2871,7 +1585,8 @@
return;
}
- final ActivityStack stack = getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack stack =
+ mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "resizeDockedStackLocked: docked stack not found");
return;
@@ -2910,7 +1625,7 @@
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final ActivityDisplay display = getDefaultDisplay();
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
final Rect otherTaskRect = new Rect();
for (int i = display.getChildCount() - 1; i >= 0; --i) {
final ActivityStack current = display.getChildAt(i);
@@ -2930,7 +1645,8 @@
tempRect /* outStackBounds */,
otherTaskRect /* outTempTaskBounds */);
- resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null,
+ mRootActivityContainer.resizeStack(current,
+ !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -2948,7 +1664,8 @@
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
// TODO(multi-display): Pinned stack display should be passed in.
- final PinnedActivityStack stack = getDefaultDisplay().getPinnedStack();
+ final PinnedActivityStack stack =
+ mRootActivityContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
@@ -3029,22 +1746,6 @@
}
/**
- * Removes stacks in the input windowing modes from the system if they are of activity type
- * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
- */
- void removeStacksInWindowingModes(int... windowingModes) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- mActivityDisplays.get(i).removeStacksInWindowingModes(windowingModes);
- }
- }
-
- void removeStacksWithActivityTypes(int... activityTypes) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- mActivityDisplays.get(i).removeStacksWithActivityTypes(activityTypes);
- }
- }
-
- /**
* See {@link #removeTaskByIdLocked(int, boolean, boolean, boolean)}
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
@@ -3065,7 +1766,8 @@
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
boolean pauseImmediately, String reason) {
- final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
+ final TaskRecord tr =
+ mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
tr.removeTaskActivitiesLocked(pauseImmediately, reason);
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
@@ -3154,7 +1856,8 @@
* @return true if the task has been restored successfully.
*/
boolean restoreRecentTaskLocked(TaskRecord task, ActivityOptions aOptions, boolean onTop) {
- final ActivityStack stack = getLaunchStack(null, aOptions, task, onTop);
+ final ActivityStack stack =
+ mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop);
final ActivityStack currentStack = task.getStack();
if (currentStack != null) {
// Task has already been restored once. See if we need to do anything more
@@ -3174,7 +1877,7 @@
"Added restored task=" + task + " to stack=" + stack);
final ArrayList<ActivityRecord> activities = task.mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- activities.get(activityNdx).createWindowContainer();
+ activities.get(activityNdx).createAppWindowToken();
}
return true;
}
@@ -3196,39 +1899,6 @@
}
/**
- * Move stack with all its existing content to specified display.
- * @param stackId Id of stack to move.
- * @param displayId Id of display to move stack to.
- * @param onTop Indicates whether container should be place on top or on bottom.
- */
- void moveStackToDisplayLocked(int stackId, int displayId, boolean onTop) {
- final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
- if (activityDisplay == null) {
- throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId="
- + displayId);
- }
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId="
- + stackId);
- }
-
- final ActivityDisplay currentDisplay = stack.getDisplay();
- if (currentDisplay == null) {
- throw new IllegalStateException("moveStackToDisplayLocked: Stack with stack=" + stack
- + " is not attached to any display.");
- }
-
- if (currentDisplay.mDisplayId == displayId) {
- throw new IllegalArgumentException("Trying to move stack=" + stack
- + " to its current displayId=" + displayId);
- }
-
- stack.reparent(activityDisplay, onTop, false /* displayRemoved */);
- // TODO(multi-display): resize stacks properly if moved from split-screen.
- }
-
- /**
* Returns the reparent target stack, creating the stack if necessary. This call also enforces
* the various checks on tasks that are going to be reparented from one stack to another.
*/
@@ -3280,159 +1950,6 @@
return stack;
}
- boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect destBounds) {
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- throw new IllegalArgumentException(
- "moveTopStackActivityToPinnedStackLocked: Unknown stackId=" + stackId);
- }
-
- final ActivityRecord r = stack.topRunningActivityLocked();
- if (r == null) {
- Slog.w(TAG, "moveTopStackActivityToPinnedStackLocked: No top running activity"
- + " in stack=" + stack);
- return false;
- }
-
- if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
- Slog.w(TAG,
- "moveTopStackActivityToPinnedStackLocked: Picture-In-Picture not supported for "
- + " r=" + r);
- return false;
- }
-
- moveActivityToPinnedStackLocked(r, null /* sourceBounds */, 0f /* aspectRatio */,
- "moveTopActivityToPinnedStack");
- return true;
- }
-
- void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
- String reason) {
-
- mWindowManager.deferSurfaceLayout();
-
- final ActivityDisplay display = r.getStack().getDisplay();
- PinnedActivityStack stack = display.getPinnedStack();
-
- // This will clear the pinned stack by moving an existing task to the full screen stack,
- // ensuring only one task is present.
- if (stack != null) {
- moveTasksToFullscreenStackLocked(stack, !ON_TOP);
- }
-
- // Need to make sure the pinned stack exist so we can resize it below...
- stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP);
-
- // Calculate the target bounds here before the task is reparented back into pinned windowing
- // mode (which will reset the saved bounds)
- final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio);
-
- try {
- final TaskRecord task = r.getTask();
- // Resize the pinned stack to match the current size of the task the activity we are
- // going to be moving is currently contained in. We do this to have the right starting
- // animation bounds for the pinned stack to the desired bounds the caller wants.
- resizeStackLocked(stack, task.getOverrideBounds(), null /* tempTaskBounds */,
- null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
- true /* allowResizeInDockedMode */, !DEFER_RESUME);
-
- if (task.mActivities.size() == 1) {
- // Defer resume until below, and do not schedule PiP changes until we animate below
- task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME,
- false /* schedulePictureInPictureModeChange */, reason);
- } else {
- // There are multiple activities in the task and moving the top activity should
- // reveal/leave the other activities in their original task.
-
- // Currently, we don't support reparenting activities across tasks in two different
- // stacks, so instead, just create a new task in the same stack, reparent the
- // activity into that task, and then reparent the whole task to the new stack. This
- // ensures that all the necessary work to migrate states in the old and new stacks
- // is also done.
- final TaskRecord newTask = task.getStack().createTaskRecord(
- getNextTaskIdForUserLocked(r.userId), r.info, r.intent, null, null, true);
- r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
-
- // Defer resume until below, and do not schedule PiP changes until we animate below
- newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
- }
-
- // Reset the state that indicates it can enter PiP while pausing after we've moved it
- // to the pinned stack
- r.supportsEnterPipOnTaskSwitch = false;
- } finally {
- mWindowManager.continueSurfaceLayout();
- }
-
- stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
- true /* fromFullscreen */);
-
- // Update the visibility of all activities after the they have been reparented to the new
- // stack. This MUST run after the animation above is scheduled to ensure that the windows
- // drawn signal is scheduled after the bounds animation start call on the bounds animator
- // thread.
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- resumeFocusedStacksTopActivitiesLocked();
-
- mService.getTaskChangeNotificationController().notifyActivityPinned(r);
- }
-
- ActivityRecord findTaskLocked(ActivityRecord r, int preferredDisplayId) {
- if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
- mTmpFindTaskResult.clear();
-
- // Looking up task on preferred display first
- final ActivityDisplay preferredDisplay = getActivityDisplay(preferredDisplayId);
- if (preferredDisplay != null) {
- preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
- if (mTmpFindTaskResult.mIdealMatch) {
- return mTmpFindTaskResult.mRecord;
- }
- }
-
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- if (display.mDisplayId == preferredDisplayId) {
- continue;
- }
-
- display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
- if (mTmpFindTaskResult.mIdealMatch) {
- return mTmpFindTaskResult.mRecord;
- }
- }
-
- if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
- return mTmpFindTaskResult.mRecord;
- }
-
- ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
- boolean compareIntentFilters) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord ar = stack.findActivityLocked(
- intent, info, compareIntentFilters);
- if (ar != null) {
- return ar;
- }
- }
- }
- return null;
- }
-
- boolean hasAwakeDisplay() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- if (!display.shouldSleep()) {
- return true;
- }
- }
- return false;
- }
-
void goingToSleepLocked() {
scheduleSleepTimeout();
if (!mGoingToSleep.isHeld()) {
@@ -3446,24 +1963,19 @@
}
}
- applySleepTokensLocked(false /* applyToStacks */);
+ mRootActivityContainer.applySleepTokens(false /* applyToStacks */);
checkReadyForSleepLocked(true /* allowDelay */);
}
- void prepareForShutdownLocked() {
- for (int i = 0; i < mActivityDisplays.size(); i++) {
- createSleepTokenLocked("shutdown", mActivityDisplays.get(i).mDisplayId);
- }
- }
-
boolean shutdownLocked(int timeout) {
goingToSleepLocked();
boolean timedout = false;
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
- if (!putStacksToSleepLocked(true /* allowDelay */, true /* shuttingDown */)) {
+ if (!mRootActivityContainer.putStacksToSleep(
+ true /* allowDelay */, true /* shuttingDown */)) {
long timeRemaining = endTime - System.currentTimeMillis();
if (timeRemaining > 0) {
try {
@@ -3493,51 +2005,6 @@
}
}
- void applySleepTokensLocked(boolean applyToStacks) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- // Set the sleeping state of the display.
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- final boolean displayShouldSleep = display.shouldSleep();
- if (displayShouldSleep == display.isSleeping()) {
- continue;
- }
- display.setIsSleeping(displayShouldSleep);
-
- if (!applyToStacks) {
- continue;
- }
-
- // Set the sleeping state of the stacks on the display.
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (displayShouldSleep) {
- stack.goToSleepIfPossible(false /* shuttingDown */);
- } else {
- stack.awakeFromSleepingLocked();
- if (stack.isFocusedStackOnDisplay() && !getKeyguardController()
- .isKeyguardOrAodShowing(display.mDisplayId)) {
- // If the keyguard is unlocked - resume immediately.
- // It is possible that the display will not be awake at the time we
- // process the keyguard going away, which can happen before the sleep token
- // is released. As a result, it is important we resume the activity here.
- resumeFocusedStacksTopActivitiesLocked();
- }
- }
- }
-
- if (displayShouldSleep || mGoingToSleepActivities.isEmpty()) {
- continue;
- }
- // The display is awake now, so clean up the going to sleep list.
- for (Iterator<ActivityRecord> it = mGoingToSleepActivities.iterator(); it.hasNext(); ) {
- final ActivityRecord r = it.next();
- if (r.getDisplayId() == display.mDisplayId) {
- it.remove();
- }
- }
- }
- }
-
void activitySleptLocked(ActivityRecord r) {
mGoingToSleepActivities.remove(r);
final ActivityStack s = r.getStack();
@@ -3554,12 +2021,13 @@
return;
}
- if (!putStacksToSleepLocked(allowDelay, false /* shuttingDown */)) {
+ if (!mRootActivityContainer.putStacksToSleep(
+ allowDelay, false /* shuttingDown */)) {
return;
}
// Send launch end powerhint before going sleep
- sendPowerHintForLaunchEndIfNeeded();
+ mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
removeSleepTimeouts();
@@ -3571,52 +2039,24 @@
}
}
- // Tries to put all activity stacks to sleep. Returns true if all stacks were
- // successfully put to sleep.
- private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
- boolean allSleep = true;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (allowDelay) {
- allSleep &= stack.goToSleepIfPossible(shuttingDown);
- } else {
- stack.goToSleep();
- }
- }
- }
- return allSleep;
- }
-
boolean reportResumedActivityLocked(ActivityRecord r) {
// A resumed activity cannot be stopping. remove from list
mStoppingActivities.remove(r);
final ActivityStack stack = r.getStack();
- if (isTopDisplayFocusedStack(stack)) {
+ if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
mService.updateUsageStats(r, true);
}
if (stack.getDisplay().allResumedActivitiesComplete()) {
- ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// Make sure activity & window visibility should be identical
// for all displays in this stage.
- executeAppTransitionForAllDisplay();
+ mRootActivityContainer.executeAppTransitionForAllDisplay();
return true;
}
return false;
}
- void handleAppCrashLocked(WindowProcessController app) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.handleAppCrashLocked(app);
- }
- }
- }
-
// Called when WindowManager has finished animating the launchingBehind activity to the back.
private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
final TaskRecord task = r.getTask();
@@ -3639,157 +2079,9 @@
mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
}
- /**
- * Make sure that all activities that need to be visible in the system actually are and update
- * their configuration.
- */
- void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
- boolean preserveWindows) {
- ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
- true /* notifyClients */);
- }
-
- /**
- * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
- */
- void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
- boolean preserveWindows, boolean notifyClients) {
- getKeyguardController().beginActivityVisibilityUpdate();
- try {
- // First the front stacks. In case any are not fullscreen and are in front of home.
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
- notifyClients);
- }
- }
- } finally {
- getKeyguardController().endActivityVisibilityUpdate();
- }
- }
-
- void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.addStartingWindowsForVisibleActivities(taskSwitch);
- }
- }
- }
-
- void invalidateTaskLayers() {
- mTaskLayersChanged = true;
- }
-
- void rankTaskLayersIfNeeded() {
- if (!mTaskLayersChanged) {
- return;
- }
- mTaskLayersChanged = false;
- for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- int baseLayer = 0;
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- baseLayer += stack.rankTaskLayers(baseLayer);
- }
- }
- }
-
- void clearOtherAppTimeTrackers(AppTimeTracker except) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.clearOtherAppTimeTrackers(except);
- }
- }
- }
-
- void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.scheduleDestroyActivities(app, reason);
- }
- }
- }
-
- void releaseSomeActivitiesLocked(WindowProcessController app, String reason) {
- // Tasks is non-null only if two or more tasks are found.
- ArraySet<TaskRecord> tasks = app.getReleaseSomeActivitiesTasks();
- if (tasks == null) {
- if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release");
- return;
- }
- // If we have activities in multiple tasks that are in a position to be destroyed,
- // let's iterate through the tasks and release the oldest one.
- final int numDisplays = mActivityDisplays.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- final int stackCount = display.getChildCount();
- // Step through all stacks starting from behind, to hit the oldest things first.
- for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- // Try to release activities in this stack; if we manage to, we are done.
- if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
- return;
- }
- }
- }
- }
-
- boolean switchUserLocked(int userId, UserState uss) {
- final int focusStackId = getTopDisplayFocusedStack().getStackId();
- // We dismiss the docked stack whenever we switch users.
- final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
- if (dockedStack != null) {
- moveTasksToFullscreenStackLocked(dockedStack, dockedStack.isFocusedStackOnDisplay());
- }
- // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
- // also cause all tasks to be moved to the fullscreen stack at a position that is
- // appropriate.
- removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
-
- mUserStackInFront.put(mCurrentUser, focusStackId);
- final int restoreStackId =
- mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId);
- mCurrentUser = userId;
-
- mStartingUsers.add(uss);
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- stack.switchUserLocked(userId);
- TaskRecord task = stack.topTask();
- if (task != null) {
- stack.positionChildWindowContainerAtTop(task);
- }
- }
- }
-
- ActivityStack stack = getStack(restoreStackId);
- if (stack == null) {
- stack = getDefaultDisplay().getHomeStack();
- }
- final boolean homeInFront = stack.isActivityTypeHome();
- if (stack.isOnHomeDisplay()) {
- stack.moveToFront("switchUserOnHomeDisplay");
- } else {
- // Stack was moved to another display while user was swapped out.
- resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY);
- }
- return homeInFront;
- }
-
/** Checks whether the userid is a profile of the current user. */
boolean isCurrentProfileLocked(int userId) {
- if (userId == mCurrentUser) return true;
+ if (userId == mRootActivityContainer.mCurrentUser) return true;
return mService.mAmInternal.isCurrentProfile(userId);
}
@@ -3814,7 +2106,7 @@
boolean remove, boolean processPausingActivities) {
ArrayList<ActivityRecord> stops = null;
- final boolean nowVisible = allResumedActivitiesVisible();
+ final boolean nowVisible = mRootActivityContainer.allResumedActivitiesVisible();
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
boolean waitingVisible = mActivitiesWaitingForVisibleActivity.contains(s);
@@ -3864,134 +2156,26 @@
return stops;
}
- void validateTopActivitiesLocked() {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- final ActivityRecord r = stack.topRunningActivityLocked();
- final ActivityState state = r == null ? DESTROYED : r.getState();
- if (isTopDisplayFocusedStack(stack)) {
- if (r == null) Slog.e(TAG,
- "validateTop...: null top activity, stack=" + stack);
- else {
- final ActivityRecord pausing = stack.mPausingActivity;
- if (pausing != null && pausing == r) Slog.e(TAG,
- "validateTop...: top stack has pausing activity r=" + r
- + " state=" + state);
- if (state != INITIALIZING && state != RESUMED) Slog.e(TAG,
- "validateTop...: activity in front not resumed r=" + r
- + " state=" + state);
- }
- } else {
- final ActivityRecord resumed = stack.getResumedActivity();
- if (resumed != null && resumed == r) Slog.e(TAG,
- "validateTop...: back stack has resumed activity r=" + r
- + " state=" + state);
- if (r != null && (state == INITIALIZING || state == RESUMED)) Slog.e(TAG,
- "validateTop...: activity in back resumed r=" + r + " state=" + state);
- }
- }
- }
- }
-
- public void dumpDisplays(PrintWriter pw) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- pw.print("[id:" + display.mDisplayId + " stacks:");
- display.dumpStacks(pw);
- pw.print("]");
- }
- }
-
public void dump(PrintWriter pw, String prefix) {
pw.println();
pw.println("ActivityStackSupervisor state:");
- pw.print(prefix);
- pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
+ mRootActivityContainer.dump(pw, prefix);
pw.print(prefix);
pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser);
- pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- display.dump(pw, prefix);
- }
+ pw.println(prefix + "mUserStackInFront=" + mRootActivityContainer.mUserStackInFront);
if (!mWaitingForActivityVisible.isEmpty()) {
- pw.print(prefix); pw.println("mWaitingForActivityVisible=");
+ pw.println(prefix + "mWaitingForActivityVisible=");
for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) {
- pw.print(prefix); pw.print(prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix);
+ pw.print(prefix + prefix); mWaitingForActivityVisible.get(i).dump(pw, prefix);
}
}
pw.print(prefix); pw.print("isHomeRecentsComponent=");
- pw.print(mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
+ pw.print(mRecentTasks.isRecentsComponentHomeActivity(mRootActivityContainer.mCurrentUser));
getKeyguardController().dump(pw, prefix);
mService.getLockTaskController().dump(pw, prefix);
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
- for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
- activityDisplay.writeToProto(proto, DISPLAYS);
- }
- getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER);
- // TODO(b/111541062): Update tests to look for resumed activities on all displays
- final ActivityStack focusedStack = getTopDisplayFocusedStack();
- if (focusedStack != null) {
- proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
- final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
- if (focusedActivity != null) {
- focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
- }
- } else {
- proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
- }
- proto.write(IS_HOME_RECENTS_COMPONENT,
- mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
- mService.getActivityStartController().writeToProto(proto, PENDING_ACTIVITIES);
- proto.end(token);
- }
-
- /**
- * Dump all connected displays' configurations.
- * @param prefix Prefix to apply to each line of the dump.
- */
- void dumpDisplayConfigs(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.println("Display override configurations:");
- final int displayCount = mActivityDisplays.size();
- for (int i = 0; i < displayCount; i++) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
- pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
- pw.println(activityDisplay.getOverrideConfiguration());
- }
- }
-
- /**
- * Dumps the activities matching the given {@param name} in the either the focused stack
- * or all visible stacks if {@param dumpVisibleStacks} is true.
- */
- ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, boolean dumpVisibleStacksOnly,
- boolean dumpFocusedStackOnly) {
- if (dumpFocusedStackOnly) {
- return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
- } else {
- ArrayList<ActivityRecord> activities = new ArrayList<>();
- int numDisplays = mActivityDisplays.size();
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
- activities.addAll(stack.getDumpActivitiesLocked(name));
- }
- }
- }
- return activities;
- }
- }
-
static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
boolean needSep, String prefix) {
if (activity != null) {
@@ -4007,73 +2191,6 @@
return false;
}
- boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
- boolean dumpClient, String dumpPackage) {
- boolean printed = false;
- boolean needSep = false;
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
- pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
- pw.println(" (activities from top to bottom):");
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- pw.println();
- pw.println(" Stack #" + stack.mStackId
- + ": type=" + activityTypeToString(stack.getActivityType())
- + " mode=" + windowingModeToString(stack.getWindowingMode()));
- pw.println(" isSleeping=" + stack.shouldSleepActivities());
- pw.println(" mBounds=" + stack.getOverrideBounds());
-
- printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
- needSep);
-
- printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
- !dumpAll, false, dumpPackage, true,
- " Running activities (most recent first):", null);
-
- needSep = printed;
- boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
- " mPausingActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
- " mResumedActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- if (dumpAll) {
- pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
- " mLastPausedActivity: ");
- if (pr) {
- printed = true;
- needSep = true;
- }
- printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
- needSep, " mLastNoHistoryActivity: ");
- }
- needSep = printed;
- }
- printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep,
- " ResumedActivity:");
- }
-
- printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to finish:", null);
- printed |= dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to stop:", null);
- printed |= dumpHistoryList(fd, pw, mActivitiesWaitingForVisibleActivity, " ", "Wait",
- false, !dumpAll, false, dumpPackage, true,
- " Activities waiting for another to become visible:", null);
- printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, " ", "Sleep", false, !dumpAll,
- false, dumpPackage, true, " Activities waiting to sleep:", null);
-
- return printed;
- }
-
static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
String prefix, String label, boolean complete, boolean brief, boolean client,
String dumpPackage, boolean needNL, String header, TaskRecord lastTask) {
@@ -4183,294 +2300,6 @@
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
}
- @Override
- public void onDisplayAdded(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
- synchronized (mService.mGlobalLock) {
- getActivityDisplayOrCreateLocked(displayId);
- // Do not start home before booting, or it may accidentally finish booting before it
- // starts. Instead, we expect home activities to be launched when the system is ready
- // (ActivityManagerService#systemReady).
- if (mService.isBooted() || mService.isBooting()) {
- startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
- }
- }
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
- if (displayId == DEFAULT_DISPLAY) {
- throw new IllegalArgumentException("Can't remove the primary display.");
- }
-
- synchronized (mService.mGlobalLock) {
- final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
- if (activityDisplay == null) {
- return;
- }
-
- activityDisplay.remove();
- }
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
- synchronized (mService.mGlobalLock) {
- final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
- if (activityDisplay != null) {
- activityDisplay.onDisplayChanged();
- }
- }
- }
-
- /** Check if display with specified id is added to the list. */
- boolean isDisplayAdded(int displayId) {
- return getActivityDisplayOrCreateLocked(displayId) != null;
- }
-
- // TODO: Look into consolidating with getActivityDisplayOrCreateLocked()
- ActivityDisplay getActivityDisplay(int displayId) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
- if (activityDisplay.mDisplayId == displayId) {
- return activityDisplay;
- }
- }
- return null;
- }
-
- // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
- ActivityDisplay getDefaultDisplay() {
- return mDefaultDisplay;
- }
-
- /**
- * Get an existing instance of {@link ActivityDisplay} or create new if there is a
- * corresponding record in display manager.
- */
- // TODO: Look into consolidating with getActivityDisplay()
- ActivityDisplay getActivityDisplayOrCreateLocked(int displayId) {
- ActivityDisplay activityDisplay = getActivityDisplay(displayId);
- if (activityDisplay != null) {
- return activityDisplay;
- }
- if (mDisplayManager == null) {
- // The system isn't fully initialized yet.
- return null;
- }
- final Display display = mDisplayManager.getDisplay(displayId);
- if (display == null) {
- // The display is not registered in DisplayManager.
- return null;
- }
- // The display hasn't been added to ActivityManager yet, create a new record now.
- activityDisplay = new ActivityDisplay(this, display);
- addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM);
- return activityDisplay;
- }
-
- /**
- * Get an existing instance of {@link ActivityDisplay} that has the given uniqueId. Unique ID is
- * defined in {@link DisplayInfo#uniqueId}.
- *
- * @param uniqueId the unique ID of the display
- * @return the {@link ActivityDisplay} or {@code null} if nothing is found.
- */
- ActivityDisplay getActivityDisplay(String uniqueId) {
- for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- final boolean isValid = display.mDisplay.isValid();
- if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
- return display;
- }
- }
-
- return null;
- }
-
- boolean startHomeOnAllDisplays(int userId, String reason) {
- boolean homeStarted = false;
- for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
- final int displayId = mActivityDisplays.get(i).mDisplayId;
- homeStarted |= startHomeOnDisplay(userId, reason, displayId);
- }
- return homeStarted;
- }
-
- /**
- * This starts home activity on displays that can have system decorations and only if the
- * home activity can have multiple instances.
- */
- boolean startHomeOnDisplay(int userId, String reason, int displayId) {
- final Intent homeIntent = mService.getHomeIntent();
- final ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
- if (aInfo == null) {
- return false;
- }
-
- if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
- return false;
- }
-
- // Update the reason for ANR debugging to verify if the user activity is the one that
- // actually launched.
- final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
- aInfo.applicationInfo.uid);
- mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
- displayId);
- return true;
- }
-
- /**
- * This resolves the home activity info and updates the home component of the given intent.
- * @return the home activity info if any.
- */
- private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
- final int flags = ActivityManagerService.STOCK_PM_FLAGS;
- final ComponentName comp = homeIntent.getComponent();
- ActivityInfo aInfo = null;
- try {
- if (comp != null) {
- // Factory test.
- aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
- } else {
- final String resolvedType =
- homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
- final ResolveInfo info = AppGlobals.getPackageManager()
- .resolveIntent(homeIntent, resolvedType, flags, userId);
- if (info != null) {
- aInfo = info.activityInfo;
- }
- }
- } catch (RemoteException e) {
- // ignore
- }
-
- if (aInfo == null) {
- Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
- return null;
- }
-
- homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
- aInfo = new ActivityInfo(aInfo);
- aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
- homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
- return aInfo;
- }
-
- @VisibleForTesting
- void addChild(ActivityDisplay activityDisplay, int position) {
- positionChildAt(activityDisplay, position);
- mWindowContainerController.positionChildAt(
- activityDisplay.getWindowContainerController(), position);
- }
-
- void removeChild(ActivityDisplay activityDisplay) {
- // The caller must tell the controller of {@link ActivityDisplay} to release its container
- // {@link DisplayContent}. That is done in {@link ActivityDisplay#releaseSelfIfNeeded}).
- mActivityDisplays.remove(activityDisplay);
- }
-
- private void calculateDefaultMinimalSizeOfResizeableTasks() {
- final Resources res = mService.mContext.getResources();
- final float minimalSize = res.getDimension(
- com.android.internal.R.dimen.default_minimal_size_resizable_task);
- final DisplayMetrics dm = res.getDisplayMetrics();
-
- mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
- }
-
- SleepToken createSleepTokenLocked(String tag, int displayId) {
- final ActivityDisplay display = getActivityDisplay(displayId);
- if (display == null) {
- throw new IllegalArgumentException("Invalid display: " + displayId);
- }
-
- final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
- mSleepTokens.add(token);
- display.mAllSleepTokens.add(token);
- return token;
- }
-
- private void removeSleepTokenLocked(SleepTokenImpl token) {
- mSleepTokens.remove(token);
-
- final ActivityDisplay display = getActivityDisplay(token.mDisplayId);
- if (display != null) {
- display.mAllSleepTokens.remove(token);
- if (display.mAllSleepTokens.isEmpty()) {
- mService.updateSleepIfNeededLocked();
- }
- }
- }
-
- private StackInfo getStackInfo(ActivityStack stack) {
- final int displayId = stack.mDisplayId;
- final ActivityDisplay display = getActivityDisplay(displayId);
- StackInfo info = new StackInfo();
- stack.getWindowContainerBounds(info.bounds);
- info.displayId = displayId;
- info.stackId = stack.mStackId;
- info.userId = stack.mCurrentUser;
- info.visible = stack.shouldBeVisible(null);
- // A stack might be not attached to a display.
- info.position = display != null ? display.getIndexOf(stack) : 0;
- info.configuration.setTo(stack.getConfiguration());
-
- ArrayList<TaskRecord> tasks = stack.getAllTasks();
- final int numTasks = tasks.size();
- int[] taskIds = new int[numTasks];
- String[] taskNames = new String[numTasks];
- Rect[] taskBounds = new Rect[numTasks];
- int[] taskUserIds = new int[numTasks];
- for (int i = 0; i < numTasks; ++i) {
- final TaskRecord task = tasks.get(i);
- taskIds[i] = task.taskId;
- taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
- : task.realActivity != null ? task.realActivity.flattenToString()
- : task.getTopActivity() != null ? task.getTopActivity().packageName
- : "unknown";
- taskBounds[i] = new Rect();
- task.getWindowContainerBounds(taskBounds[i]);
- taskUserIds[i] = task.userId;
- }
- info.taskIds = taskIds;
- info.taskNames = taskNames;
- info.taskBounds = taskBounds;
- info.taskUserIds = taskUserIds;
-
- final ActivityRecord top = stack.topRunningActivityLocked();
- info.topActivity = top != null ? top.intent.getComponent() : null;
- return info;
- }
-
- StackInfo getStackInfo(int stackId) {
- ActivityStack stack = getStack(stackId);
- if (stack != null) {
- return getStackInfo(stack);
- }
- return null;
- }
-
- StackInfo getStackInfo(int windowingMode, int activityType) {
- final ActivityStack stack = getStack(windowingMode, activityType);
- return (stack != null) ? getStackInfo(stack) : null;
- }
-
- ArrayList<StackInfo> getAllStackInfosLocked() {
- ArrayList<StackInfo> list = new ArrayList<>();
- for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- final ActivityDisplay display = mActivityDisplays.get(displayNdx);
- for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getChildAt(stackNdx);
- list.add(getStackInfo(stack));
- }
- }
- return list;
- }
-
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
int preferredDisplayId, ActivityStack actualStack) {
handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
@@ -4616,21 +2445,6 @@
}
}
- void setDockedStackMinimized(boolean minimized) {
- // Get currently focused stack before setting mIsDockMinimized. We do this because if
- // split-screen is active, primary stack will not be focusable (see #isFocusable) while
- // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null.
- final ActivityStack current = getTopDisplayFocusedStack();
- mIsDockMinimized = minimized;
- if (mIsDockMinimized) {
- if (current.inSplitScreenPrimaryWindowingMode()) {
- // The primary split-screen stack can't be focused while it is minimize, so move
- // focus to something else.
- current.adjustFocusToNextFocusableStack("setDockedStackMinimized");
- }
- }
- }
-
void wakeUp(String reason) {
mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.am:TURN_ON:" + reason);
}
@@ -4649,10 +2463,8 @@
mDeferResumeCount--;
}
- /**
- * @return True if resume can be called.
- */
- private boolean readyToResume() {
+ /** @return True if resume can be called. */
+ boolean readyToResume() {
return mDeferResumeCount == 0;
}
@@ -4704,7 +2516,7 @@
} break;
case RESUME_TOP_ACTIVITY_MSG: {
synchronized (mService.mGlobalLock) {
- resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
} break;
case SLEEP_TIMEOUT_MSG: {
@@ -4740,19 +2552,6 @@
}
}
- ActivityStack findStackBehind(ActivityStack stack) {
- final ActivityDisplay display = getActivityDisplay(stack.mDisplayId);
- if (display != null) {
- for (int i = display.getChildCount() - 1; i >= 0; i--) {
- if (display.getChildAt(i) == stack && i > 0) {
- return display.getChildAt(i - 1);
- }
- }
- }
- throw new IllegalStateException("Failed to find a stack behind stack=" + stack
- + " in=" + display);
- }
-
/**
* Puts a task into resizing mode during the next app transition.
*
@@ -4797,8 +2596,8 @@
mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
}
- task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
- activityOptions, ON_TOP);
+ task = mRootActivityContainer.anyTaskForId(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, activityOptions, ON_TOP);
if (task == null) {
continueUpdateRecentsHomeStackBounds();
mWindowManager.executeAppTransition();
@@ -4811,7 +2610,8 @@
// from whatever is started from the recents activity, so move the home stack
// forward.
// TODO (b/115289124): Multi-display supports for recents.
- getDefaultDisplay().moveHomeStackToFront("startActivityFromRecents");
+ mRootActivityContainer.getDefaultDisplay().moveHomeStackToFront(
+ "startActivityFromRecents");
}
// If the user must confirm credentials (e.g. when first launching a work app and the
@@ -4820,7 +2620,8 @@
&& task.getRootActivity() != null) {
final ActivityRecord targetActivity = task.getTopActivity();
- sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
+ mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ true /* forceSend */, targetActivity);
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
try {
mService.moveTaskToFrontLocked(task.taskId, 0, options,
@@ -4873,35 +2674,6 @@
}
/**
- * @return a list of activities which are the top ones in each visible stack. The first
- * entry will be the focused activity.
- */
- List<IBinder> getTopVisibleActivities() {
- final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
- final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
- // Traverse all displays.
- for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
- final ActivityDisplay display = mActivityDisplays.get(i);
- // Traverse all stacks on a display.
- for (int j = display.getChildCount() - 1; j >= 0; --j) {
- final ActivityStack stack = display.getChildAt(j);
- // Get top activity from a visible stack and add it to the list.
- if (stack.shouldBeVisible(null /* starting */)) {
- final ActivityRecord top = stack.getTopActivity();
- if (top != null) {
- if (stack == topFocusedStack) {
- topActivityTokens.add(0, top.appToken);
- } else {
- topActivityTokens.add(top.appToken);
- }
- }
- }
- }
- }
- return topActivityTokens;
- }
-
- /**
* Internal container to store a match qualifier alongside a WaitResult.
*/
static class WaitInfo {
@@ -4939,30 +2711,4 @@
mResult.dump(pw, prefix);
}
}
-
- private final class SleepTokenImpl extends SleepToken {
- private final String mTag;
- private final long mAcquireTime;
- private final int mDisplayId;
-
- public SleepTokenImpl(String tag, int displayId) {
- mTag = tag;
- mDisplayId = displayId;
- mAcquireTime = SystemClock.uptimeMillis();
- }
-
- @Override
- public void release() {
- synchronized (mService.mGlobalLock) {
- removeSleepTokenLocked(this);
- }
- }
-
- @Override
- public String toString() {
- return "{\"" + mTag + "\", display " + mDisplayId
- + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
- }
- }
-
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index ee5a43c..54a63a1 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -70,6 +70,7 @@
private final ActivityTaskManagerService mService;
private final ActivityStackSupervisor mSupervisor;
+ private final RootActivityContainer mRootActivityContainer;
private final Context mServiceContext;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
@@ -102,14 +103,15 @@
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityStackSupervisor supervisor) {
- this(service, supervisor, service.mContext);
+ this(service, supervisor, service.mRootActivityContainer, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityStackSupervisor supervisor,
- Context context) {
+ RootActivityContainer root, Context context) {
mService = service;
mSupervisor = supervisor;
+ mRootActivityContainer = root;
mServiceContext = context;
}
@@ -279,7 +281,7 @@
mActivityOptions = ActivityOptions.makeBasic();
}
- ActivityRecord homeActivityRecord = mSupervisor.getDefaultDisplayHomeActivity();
+ ActivityRecord homeActivityRecord = mRootActivityContainer.getDefaultDisplayHomeActivity();
if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
// Showing credential confirmation activity in home task to avoid stopping multi-windowed
// mode after showing the full-screen credential confirmation activity.
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 90f3ff8..cba1044 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -98,6 +98,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -108,6 +109,7 @@
import android.util.EventLog;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
+import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HeavyWeightSwitcherActivity;
@@ -137,6 +139,7 @@
private static final int INVALID_LAUNCH_MODE = -1;
private final ActivityTaskManagerService mService;
+ private final RootActivityContainer mRootActivityContainer;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
private final ActivityStartController mController;
@@ -421,6 +424,7 @@
ActivityStackSupervisor supervisor, ActivityStartInterceptor interceptor) {
mController = controller;
mService = service;
+ mRootActivityContainer = service.mRootActivityContainer;
mSupervisor = supervisor;
mInterceptor = interceptor;
reset(true);
@@ -617,7 +621,7 @@
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
- sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
+ sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
@@ -731,6 +735,12 @@
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
+ // not sure if we need to create START_ABORTED_BACKGROUND so for now piggybacking
+ // on START_ABORTED
+ if (!abort) {
+ abort |= shouldAbortBackgroundActivityStart(callingUid, callingPackage, callerApp);
+ }
+
// Merge the two options bundles, while realCallerOptions takes precedence.
ActivityOptions checkedOptions = options != null
? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
@@ -774,6 +784,8 @@
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(checkedOptions);
+ maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp,
+ null /*r*/, originatingPendingIntent, true /*abortedStart*/);
return START_ABORTED;
}
@@ -811,7 +823,8 @@
null /*profilerInfo*/);
if (DEBUG_PERMISSIONS_REVIEW) {
- final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack =
+ mRootActivityContainer.getTopDisplayFocusedStack();
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
true, false) + "} from uid " + callingUid + " on display "
+ (focusedStack == null ? DEFAULT_DISPLAY : focusedStack.mDisplayId));
@@ -847,7 +860,7 @@
r.appTimeTracker = sourceRecord.appTimeTracker;
}
- final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
// If we are starting an activity that is not from the same uid as the currently resumed
// one, check whether app switches are allowed.
@@ -866,19 +879,54 @@
mController.doPendingActivityLaunches(false);
maybeLogActivityStart(callingUid, callingPackage, realCallingUid, intent, callerApp, r,
- originatingPendingIntent);
+ originatingPendingIntent, false /*abortedStart*/);
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity);
}
+ private boolean shouldAbortBackgroundActivityStart(int callingUid, final String callingPackage,
+ WindowProcessController callerApp) {
+ if (mService.isBackgroundActivityStartsEnabled()) {
+ return false;
+ }
+ // don't abort for the most important UIDs
+ if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID) {
+ return false;
+ }
+ // don't abort if the callerApp has any visible activity
+ if (callerApp != null && callerApp.hasForegroundActivities()) {
+ return false;
+ }
+ // don't abort if the callingUid's process is important enough
+ if (mService.getUidStateLocked(callingUid) <= ActivityManager.PROCESS_STATE_TOP) {
+ return false;
+ }
+ // don't abort if the callingUid has any visible window
+ if (mService.mWindowManager.isAnyWindowVisibleForUid(callingUid)) {
+ return false;
+ }
+ // don't abort if the caller has the same uid as the recents component
+ if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
+ return false;
+ }
+ // anything that has fallen through will currently be aborted
+ // TODO: remove this toast after feature development is done
+ mService.mUiHandler.post(() -> {
+ Toast.makeText(mService.mContext,
+ "Blocking background activity start for " + callingPackage,
+ Toast.LENGTH_SHORT).show();
+ });
+ return true;
+ }
+
private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid,
Intent intent, WindowProcessController callerApp, ActivityRecord r,
- PendingIntentRecord originatingPendingIntent) {
+ PendingIntentRecord originatingPendingIntent, boolean abortedStart) {
boolean callerAppHasForegroundActivity =
callerApp != null && callerApp.hasForegroundActivities();
if (!mService.isActivityStartsLoggingEnabled() || callerAppHasForegroundActivity
- || r == null) {
+ || (!abortedStart && r == null)) {
// skip logging in this case
return;
}
@@ -894,8 +942,8 @@
final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
? callingUidHasAnyVisibleWindow
: mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid);
- final String targetPackage = r.packageName;
- final int targetUid = (r.appInfo != null) ? r.appInfo.uid : -1;
+ final String targetPackage = (r != null) ? r.packageName : null;
+ final int targetUid = (r!= null) ? ((r.appInfo != null) ? r.appInfo.uid : -1) : -1;
final int targetUidProcState = mService.getUidStateLocked(targetUid);
final boolean targetUidHasAnyVisibleWindow = (targetUid != -1)
? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid)
@@ -1063,7 +1111,7 @@
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
synchronized (mService.mGlobalLock) {
- final ActivityStack stack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
stack.mConfigWillChange = globalConfig != null
&& mService.getGlobalConfiguration().diff(globalConfig) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
@@ -1249,7 +1297,8 @@
final ActivityRecord currentTop =
startedActivityStack.topRunningActivityLocked();
if (currentTop != null && currentTop.shouldUpdateConfigForDisplayChanged()) {
- mSupervisor.ensureVisibilityAndConfig(currentTop, currentTop.getDisplayId(),
+ mRootActivityContainer.ensureVisibilityAndConfig(
+ currentTop, currentTop.getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
}
@@ -1284,7 +1333,7 @@
// Do not start home activity if it cannot be launched on preferred display. We are not
// doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
// fallback to launch on other displays.
- if (r.isActivityTypeHome() && !mSupervisor.canStartHomeOnDisplay(r.info,
+ if (r.isActivityTypeHome() && !mRootActivityContainer.canStartHomeOnDisplay(r.info,
mPreferredDisplayId, true /* allowInstrumenting */)) {
Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
return START_CANCELED;
@@ -1361,7 +1410,8 @@
}
}
- mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
+ mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded
+ (false /* forceSend */, reusedActivity);
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
@@ -1413,7 +1463,7 @@
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
- final ActivityStack topStack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack();
final ActivityRecord topFocused = topStack.getTopActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
@@ -1430,7 +1480,7 @@
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -1485,7 +1535,8 @@
EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
mTargetStack.mLastPausedActivity = null;
- mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
+ mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ false /* forceSend */, mStartActivity);
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
@@ -1512,16 +1563,16 @@
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable()
- && !mSupervisor.isTopDisplayFocusedStack(mTargetStack)) {
+ && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
- mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, mStartActivity,
- mOptions);
+ mRootActivityContainer.resumeFocusedStacksTopActivities(
+ mTargetStack, mStartActivity, mOptions);
}
} else if (mStartActivity != null) {
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
}
- mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
+ mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
mPreferredDisplayId, mTargetStack);
@@ -1642,7 +1693,7 @@
if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
r.mTaskOverlay = true;
if (!mOptions.canTaskOverlayResume()) {
- final TaskRecord task = mSupervisor.anyTaskForIdLocked(
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(
mOptions.getLaunchTaskId());
final ActivityRecord top = task != null ? task.getTopActivity() : null;
if (top != null && !top.isState(RESUMED)) {
@@ -1678,7 +1729,7 @@
if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
- checkedCaller = mSupervisor.getTopDisplayFocusedStack()
+ checkedCaller = mRootActivityContainer.getTopDisplayFocusedStack()
.topRunningNonDelayedActivityLocked(mNotTop);
}
if (!checkedCaller.realActivity.equals(r.realActivity)) {
@@ -1840,22 +1891,23 @@
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
- final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
- intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
+ intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
mStartActivity.isActivityTypeHome());
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
- intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
+ intentActivity = mRootActivityContainer.findActivity(mIntent, mStartActivity.info,
!(LAUNCH_SINGLE_TASK == mLaunchMode));
} else {
// Otherwise find the best task to put the activity in.
- intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
+ intentActivity =
+ mRootActivityContainer.findTask(mStartActivity, mPreferredDisplayId);
}
}
@@ -2067,11 +2119,11 @@
private void resumeTargetStackIfNeeded() {
if (mDoResume) {
- mSupervisor.resumeFocusedStacksTopActivitiesLocked(mTargetStack, null, mOptions);
+ mRootActivityContainer.resumeFocusedStacksTopActivities(mTargetStack, null, mOptions);
} else {
ActivityOptions.abort(mOptions);
}
- mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
+ mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack);
}
private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
@@ -2145,13 +2197,13 @@
// be not suitable. Let's check other displays.
if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
// Can't use target display, lets find a stack on the source display.
- mTargetStack = mSupervisor.getValidLaunchStackOnDisplay(
+ mTargetStack = mRootActivityContainer.getValidLaunchStackOnDisplay(
sourceStack.mDisplayId, mStartActivity, mOptions, mLaunchParams);
}
if (mTargetStack == null) {
// There are no suitable stacks on the target and source display(s). Look on all
// displays.
- mTargetStack = mSupervisor.getNextValidLaunchStackLocked(
+ mTargetStack = mRootActivityContainer.getNextValidLaunchStack(
mStartActivity, -1 /* currentFocus */);
}
}
@@ -2182,7 +2234,7 @@
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
ActivityOptions.abort(mOptions);
return START_DELIVERED_TO_TOP;
@@ -2200,7 +2252,7 @@
deliverNewIntent(top);
mTargetStack.mLastPausedActivity = null;
if (mDoResume) {
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
return START_DELIVERED_TO_TOP;
}
@@ -2254,7 +2306,8 @@
if (!mLaunchParams.mBounds.isEmpty()) {
// TODO: Shouldn't we already know what stack to use by the time we get here?
- ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
+ ActivityStack stack = mRootActivityContainer.getLaunchStack(
+ null, null, mInTask, ON_TOP);
if (stack != mInTask.getStack()) {
mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
DEFER_RESUME, "inTaskToFront");
@@ -2348,7 +2401,7 @@
}
final ActivityStack currentStack = task != null ? task.getStack() : null;
- final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
if (currentStack != null) {
if (focusedStack != currentStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -2369,18 +2422,18 @@
if (mPreferredDisplayId != DEFAULT_DISPLAY) {
// Try to put the activity in a stack on a secondary display.
- stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r, aOptions,
- mLaunchParams);
+ stack = mRootActivityContainer.getValidLaunchStackOnDisplay(
+ mPreferredDisplayId, r, aOptions, mLaunchParams);
if (stack == null) {
// If source display is not suitable - look for topmost valid stack in the system.
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Can't launch on mPreferredDisplayId="
+ mPreferredDisplayId + ", looking on all displays.");
- stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId);
+ stack = mRootActivityContainer.getNextValidLaunchStack(r, mPreferredDisplayId);
}
}
if (stack == null) {
- stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
+ stack = mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
@@ -2390,7 +2443,7 @@
/** Check if provided activity record can launch in currently focused stack. */
// TODO: This method can probably be consolidated into getLaunchStack() below.
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
- final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
final boolean canUseFocusedStack;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
@@ -2436,14 +2489,14 @@
// full resolution.
mLaunchParams.mPreferredDisplayId =
mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
- final ActivityStack stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
- mLaunchParams);
+ final ActivityStack stack =
+ mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP, mLaunchParams);
mLaunchParams.mPreferredDisplayId = mPreferredDisplayId;
return stack;
}
// Otherwise handle adjacent launch.
- final ActivityStack focusedStack = mSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack focusedStack = mRootActivityContainer.getTopDisplayFocusedStack();
// The parent activity doesn't want to launch the activity on top of itself, but
// instead tries to put it onto other side in side-by-side mode.
final ActivityStack parentStack = task != null ? task.getStack(): focusedStack;
@@ -2461,7 +2514,8 @@
if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
- final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
+ final int activityType =
+ mRootActivityContainer.resolveActivityType(r, mOptions, task);
return parentStack.getDisplay().getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
} else {
@@ -2469,10 +2523,10 @@
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack =
- mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
- return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
+ return mRootActivityContainer.getLaunchStack(r, aOptions, task, ON_TOP);
} else {
return dockedStack;
}
@@ -2660,7 +2714,7 @@
prefix = prefix + " ";
pw.print(prefix);
pw.print("mCurrentUser=");
- pw.println(mSupervisor.mCurrentUser);
+ pw.println(mRootActivityContainer.mCurrentUser);
pw.print(prefix);
pw.print("mLastStartReason=");
pw.println(mLastStartReason);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d0e3fb4..11e998c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -91,8 +91,6 @@
.PACKAGE;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
-import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
-import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -122,6 +120,8 @@
import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_ONLY;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
@@ -352,6 +352,7 @@
/* Global service lock used by the package the owns this service. */
final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
ActivityStackSupervisor mStackSupervisor;
+ RootActivityContainer mRootActivityContainer;
WindowManagerService mWindowManager;
private UserManagerService mUserManager;
private AppOpsService mAppOpsService;
@@ -766,7 +767,8 @@
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
mStackSupervisor = createStackSupervisor();
- mStackSupervisor.onConfigurationChanged(mTempConfig);
+ mRootActivityContainer = new RootActivityContainer(this);
+ mRootActivityContainer.onConfigurationChanged(mTempConfig);
mTaskChangeNotificationController =
new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
@@ -801,6 +803,7 @@
mWindowManager = wm;
mLockTaskController.setWindowManager(wm);
mStackSupervisor.setWindowManager(wm);
+ mRootActivityContainer.setWindowManager(wm);
}
}
@@ -1255,7 +1258,7 @@
sourceToken = resultTo;
}
- sourceRecord = mStackSupervisor.isInAnyStackLocked(sourceToken);
+ sourceRecord = mRootActivityContainer.isInAnyStack(sourceToken);
if (sourceRecord == null) {
throw new SecurityException("Called with bad activity token: " + sourceToken);
}
@@ -1799,7 +1802,7 @@
}
final boolean translucentChanged = r.changeWindowTranslucency(true);
if (translucentChanged) {
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
mWindowManager.setAppFullscreen(token, true);
return translucentChanged;
@@ -1829,7 +1832,7 @@
if (translucentChanged) {
r.getStack().convertActivityToTranslucent(r);
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mWindowManager.setAppFullscreen(token, false);
return translucentChanged;
}
@@ -1842,7 +1845,7 @@
public void notifyActivityDrawn(IBinder token) {
if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token);
synchronized (mGlobalLock) {
- ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token);
+ ActivityRecord r = mRootActivityContainer.isInAnyStack(token);
if (r != null) {
r.getStack().notifyActivityDrawnLocked(r);
}
@@ -1879,7 +1882,7 @@
synchronized (mGlobalLock) {
ActivityStack focusedStack = getTopDisplayFocusedStack();
if (focusedStack != null) {
- return mStackSupervisor.getStackInfo(focusedStack.mStackId);
+ return mRootActivityContainer.getStackInfo(focusedStack.mStackId);
}
return null;
}
@@ -1895,14 +1898,14 @@
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId);
return;
}
final ActivityRecord r = stack.topRunningActivityLocked();
if (r != null && r.moveFocusableActivityToTop("setFocusedStack")) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
} finally {
@@ -1917,14 +1920,14 @@
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
return;
}
final ActivityRecord r = task.topRunningActivityLocked();
if (r != null && r.moveFocusableActivityToTop("setFocusedTask")) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
} finally {
@@ -2009,7 +2012,7 @@
final long origId = Binder.clearCallingIdentity();
try {
int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId);
if (task != null) {
return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
}
@@ -2027,7 +2030,7 @@
Rect rect = new Rect();
try {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
@@ -2058,7 +2061,7 @@
synchronized (mGlobalLock) {
enforceCallerIsRecentsOrHasPermission(
MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
- final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
+ final TaskRecord tr = mRootActivityContainer.anyTaskForId(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
return tr.lastTaskDescription;
@@ -2078,7 +2081,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "setTaskWindowingMode: No task for id=" + taskId);
@@ -2167,7 +2170,7 @@
}
final long origId = Binder.clearCallingIdentity();
try {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId);
if (task == null) {
Slog.d(TAG, "Could not find task for id: "+ taskId);
SafeActivityOptions.abort(options);
@@ -2284,7 +2287,7 @@
final boolean allowed = isGetTasksAllowed("getTasks", Binder.getCallingPid(),
callingUid);
- mStackSupervisor.getRunningTasks(maxNum, list, ignoreActivityType,
+ mRootActivityContainer.getRunningTasks(maxNum, list, ignoreActivityType,
ignoreWindowingMode, callingUid, allowed);
}
@@ -2320,7 +2323,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId);
if (task == null) {
Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
return;
@@ -2329,7 +2332,7 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
throw new IllegalStateException(
"moveTaskToStack: No stack for stackId=" + stackId);
@@ -2359,7 +2362,7 @@
try {
synchronized (mGlobalLock) {
if (animate) {
- final PinnedActivityStack stack = mStackSupervisor.getStack(stackId);
+ final PinnedActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
@@ -2371,12 +2374,12 @@
stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
animationDuration, false /* fromFullscreen */);
} else {
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
}
- mStackSupervisor.resizeStackLocked(stack, destBounds,
+ mRootActivityContainer.resizeStack(stack, destBounds,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
preserveWindows, allowResizeInDockedMode, !DEFER_RESUME);
}
@@ -2410,7 +2413,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId);
@@ -2452,7 +2455,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- mStackSupervisor.removeStacksInWindowingModes(windowingModes);
+ mRootActivityContainer.removeStacksInWindowingModes(windowingModes);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2467,7 +2470,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- mStackSupervisor.removeStacksWithActivityTypes(activityTypes);
+ mRootActivityContainer.removeStacksWithActivityTypes(activityTypes);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -2498,7 +2501,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mStackSupervisor.getAllStackInfosLocked();
+ return mRootActivityContainer.getAllStackInfos();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2511,7 +2514,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mStackSupervisor.getStackInfo(windowingMode, activityType);
+ return mRootActivityContainer.getStackInfo(windowingMode, activityType);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2553,7 +2556,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
return;
@@ -2595,7 +2598,7 @@
return;
}
- final ActivityStack stack = mStackSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
if (stack == null || task != stack.topTask()) {
throw new IllegalArgumentException("Invalid task, not in foreground");
}
@@ -2610,7 +2613,7 @@
long ident = Binder.clearCallingIdentity();
try {
// When a task is locked, dismiss the pinned stack if it exists
- mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+ mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid);
} finally {
@@ -2712,7 +2715,7 @@
try {
// TODO: VI Consider treating local voice interactions and voice tasks
// differently here
- mStackSupervisor.finishVoiceTask(session);
+ mRootActivityContainer.finishVoiceTask(session);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -2902,7 +2905,7 @@
@Override
public void setTaskResizeable(int taskId, int resizeableMode) {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(
taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
@@ -2918,7 +2921,7 @@
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
@@ -2983,7 +2986,7 @@
final long origId = Binder.clearCallingIdentity();
try {
final WindowProcessController app = getProcessController(appInt);
- mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem");
+ mRootActivityContainer.releaseSomeActivitiesLocked(app, "low-mem");
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3077,7 +3080,7 @@
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
Slog.w(TAG, "removeStack: No stack with id=" + stackId);
return;
@@ -3102,7 +3105,7 @@
try {
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId
+ " to displayId=" + displayId);
- mStackSupervisor.moveStackToDisplayLocked(stackId, displayId, ON_TOP);
+ mRootActivityContainer.moveStackToDisplay(stackId, displayId, ON_TOP);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3564,13 +3567,13 @@
try {
if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task="
+ taskId + " in stackId=" + stackId + " at position=" + position);
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId);
if (task == null) {
throw new IllegalArgumentException("positionTaskInStack: no task for id="
+ taskId);
}
- final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(stackId);
if (stack == null) {
throw new IllegalArgumentException("positionTaskInStack: no stack for id="
@@ -3625,7 +3628,7 @@
try {
synchronized (mGlobalLock) {
final ActivityStack stack =
- mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
return;
@@ -3635,7 +3638,7 @@
// Caller wants the current split-screen primary stack to be the top stack after
// it goes fullscreen, so move it to the front.
stack.moveToFront("dismissSplitScreenMode");
- } else if (mStackSupervisor.isTopDisplayFocusedStack(stack)) {
+ } else if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
// In this case the current split-screen primary stack shouldn't be the top
// stack after it goes fullscreen, but it current has focus, so we move the
// focus to the top-most split-screen secondary stack next to it.
@@ -3666,7 +3669,7 @@
try {
synchronized (mGlobalLock) {
final PinnedActivityStack stack =
- mStackSupervisor.getDefaultDisplay().getPinnedStack();
+ mRootActivityContainer.getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "dismissPip: pinned stack not found.");
return;
@@ -3708,7 +3711,7 @@
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
try {
- final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
+ final ActivityStack stack = mRootActivityContainer.getStack(fromStackId);
if (stack != null){
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
@@ -3743,7 +3746,7 @@
long ident = Binder.clearCallingIdentity();
try {
- return mStackSupervisor.moveTopStackActivityToPinnedStackLocked(stackId, bounds);
+ return mRootActivityContainer.moveTopStackActivityToPinnedStack(stackId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3821,7 +3824,7 @@
// Adjust the source bounds by the insets for the transition down
final Rect sourceBounds = new Rect(
r.pictureInPictureArgs.getSourceRectHint());
- mStackSupervisor.moveActivityToPinnedStackLocked(
+ mRootActivityContainer.moveActivityToPinnedStack(
r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
final PinnedActivityStack stack = r.getStack();
stack.setPictureInPictureAspectRatio(aspectRatio);
@@ -4100,7 +4103,7 @@
synchronized (mGlobalLock) {
// Check if display is initialized in AM.
- if (!mStackSupervisor.isDisplayAdded(displayId)) {
+ if (!mRootActivityContainer.isDisplayAdded(displayId)) {
// Call might come when display is not yet added or has already been removed.
if (DEBUG_CONFIGURATION) {
Slog.w(TAG, "Trying to update display configuration for non-existing displayId="
@@ -4190,7 +4193,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
@@ -4210,7 +4213,7 @@
try {
final TaskRecord task;
synchronized (mGlobalLock) {
- task = mStackSupervisor.anyTaskForIdLocked(taskId,
+ task = mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
@@ -4430,7 +4433,7 @@
if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ " to main stack for VR");
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack(
+ final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
}
@@ -4444,7 +4447,7 @@
if (disableNonVrUi) {
// If we are in a VR mode where Picture-in-Picture mode is unsupported,
// then remove the pinned stack.
- mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+ mRootActivityContainer.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
}
}
});
@@ -4496,7 +4499,7 @@
}
ActivityStack getTopDisplayFocusedStack() {
- return mStackSupervisor.getTopDisplayFocusedStack();
+ return mRootActivityContainer.getTopDisplayFocusedStack();
}
/** Pokes the task persister. */
@@ -4508,6 +4511,21 @@
return mKeyguardController.isKeyguardLocked();
}
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @Override
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "clearLaunchParamsForPackages");
+ synchronized (mGlobalLock) {
+ for (int i = 0; i < packageNames.size(); ++i) {
+ mStackSupervisor.mLaunchParamsPersister.removeRecordForPackage(packageNames.get(i));
+ }
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
@@ -4557,12 +4575,12 @@
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage, String header) {
pw.println(header);
- boolean printedAnything = mStackSupervisor.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient,
+ boolean printedAnything = mRootActivityContainer.dumpActivities(fd, pw, dumpAll, dumpClient,
dumpPackage);
boolean needSep = printedAnything;
boolean printed = ActivityStackSupervisor.printThisActivity(pw,
- mStackSupervisor.getTopResumedActivity(), dumpPackage, needSep,
+ mRootActivityContainer.getTopResumedActivity(), dumpPackage, needSep,
" ResumedActivity: ");
if (printed) {
printedAnything = true;
@@ -4584,7 +4602,7 @@
void dumpActivityContainersLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER STARTER (dumpsys activity containers)");
- mStackSupervisor.dumpChildrenNames(pw, " ");
+ mRootActivityContainer.dumpChildrenNames(pw, " ");
pw.println(" ");
}
@@ -4608,7 +4626,7 @@
ArrayList<ActivityRecord> activities;
synchronized (mGlobalLock) {
- activities = mStackSupervisor.getDumpActivitiesLocked(name, dumpVisibleStacksOnly,
+ activities = mRootActivityContainer.getDumpActivities(name, dumpVisibleStacksOnly,
dumpFocusedStackOnly);
}
@@ -4683,7 +4701,7 @@
}
void writeSleepStateToProto(ProtoOutputStream proto) {
- for (ActivityTaskManagerInternal.SleepToken st : mStackSupervisor.mSleepTokens) {
+ for (ActivityTaskManagerInternal.SleepToken st : mRootActivityContainer.mSleepTokens) {
proto.write(ActivityManagerServiceDumpProcessesProto.SleepStatus.SLEEP_TOKENS,
st.toString());
}
@@ -4728,7 +4746,7 @@
* also corresponds to the merged configuration of the default display.
*/
Configuration getGlobalConfiguration() {
- return mStackSupervisor.getConfiguration();
+ return mRootActivityContainer.getConfiguration();
}
boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
@@ -4860,7 +4878,7 @@
mTempConfig.seq = increaseConfigurationSeqLocked();
// Update stored global config and notify everyone about the change.
- mStackSupervisor.onConfigurationChanged(mTempConfig);
+ mRootActivityContainer.onConfigurationChanged(mTempConfig);
Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
// TODO(multi-display): Update UsageEvents#Event to include displayId.
@@ -4907,7 +4925,7 @@
// Override configuration of the default display duplicates global config, so we need to
// update it also. This will also notify WindowManager about changes.
- performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
+ performDisplayOverrideConfigUpdate(mRootActivityContainer.getConfiguration(), deferResume,
DEFAULT_DISPLAY);
return changes;
@@ -4961,12 +4979,12 @@
private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
int displayId) {
- mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
+ mTempConfig.setTo(mRootActivityContainer.getDisplayOverrideConfiguration(displayId));
final int changes = mTempConfig.updateFrom(values);
if (changes != 0) {
Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+ mTempConfig + " for displayId=" + displayId);
- mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
+ mRootActivityContainer.setDisplayOverrideConfiguration(mTempConfig, displayId);
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
if (isDensityChange && displayId == DEFAULT_DISPLAY) {
@@ -5016,6 +5034,10 @@
return mAmInternal.isActivityStartsLoggingEnabled();
}
+ boolean isBackgroundActivityStartsEnabled() {
+ return mAmInternal.isBackgroundActivityStartsEnabled();
+ }
+
void enableScreenAfterBoot(boolean booted) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
@@ -5096,7 +5118,7 @@
mCurAppTimeTracker.stop();
mH.obtainMessage(
REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
- mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
+ mRootActivityContainer.clearOtherAppTimeTrackers(r.appTimeTracker);
mCurAppTimeTracker = null;
}
if (r.appTimeTracker != null) {
@@ -5157,14 +5179,15 @@
ActivityTaskManagerInternal.SleepToken acquireSleepToken(String tag, int displayId) {
synchronized (mGlobalLock) {
- final ActivityTaskManagerInternal.SleepToken token = mStackSupervisor.createSleepTokenLocked(tag, displayId);
+ final ActivityTaskManagerInternal.SleepToken token =
+ mRootActivityContainer.createSleepToken(tag, displayId);
updateSleepIfNeededLocked();
return token;
}
}
void updateSleepIfNeededLocked() {
- final boolean shouldSleep = !mStackSupervisor.hasAwakeDisplay();
+ final boolean shouldSleep = !mRootActivityContainer.hasAwakeDisplay();
final boolean wasSleeping = mSleeping;
boolean updateOomAdj = false;
@@ -5180,7 +5203,7 @@
mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
mStackSupervisor.comeOutOfSleepIfNeededLocked();
}
- mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
+ mRootActivityContainer.applySleepTokens(true /* applyToStacks */);
if (wasSleeping) {
updateOomAdj = true;
}
@@ -5356,7 +5379,7 @@
// TODO(b/111541062): Update app time tracking to make it aware of multiple resumed activities
private void startTimeTrackingFocusedActivityLocked() {
- final ActivityRecord resumedActivity = mStackSupervisor.getTopResumedActivity();
+ final ActivityRecord resumedActivity = mRootActivityContainer.getTopResumedActivity();
if (!mSleeping && mCurAppTimeTracker != null && resumedActivity != null) {
mCurAppTimeTracker.start(resumedActivity.packageName);
}
@@ -5381,7 +5404,7 @@
/** Applies latest configuration and/or visibility updates if needed. */
private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
boolean kept = true;
- final ActivityStack mainStack = mStackSupervisor.getTopDisplayFocusedStack();
+ final ActivityStack mainStack = mRootActivityContainer.getTopDisplayFocusedStack();
// mainStack is null during startup.
if (mainStack != null) {
if (changes != 0 && starting == null) {
@@ -5396,7 +5419,7 @@
false /* preserveWindow */);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
+ mRootActivityContainer.ensureActivitiesVisible(starting, changes,
!PRESERVE_WINDOWS);
}
}
@@ -5612,8 +5635,8 @@
@Override
public ComponentName getHomeActivityForUser(int userId) {
synchronized (mGlobalLock) {
- ActivityRecord homeActivity =
- mStackSupervisor.getDefaultDisplayHomeActivityForUser(userId);
+ final ActivityRecord homeActivity =
+ mRootActivityContainer.getDefaultDisplayHomeActivityForUser(userId);
return homeActivity == null ? null : homeActivity.realActivity;
}
}
@@ -5651,14 +5674,14 @@
@Override
public List<IBinder> getTopVisibleActivities() {
synchronized (mGlobalLock) {
- return mStackSupervisor.getTopVisibleActivities();
+ return mRootActivityContainer.getTopVisibleActivities();
}
}
@Override
public void notifyDockedStackMinimizedChanged(boolean minimized) {
synchronized (mGlobalLock) {
- mStackSupervisor.setDockedStackMinimized(minimized);
+ mRootActivityContainer.setDockedStackMinimized(minimized);
}
}
@@ -5739,7 +5762,7 @@
// We might change the visibilities here, so prepare an empty app transition which
// might be overridden later if we actually change visibilities.
final ActivityDisplay activityDisplay =
- mStackSupervisor.getActivityDisplay(displayId);
+ mRootActivityContainer.getActivityDisplay(displayId);
if (activityDisplay == null) {
return;
}
@@ -5748,7 +5771,7 @@
if (!wasTransitionSet) {
dwc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// If there was a transition set already we don't want to interfere with it as we
// might be starting it too early.
@@ -5765,7 +5788,7 @@
public void notifyKeyguardTrustedChanged() {
synchronized (mGlobalLock) {
if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
}
}
@@ -5792,7 +5815,7 @@
"setFocusedActivity: No activity record matching token=" + token);
}
if (r.moveFocusableActivityToTop("setFocusedActivity")) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -5943,7 +5966,7 @@
public boolean shuttingDown(boolean booted, int timeout) {
synchronized (mGlobalLock) {
mShuttingDown = true;
- mStackSupervisor.prepareForShutdownLocked();
+ mRootActivityContainer.prepareForShutdown();
updateEventDispatchingLocked(booted);
notifyTaskPersisterLocked(null, true);
return mStackSupervisor.shutdownLocked(timeout);
@@ -6050,7 +6073,7 @@
@Override
public void onPackageReplaced(ApplicationInfo aInfo) {
synchronized (mGlobalLock) {
- mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
+ mRootActivityContainer.updateActivityApplicationInfo(aInfo);
}
}
@@ -6080,7 +6103,7 @@
mH.post(() -> {
synchronized (mGlobalLock) {
final ActivityDisplay activityDisplay =
- mStackSupervisor.getActivityDisplay(displayId);
+ mRootActivityContainer.getActivityDisplay(displayId);
if (activityDisplay == null) {
// Call might come when display is not yet added or has been removed.
if (DEBUG_CONFIGURATION) {
@@ -6163,14 +6186,14 @@
@Override
public boolean startHomeActivity(int userId, String reason) {
synchronized (mGlobalLock) {
- return mStackSupervisor.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY);
+ return mRootActivityContainer.startHomeOnDisplay(userId, reason, DEFAULT_DISPLAY);
}
}
@Override
public boolean startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
- return mStackSupervisor.startHomeOnAllDisplays(userId, reason);
+ return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
}
}
@@ -6234,7 +6257,7 @@
Runnable finishInstrumentationCallback) {
synchronized (mGlobalLock) {
// Remove this application's activities from active lists.
- boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(wpc);
+ boolean hasVisibleActivities = mRootActivityContainer.handleAppDied(wpc);
wpc.clearRecentTasks();
wpc.clearActivities();
@@ -6246,12 +6269,12 @@
mWindowManager.deferSurfaceLayout();
try {
if (!restarting && hasVisibleActivities
- && !mStackSupervisor.resumeFocusedStacksTopActivitiesLocked()) {
+ && !mRootActivityContainer.resumeFocusedStacksTopActivities()) {
// If there was nothing to resume, and we are not already restarting this
// process, but there is a visible activity that is hosted by the process...
// then make sure all visible activities are running, taking care of
// restarting this process.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
}
} finally {
mWindowManager.continueSurfaceLayout();
@@ -6280,7 +6303,7 @@
}
mWindowManager.closeSystemDialogs(reason);
- mStackSupervisor.closeSystemDialogsLocked();
+ mRootActivityContainer.closeSystemDialogs();
}
// Call into AM outside the synchronized block.
mAmInternal.broadcastCloseSystemDialogs(reason);
@@ -6294,9 +6317,9 @@
String packageName, Set<String> disabledClasses, int userId, boolean booted) {
synchronized (mGlobalLock) {
// Clean-up disabled activities.
- if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
+ if (mRootActivityContainer.finishDisabledPackageActivities(
packageName, disabledClasses, true, false, userId) && booted) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
mStackSupervisor.scheduleIdleLocked();
}
@@ -6313,7 +6336,7 @@
boolean didSomething =
getActivityStartController().clearPendingActivityLaunches(packageName);
- didSomething |= mStackSupervisor.finishDisabledPackageActivitiesLocked(packageName,
+ didSomething |= mRootActivityContainer.finishDisabledPackageActivities(packageName,
null, doit, evenPersistent, userId);
return didSomething;
}
@@ -6322,7 +6345,7 @@
@Override
public void resumeTopActivities(boolean scheduleIdle) {
synchronized (mGlobalLock) {
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
if (scheduleIdle) {
mStackSupervisor.scheduleIdleLocked();
}
@@ -6339,7 +6362,7 @@
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLock) {
- return mStackSupervisor.attachApplicationLocked(wpc);
+ return mRootActivityContainer.attachApplication(wpc);
}
}
@@ -6361,7 +6384,7 @@
// Showing launcher to avoid user entering credential twice.
startHomeActivity(currentUserId, "notifyLockedProfile");
}
- mStackSupervisor.lockAllProfileTasks(userId);
+ mRootActivityContainer.lockAllProfileTasks(userId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6382,7 +6405,7 @@
ActivityOptions activityOptions = options != null
? new ActivityOptions(options) : ActivityOptions.makeBasic();
final ActivityRecord homeActivity =
- mStackSupervisor.getDefaultDisplayHomeActivity();
+ mRootActivityContainer.getDefaultDisplayHomeActivity();
if (homeActivity != null) {
activityOptions.setLaunchTaskId(homeActivity.getTask().taskId);
}
@@ -6399,7 +6422,7 @@
synchronized (mGlobalLock) {
// The output proto of "activity --proto activities"
// is ActivityManagerServiceDumpActivitiesProto
- mStackSupervisor.writeToProto(proto,
+ mRootActivityContainer.writeToProto(proto,
ActivityManagerServiceDumpActivitiesProto.ACTIVITY_STACK_SUPERVISOR);
}
}
@@ -6494,7 +6517,7 @@
}
if (dumpPackage == null) {
pw.println(" mGlobalConfiguration: " + getGlobalConfiguration());
- mStackSupervisor.dumpDisplayConfigs(pw, " ");
+ mRootActivityContainer.dumpDisplayConfigs(pw, " ");
}
if (dumpAll) {
if (dumpPackage == null) {
@@ -6522,7 +6545,7 @@
if (dumpPackage == null) {
pw.println(" mWakefulness="
+ PowerManagerInternal.wakefulnessToString(wakefulness));
- pw.println(" mSleepTokens=" + mStackSupervisor.mSleepTokens);
+ pw.println(" mSleepTokens=" + mRootActivityContainer.mSleepTokens);
if (mRunningVoice != null) {
pw.println(" mRunningVoice=" + mRunningVoice);
pw.println(" mVoiceWakeLock" + mVoiceWakeLock);
@@ -6649,14 +6672,14 @@
@Override
public boolean canGcNow() {
synchronized (mGlobalLock) {
- return isSleeping() || mStackSupervisor.allResumedActivitiesIdle();
+ return isSleeping() || mRootActivityContainer.allResumedActivitiesIdle();
}
}
@Override
public WindowProcessController getTopApp() {
synchronized (mGlobalLock) {
- final ActivityRecord top = mStackSupervisor.getTopResumedActivity();
+ final ActivityRecord top = mRootActivityContainer.getTopResumedActivity();
return top != null ? top.app : null;
}
}
@@ -6664,8 +6687,8 @@
@Override
public void rankTaskLayersIfNeeded() {
synchronized (mGlobalLock) {
- if (mStackSupervisor != null) {
- mStackSupervisor.rankTaskLayersIfNeeded();
+ if (mRootActivityContainer != null) {
+ mRootActivityContainer.rankTaskLayersIfNeeded();
}
}
}
@@ -6673,35 +6696,35 @@
@Override
public void scheduleDestroyAllActivities(String reason) {
synchronized (mGlobalLock) {
- mStackSupervisor.scheduleDestroyAllActivities(null, reason);
+ mRootActivityContainer.scheduleDestroyAllActivities(null, reason);
}
}
@Override
public void removeUser(int userId) {
synchronized (mGlobalLock) {
- mStackSupervisor.removeUserLocked(userId);
+ mRootActivityContainer.removeUser(userId);
}
}
@Override
public boolean switchUser(int userId, UserState userState) {
synchronized (mGlobalLock) {
- return mStackSupervisor.switchUserLocked(userId, userState);
+ return mRootActivityContainer.switchUser(userId, userState);
}
}
@Override
public void onHandleAppCrash(WindowProcessController wpc) {
synchronized (mGlobalLock) {
- mStackSupervisor.handleAppCrashLocked(wpc);
+ mRootActivityContainer.handleAppCrash(wpc);
}
}
@Override
public int finishTopCrashedActivities(WindowProcessController crashedApp, String reason) {
synchronized (mGlobalLock) {
- return mStackSupervisor.finishTopCrashedActivitiesLocked(crashedApp, reason);
+ return mRootActivityContainer.finishTopCrashedActivities(crashedApp, reason);
}
}
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 04fef02..441c593 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
-import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import android.app.ActivityManager;
import android.app.IAppTask;
@@ -77,7 +77,7 @@
synchronized (mService.mGlobalLock) {
long origId = Binder.clearCallingIdentity();
try {
- TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId,
+ TaskRecord tr = mService.mRootActivityContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
@@ -115,7 +115,7 @@
TaskRecord tr;
IApplicationThread appThread;
synchronized (mService.mGlobalLock) {
- tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId,
+ tr = mService.mRootActivityContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
@@ -143,7 +143,7 @@
synchronized (mService.mGlobalLock) {
long origId = Binder.clearCallingIdentity();
try {
- TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId,
+ TaskRecord tr = mService.mRootActivityContainer.anyTaskForId(mTaskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr == null) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 32a6f74..bf00ffb 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -305,7 +305,7 @@
AppWindowToken wtoken = openingApps.valueAt(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
- if (!wtoken.setVisibility(animLp, true, transit, false, voiceInteraction)) {
+ if (!wtoken.commitVisibility(animLp, true, transit, false, voiceInteraction)) {
// This token isn't going to be animating. Add it to the list of tokens to
// be notified of app transition complete since the notification will not be
// sent be the app window animator.
@@ -341,7 +341,7 @@
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
// TODO: Do we need to add to mNoAnimationNotifyOnTransitionFinished like above if not
// animating?
- wtoken.setVisibility(animLp, false, transit, false, voiceInteraction);
+ wtoken.commitVisibility(animLp, false, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
// Force the allDrawn flag, because we want to start
// this guy's animations regardless of whether it's
@@ -350,9 +350,8 @@
wtoken.deferClearAllDrawn = false;
// Ensure that apps that are mid-starting are also scheduled to have their
// starting windows removed after the animation is complete
- if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit
- && wtoken.getController() != null) {
- wtoken.getController().removeStartingWindow();
+ if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
+ wtoken.removeStartingWindow();
}
if (mDisplayContent.mAppTransition.isNextAppTransitionThumbnailDown()) {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
deleted file mode 100644
index 7fdea10..0000000
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * Copyright (C) 2016 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
- */
-
-package com.android.server.wm;
-
-import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
-import static android.app.ActivityOptions.ANIM_CUSTOM;
-import static android.app.ActivityOptions.ANIM_NONE;
-import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
-import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
-import static android.app.ActivityOptions.ANIM_SCALE_UP;
-import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
-import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
-import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
-import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
-import static android.view.WindowManager.TRANSIT_UNSET;
-
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
-import android.app.ActivityManager.TaskSnapshot;
-import android.app.ActivityOptions;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.res.CompatibilityInfo;
-import android.content.res.Configuration;
-import android.graphics.GraphicBuffer;
-import android.graphics.Rect;
-import android.os.Debug;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Slog;
-import android.view.AppTransitionAnimationSpec;
-import android.view.IAppTransitionAnimationSpecsFuture;
-import android.view.IApplicationToken;
-import android.view.RemoteAnimationDefinition;
-import android.view.WindowManager;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.AttributeCache;
-import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-
-/**
- * Controller for the app window token container. This is created by activity manager to link
- * activity records to the app window token container they use in window manager.
- *
- * Test class: {@link AppWindowContainerControllerTests}
- */
-public class AppWindowContainerController
- extends WindowContainerController<AppWindowToken, AppWindowContainerListener> {
-
- private static final int STARTING_WINDOW_TYPE_NONE = 0;
- private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
- private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
-
- private final IApplicationToken mToken;
- private final Handler mHandler;
-
- private final class H extends Handler {
- public static final int NOTIFY_WINDOWS_DRAWN = 1;
- public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
- public static final int NOTIFY_WINDOWS_NOTDRAWN = 3;
-
- public H(Looper looper) {
- super(looper);
- }
-
- @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(true /* drawn */, msg.getWhen());
- break;
- case NOTIFY_STARTING_WINDOW_DRAWN:
- if (mListener == null) {
- return;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in "
- + AppWindowContainerController.this.mToken);
- mListener.onStartingWindowDrawn(msg.getWhen());
- break;
- case NOTIFY_WINDOWS_NOTDRAWN:
- if (mListener == null) {
- return;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting not drawn in "
- + AppWindowContainerController.this.mToken);
- mListener.onWindowsDrawn(false /* drawn */, msg.getWhen());
- break;
- default:
- break;
- }
- }
- }
-
- private final Runnable mOnWindowsVisible = () -> {
- if (mListener == null) {
- return;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in "
- + AppWindowContainerController.this.mToken);
- mListener.onWindowsVisible();
- };
-
- private final Runnable mOnWindowsGone = () -> {
- if (mListener == null) {
- return;
- }
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in "
- + AppWindowContainerController.this.mToken);
- mListener.onWindowsGone();
- };
-
- private final Runnable mAddStartingWindow = new Runnable() {
-
- @Override
- public void run() {
- final StartingData startingData;
- final AppWindowToken container;
-
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
- + " add starting window");
- return;
- }
-
- // There can only be one adding request, silly caller!
- mService.mAnimationHandler.removeCallbacks(this);
-
- startingData = mContainer.startingData;
- container = mContainer;
- }
-
- if (startingData == null) {
- // Animation has been canceled... do nothing.
- if (DEBUG_STARTING_WINDOW)
- Slog.v(TAG_WM, "startingData was nulled out before handling"
- + " mAddStartingWindow: " + mContainer);
- return;
- }
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting "
- + AppWindowContainerController.this + ": startingData="
- + container.startingData);
-
- StartingSurface surface = null;
- try {
- surface = startingData.createStartingSurface(container);
- } catch (Exception e) {
- Slog.w(TAG_WM, "Exception when adding starting window", e);
- }
- if (surface != null) {
- boolean abort = false;
- synchronized (mGlobalLock) {
- // If the window was successfully added, then
- // we need to remove it.
- if (container.removed || container.startingData == null) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Aborted starting " + container
- + ": removed=" + container.removed
- + " startingData=" + container.startingData);
- container.startingWindow = null;
- container.startingData = null;
- abort = true;
- } else {
- container.startingSurface = surface;
- }
- if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM,
- "Added starting " + mContainer
- + ": startingWindow="
- + container.startingWindow + " startingView="
- + container.startingSurface);
- }
- if (abort) {
- surface.remove();
- }
- } else if (DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
- }
- }
- };
-
- public AppWindowContainerController(TaskWindowContainerController taskController,
- IApplicationToken token, ComponentName activityComponent,
- AppWindowContainerListener listener, int index, int requestedOrientation,
- boolean fullscreen, boolean showForAllUsers, int configChanges,
- boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
- int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
- this(taskController, token, activityComponent, listener, index, requestedOrientation,
- fullscreen, showForAllUsers, configChanges, voiceInteraction, launchTaskBehind,
- alwaysFocusable, targetSdkVersion, rotationAnimationHint,
- inputDispatchingTimeoutNanos, WindowManagerService.getInstance());
- }
-
- public AppWindowContainerController(TaskWindowContainerController taskController,
- IApplicationToken token, ComponentName activityComponent,
- AppWindowContainerListener listener, int index, int requestedOrientation,
- boolean fullscreen, boolean showForAllUsers, int configChanges,
- boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
- int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
- WindowManagerService service) {
- super(listener, service);
- mHandler = new H(service.mH.getLooper());
- mToken = token;
- synchronized (mGlobalLock) {
- AppWindowToken atoken = mRoot.getAppWindowToken(mToken.asBinder());
- if (atoken != null) {
- // TODO: Should this throw an exception instead?
- Slog.w(TAG_WM, "Attempted to add existing app token: " + mToken);
- return;
- }
-
- final Task task = taskController.mContainer;
- if (task == null) {
- throw new IllegalArgumentException("AppWindowContainerController: invalid "
- + " controller=" + taskController);
- }
-
- atoken = createAppWindow(mService, token, activityComponent, voiceInteraction,
- task.getDisplayContent(), inputDispatchingTimeoutNanos, fullscreen,
- showForAllUsers, targetSdkVersion, requestedOrientation, rotationAnimationHint,
- configChanges, launchTaskBehind, alwaysFocusable, this);
- if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
- + " controller=" + taskController + " at " + index);
- task.addChild(atoken, index);
- }
- }
-
- @VisibleForTesting
- AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
- ComponentName component, boolean voiceInteraction, DisplayContent dc,
- long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
- int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
- boolean launchTaskBehind, boolean alwaysFocusable,
- AppWindowContainerController controller) {
- return new AppWindowToken(service, token, component, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
- rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
- controller);
- }
-
- public void removeContainer(int displayId) {
- synchronized (mGlobalLock) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc == null) {
- Slog.w(TAG_WM, "removeAppToken: Attempted to remove binder token: "
- + mToken + " from non-existing displayId=" + displayId);
- return;
- }
- dc.removeAppToken(mToken.asBinder());
- super.removeContainer();
- }
- }
-
- @Override
- public void removeContainer() {
- throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
- }
-
- public void reparent(TaskWindowContainerController taskController, int position) {
- synchronized (mGlobalLock) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM, "reparent: moving app token=" + mToken
- + " to task=" + taskController + " at " + position);
- if (mContainer == null) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM,
- "reparent: could not find app token=" + mToken);
- return;
- }
- final Task task = taskController.mContainer;
- if (task == null) {
- throw new IllegalArgumentException("reparent: could not find task="
- + taskController);
- }
- mContainer.reparent(task, position);
- mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
- }
-
- public Configuration setOrientation(int requestedOrientation, int displayId,
- Configuration displayConfig, boolean freezeScreenIfNeeded) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM,
- "Attempted to set orientation of non-existing app token: " + mToken);
- return null;
- }
-
- mContainer.setOrientation(requestedOrientation);
-
- final IBinder binder = freezeScreenIfNeeded ? mToken.asBinder() : null;
- return mService.updateOrientationFromAppTokens(displayConfig, binder, displayId);
-
- }
- }
-
- public int getOrientation() {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- return SCREEN_ORIENTATION_UNSPECIFIED;
- }
-
- return mContainer.getOrientationIgnoreVisibility();
- }
- }
-
- public void setDisablePreviewScreenshots(boolean disable) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
- + " token: " + mToken);
- return;
- }
- mContainer.setDisablePreviewScreenshots(disable);
- }
- }
-
- public void setVisibility(boolean visible, boolean deferHidingClient) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
- + mToken);
- return;
- }
-
- final AppWindowToken wtoken = mContainer;
- final AppTransition appTransition = mContainer.getDisplayContent().mAppTransition;
-
- // Don't set visibility to false if we were already not visible. This prevents WM from
- // adding the app to the closing app list which doesn't make sense for something that is
- // already not visible. However, set visibility to true even if we are already visible.
- // This makes sure the app is added to the opening apps list so that the right
- // transition can be selected.
- // TODO: Probably a good idea to separate the concept of opening/closing apps from the
- // concept of setting visibility...
- if (!visible && wtoken.hiddenRequested) {
-
- if (!deferHidingClient && wtoken.mDeferHidingClient) {
- // We previously deferred telling the client to hide itself when visibility was
- // initially set to false. Now we would like it to hide, so go ahead and set it.
- wtoken.mDeferHidingClient = deferHidingClient;
- wtoken.setClientHidden(true);
- }
- return;
- }
-
- if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
- + mToken + ", visible=" + visible + "): " + appTransition
- + " hidden=" + wtoken.isHidden() + " hiddenRequested="
- + wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
-
- final DisplayContent displayContent = mContainer.getDisplayContent();
- displayContent.mOpeningApps.remove(wtoken);
- displayContent.mClosingApps.remove(wtoken);
- wtoken.waitingToShow = false;
- wtoken.hiddenRequested = !visible;
- wtoken.mDeferHidingClient = deferHidingClient;
-
- if (!visible) {
- // If the app is dead while it was visible, we kept its dead window on screen.
- // Now that the app is going invisible, we can remove it. It will be restarted
- // if made visible again.
- wtoken.removeDeadWindows();
- } else {
- if (!appTransition.isTransitionSet()
- && appTransition.isReady()) {
- // Add the app mOpeningApps if transition is unset but ready. This means
- // we're doing a screen freeze, and the unfreeze will wait for all opening
- // apps to be ready.
- displayContent.mOpeningApps.add(wtoken);
- }
- wtoken.startingMoved = false;
- // If the token is currently hidden (should be the common case), or has been
- // stopped, then we need to set up to wait for its windows to be ready.
- if (wtoken.isHidden() || wtoken.mAppStopped) {
- wtoken.clearAllDrawn();
-
- // If the app was already visible, don't reset the waitingToShow state.
- if (wtoken.isHidden()) {
- wtoken.waitingToShow = true;
- }
- }
-
- // In the case where we are making an app visible but holding off for a transition,
- // we still need to tell the client to make its windows visible so they get drawn.
- // Otherwise, we will wait on performing the transition until all windows have been
- // drawn, they never will be, and we are sad.
- wtoken.setClientHidden(false);
-
- wtoken.requestUpdateWallpaperIfNeeded();
-
- if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + wtoken);
- wtoken.mAppStopped = false;
-
- mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
- }
-
- // If we are preparing an app transition, then delay changing
- // the visibility of this token until we execute that transition.
- if (wtoken.okToAnimate() && appTransition.isTransitionSet()) {
- wtoken.inPendingTransaction = true;
- if (visible) {
- displayContent.mOpeningApps.add(wtoken);
- wtoken.mEnteringAnimation = true;
- } else {
- displayContent.mClosingApps.add(wtoken);
- wtoken.mEnteringAnimation = false;
- }
- if (appTransition.getAppTransition()
- == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
- // We're launchingBehind, add the launching activity to mOpeningApps.
- final WindowState win = mContainer.getDisplayContent().findFocusedWindow();
- if (win != null) {
- final AppWindowToken focusedToken = win.mAppToken;
- if (focusedToken != null) {
- if (DEBUG_APP_TRANSITIONS) Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
- + " adding " + focusedToken + " to mOpeningApps");
- // Force animation to be loaded.
- focusedToken.setHidden(true);
- displayContent.mOpeningApps.add(focusedToken);
- }
- }
- }
- return;
- }
-
- wtoken.setVisibility(null, visible, TRANSIT_UNSET, true, wtoken.mVoiceInteraction);
- wtoken.updateReportedVisibilityLocked();
- }
- }
-
- /**
- * Notifies that we launched an app that might be visible or not visible depending on what kind
- * of Keyguard flags it's going to set on its windows.
- */
- public void notifyUnknownVisibilityLaunched() {
- synchronized (mGlobalLock) {
- if (mContainer != null) {
- mContainer.getDisplayContent().mUnknownAppVisibilityController.notifyLaunched(
- mContainer);
- }
- }
- }
-
- public boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
- CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
- IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
- synchronized (mGlobalLock) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
- + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
- + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
- + " allowTaskSnapshot=" + allowTaskSnapshot);
-
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
- return false;
- }
-
- // If the display is frozen, we won't do anything until the actual window is
- // displayed so there is no reason to put in the starting window.
- if (!mContainer.okToDisplay()) {
- return false;
- }
-
- if (mContainer.startingData != null) {
- return false;
- }
-
- final WindowState mainWin = mContainer.findMainWindow();
- if (mainWin != null && mainWin.mWinAnimator.getShown()) {
- // App already has a visible window...why would you want a starting window?
- return false;
- }
-
- final TaskSnapshot snapshot = mService.mTaskSnapshotController.getSnapshot(
- mContainer.getTask().mTaskId, mContainer.getTask().mUserId,
- false /* restoreFromDisk */, false /* reducedResolution */);
- final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
- allowTaskSnapshot, activityCreated, fromRecents, snapshot);
-
- if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
- return createSnapshot(snapshot);
- }
-
- // If this is a translucent window, then don't show a starting window -- the current
- // effect (a full-screen opaque starting window that fades away to the real contents
- // when it is ready) does not work for this.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Checking theme of starting window: 0x"
- + Integer.toHexString(theme));
- if (theme != 0) {
- AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
- com.android.internal.R.styleable.Window, mService.mCurrentUserId);
- if (ent == null) {
- // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
- // see that.
- return false;
- }
- final boolean windowIsTranslucent = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsTranslucent, false);
- final boolean windowIsFloating = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowIsFloating, false);
- final boolean windowShowWallpaper = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowShowWallpaper, false);
- final boolean windowDisableStarting = ent.array.getBoolean(
- com.android.internal.R.styleable.Window_windowDisablePreview, false);
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Translucent=" + windowIsTranslucent
- + " Floating=" + windowIsFloating
- + " ShowWallpaper=" + windowShowWallpaper);
- if (windowIsTranslucent) {
- return false;
- }
- if (windowIsFloating || windowDisableStarting) {
- return false;
- }
- if (windowShowWallpaper) {
- if (mContainer.getDisplayContent().mWallpaperController.getWallpaperTarget()
- == null) {
- // If this theme is requesting a wallpaper, and the wallpaper
- // is not currently visible, then this effectively serves as
- // an opaque window and our starting window transition animation
- // can still work. We just need to make sure the starting window
- // is also showing the wallpaper.
- windowFlags |= FLAG_SHOW_WALLPAPER;
- } else {
- return false;
- }
- }
- }
-
- if (mContainer.transferStartingWindow(transferFrom)) {
- return true;
- }
-
- // There is no existing starting window, and we don't want to create a splash screen, so
- // that's it!
- if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
- return false;
- }
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
- mContainer.startingData = new SplashScreenStartingData(mService, pkg, theme,
- compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- mContainer.getMergedOverrideConfiguration());
- scheduleAddStartingWindow();
- }
- return true;
- }
-
- private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
- TaskSnapshot snapshot) {
- if (mContainer.getDisplayContent().mAppTransition.getAppTransition()
- == TRANSIT_DOCK_TASK_FROM_RECENTS) {
- // TODO(b/34099271): Remove this statement to add back the starting window and figure
- // out why it causes flickering, the starting window appears over the thumbnail while
- // the docked from recents transition occurs
- return STARTING_WINDOW_TYPE_NONE;
- } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
- return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
- } else if (taskSwitch && allowTaskSnapshot) {
- return snapshot == null ? STARTING_WINDOW_TYPE_NONE
- : snapshotOrientationSameAsTask(snapshot) || fromRecents
- ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
- } else {
- return STARTING_WINDOW_TYPE_NONE;
- }
- }
-
- void scheduleAddStartingWindow() {
- // Note: we really want to do sendMessageAtFrontOfQueue() because we
- // want to process the message ASAP, before any other queued
- // messages.
- if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING");
- mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
- }
- }
-
- private boolean createSnapshot(TaskSnapshot snapshot) {
- if (snapshot == null) {
- return false;
- }
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
- mContainer.startingData = new SnapshotStartingData(mService, snapshot);
- scheduleAddStartingWindow();
- return true;
- }
-
- private boolean snapshotOrientationSameAsTask(TaskSnapshot snapshot) {
- if (snapshot == null) {
- return false;
- }
- return mContainer.getTask().getConfiguration().orientation == snapshot.getOrientation();
- }
-
- public void removeStartingWindow() {
- synchronized (mGlobalLock) {
- if (mContainer.startingWindow == null) {
- if (mContainer.startingData != null) {
- // Starting window has not been added yet, but it is scheduled to be added.
- // Go ahead and cancel the request.
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
- "Clearing startingData for token=" + mContainer);
- mContainer.startingData = null;
- }
- return;
- }
-
- final StartingSurface surface;
- if (mContainer.startingData != null) {
- surface = mContainer.startingSurface;
- mContainer.startingData = null;
- mContainer.startingSurface = null;
- mContainer.startingWindow = null;
- mContainer.startingDisplayed = false;
- if (surface == null) {
- if (DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
- + "remove");
- }
- return;
- }
- } else {
- if (DEBUG_STARTING_WINDOW) {
- Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
- + mContainer);
- }
- return;
- }
-
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Schedule remove starting " + mContainer
- + " startingWindow=" + mContainer.startingWindow
- + " startingView=" + mContainer.startingSurface
- + " Callers=" + Debug.getCallers(5));
-
- // Use the same thread to remove the window as we used to add it, as otherwise we end up
- // with things in the view hierarchy being called from different threads.
- mService.mAnimationHandler.post(() -> {
- if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
- try {
- surface.remove();
- } catch (Exception e) {
- Slog.w(TAG_WM, "Exception when removing starting window", e);
- }
- });
- }
- }
-
- public void pauseKeyDispatching() {
- synchronized (mGlobalLock) {
- if (mContainer != null) {
- mContainer.getDisplayContent().getInputMonitor().pauseDispatchingLw(mContainer);
- }
- }
- }
-
- public void resumeKeyDispatching() {
- synchronized (mGlobalLock) {
- if (mContainer != null) {
- mContainer.getDisplayContent().getInputMonitor().resumeDispatchingLw(mContainer);
- }
- }
- }
-
- public void notifyAppResumed(boolean wasStopped) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: " + mToken);
- return;
- }
- mContainer.notifyAppResumed(wasStopped);
- }
- }
-
- public void notifyAppStopping() {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
- + mToken);
- return;
- }
- mContainer.detachChildren();
- }
- }
-
- public void notifyAppStopped() {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to notify stopped of non-existing app token: "
- + mToken);
- return;
- }
- mContainer.notifyAppStopped();
- }
- }
-
- public void startFreezingScreen(int configChanges) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM,
- "Attempted to freeze screen with non-existing app token: " + mContainer);
- return;
- }
-
- if (configChanges == 0 && mContainer.okToDisplay()) {
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + mToken);
- return;
- }
-
- mContainer.startFreezingScreen();
- }
- }
-
- public void stopFreezingScreen(boolean force) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- return;
- }
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden="
- + mContainer.isHidden() + " freezing=" + mContainer.isFreezingScreen());
- mContainer.stopFreezingScreen(true, force);
- }
- }
-
- public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
- + " token: " + mToken);
- return;
- }
- mContainer.registerRemoteAnimations(definition);
- }
- }
-
- void reportStartingWindowDrawn() {
- mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_STARTING_WINDOW_DRAWN));
- }
-
- void reportWindowsDrawn() {
- mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
- }
-
- void reportWindowsNotDrawn() {
- mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN));
- }
-
- void reportWindowsVisible() {
- mHandler.post(mOnWindowsVisible);
- }
-
- void reportWindowsGone() {
- mHandler.post(mOnWindowsGone);
- }
-
- /** Calls directly into activity manager so window manager lock shouldn't held. */
- boolean keyDispatchingTimedOut(String reason, int windowPid) {
- return mListener != null && mListener.keyDispatchingTimedOut(reason, windowPid);
- }
-
- /**
- * Apply override app transition base on options & animation type.
- */
- public void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
- synchronized (mGlobalLock) {
- final int animationType = pendingOptions.getAnimationType();
- final DisplayContent displayContent = mContainer.getDisplayContent();
- switch (animationType) {
- case ANIM_CUSTOM:
- displayContent.mAppTransition.overridePendingAppTransition(
- pendingOptions.getPackageName(),
- pendingOptions.getCustomEnterResId(),
- pendingOptions.getCustomExitResId(),
- pendingOptions.getOnAnimationStartListener());
- break;
- case ANIM_CLIP_REVEAL:
- displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight());
- if (intent.getSourceBounds() == null) {
- intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
- pendingOptions.getStartY(),
- pendingOptions.getStartX() + pendingOptions.getWidth(),
- pendingOptions.getStartY() + pendingOptions.getHeight()));
- }
- break;
- case ANIM_SCALE_UP:
- displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight());
- if (intent.getSourceBounds() == null) {
- intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
- pendingOptions.getStartY(),
- pendingOptions.getStartX() + pendingOptions.getWidth(),
- pendingOptions.getStartY() + pendingOptions.getHeight()));
- }
- break;
- case ANIM_THUMBNAIL_SCALE_UP:
- case ANIM_THUMBNAIL_SCALE_DOWN:
- final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
- final GraphicBuffer buffer = pendingOptions.getThumbnail();
- displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getOnAnimationStartListener(),
- scaleUp);
- if (intent.getSourceBounds() == null && buffer != null) {
- intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
- pendingOptions.getStartY(),
- pendingOptions.getStartX() + buffer.getWidth(),
- pendingOptions.getStartY() + buffer.getHeight()));
- }
- break;
- case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
- case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
- final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
- final IAppTransitionAnimationSpecsFuture specsFuture =
- pendingOptions.getSpecsFuture();
- if (specsFuture != null) {
- displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
- specsFuture, pendingOptions.getOnAnimationStartListener(),
- animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
- } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
- && specs != null) {
- displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
- specs, pendingOptions.getOnAnimationStartListener(),
- pendingOptions.getAnimationFinishedListener(), false);
- } else {
- displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
- pendingOptions.getThumbnail(),
- pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getWidth(), pendingOptions.getHeight(),
- pendingOptions.getOnAnimationStartListener(),
- (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
- if (intent.getSourceBounds() == null) {
- intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
- pendingOptions.getStartY(),
- pendingOptions.getStartX() + pendingOptions.getWidth(),
- pendingOptions.getStartY() + pendingOptions.getHeight()));
- }
- }
- break;
- case ANIM_OPEN_CROSS_PROFILE_APPS:
- displayContent.mAppTransition
- .overridePendingAppTransitionStartCrossProfileApps();
- break;
- case ANIM_REMOTE_ANIMATION:
- displayContent.mAppTransition.overridePendingAppTransitionRemote(
- pendingOptions.getRemoteAnimationAdapter());
- break;
- case ANIM_NONE:
- break;
- default:
- Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
- break;
- }
- }
- }
-
- /**
- * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
- * This information helps AWT know that the app is in the process of pausing before it gets the
- * signal on the WM side.
- */
- public void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
- synchronized (mGlobalLock) {
- if (mContainer == null) {
- return;
- }
-
- mContainer.setWillCloseOrEnterPip(willCloseOrEnterPip);
- }
- }
-
- @Override
- public String toString() {
- return "AppWindowContainerController{"
- + " token=" + mToken
- + " mContainer=" + mContainer
- + " mListener=" + mListener
- + "}";
- }
-}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
deleted file mode 100644
index ad27669..0000000
--- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2016 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
- */
-
-package com.android.server.wm;
-
-/** 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 drawn state changes. */
- void onWindowsDrawn(boolean drawn, 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. */
- void onWindowsGone();
-
- /**
- * Called when the starting window for this container is drawn.
- */
- void onStartingWindowDrawn(long timestamp);
-
- /**
- * Called when the key dispatching to a window associated with the app window container
- * timed-out.
- *
- * @param reason The reason for the key dispatching time out.
- * @param windowPid The pid of the window key dispatching timed out on.
- * @return True if input dispatching should be aborted.
- */
- boolean keyDispatchingTimedOut(String reason, int windowPid);
-}
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 729f89b..b9b9d31 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -16,13 +16,13 @@
package com.android.server.wm;
+import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
+import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
-import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
-import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
-import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
@@ -65,7 +65,7 @@
// this to the task.
mSurfaceControl = appToken.makeSurface()
.setName("thumbnail anim: " + appToken.toString())
- .setSize(mWidth, mHeight)
+ .setBufferSize(mWidth, mHeight)
.setFormat(PixelFormat.TRANSLUCENT)
.setMetadata(appToken.windowType,
window != null ? window.mOwnerUid : Binder.getCallingUid())
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 52c78ce..df81c07 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -28,10 +28,12 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static android.view.WindowManager.TRANSIT_UNSET;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
@@ -81,7 +83,9 @@
import android.annotation.CallSuper;
import android.app.Activity;
+import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
@@ -90,6 +94,7 @@
import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -106,6 +111,8 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
+import com.android.server.AttributeCache;
+import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
import com.android.server.wm.WindowManagerService.H;
@@ -121,7 +128,8 @@
* Version of WindowToken that is specifically for a particular application (or
* really activity) that is displaying windows.
*/
-class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener {
+class AppWindowToken extends WindowToken implements WindowManagerService.AppFreezeListener,
+ ConfigurationContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowToken" : TAG_WM;
/**
@@ -226,6 +234,9 @@
private Task mLastParent;
+ // TODO: Remove after unification
+ ActivityRecord mActivityRecord;
+
/**
* See {@link #canTurnScreenOn()}
*/
@@ -273,14 +284,20 @@
/** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
boolean mNeedsAnimationBoundsLayer;
+ private static final int STARTING_WINDOW_TYPE_NONE = 0;
+ private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
+ private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
+
AppWindowToken(WindowManagerService service, IApplicationToken token,
ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
boolean launchTaskBehind, boolean alwaysFocusable,
- AppWindowContainerController controller) {
+ ActivityRecord activityRecord) {
this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
- setController(controller);
+ // TODO: remove after unification
+ mActivityRecord = activityRecord;
+ mActivityRecord.registerConfigurationChangeListener(this);
mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
mShowForAllUsers = showForAllUsers;
mTargetSdk = targetSdk;
@@ -304,7 +321,7 @@
mActivityComponent = activityComponent;
mVoiceInteraction = voiceInteraction;
mFillsParent = fillsParent;
- mInputApplicationHandle = new InputApplicationHandle(this);
+ mInputApplicationHandle = new InputApplicationHandle(appToken.asBinder());
}
void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
@@ -320,9 +337,7 @@
// it from behind the starting window, so there is no need for it to also be doing its
// own stuff.
win.cancelAnimation();
- if (getController() != null) {
- getController().removeStartingWindow();
- }
+ removeStartingWindow();
}
updateReportedVisibilityLocked();
}
@@ -360,16 +375,9 @@
}
if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
+ numInteresting + " visible=" + numVisible);
- final AppWindowContainerController controller = getController();
if (nowDrawn != reportedDrawn) {
- if (nowDrawn) {
- if (controller != null) {
- controller.reportWindowsDrawn();
- }
- } else {
- if (controller != null) {
- controller.reportWindowsNotDrawn();
- }
+ if (mActivityRecord != null) {
+ mActivityRecord.onWindowsDrawn(nowDrawn, SystemClock.uptimeMillis());
}
reportedDrawn = nowDrawn;
}
@@ -377,16 +385,36 @@
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Visibility changed in " + this + ": vis=" + nowVisible);
reportedVisible = nowVisible;
- if (controller != null) {
+ if (mActivityRecord != null) {
if (nowVisible) {
- controller.reportWindowsVisible();
+ onWindowsVisible();
} else {
- controller.reportWindowsGone();
+ onWindowsGone();
}
}
}
}
+ private void onWindowsGone() {
+ if (mActivityRecord == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_WM, "Reporting gone in " + mActivityRecord.appToken);
+ }
+ mActivityRecord.onWindowsGone();
+ }
+
+ private void onWindowsVisible() {
+ if (mActivityRecord == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) {
+ Slog.v(TAG_WM, "Reporting visible in " + mActivityRecord.appToken);
+ }
+ mActivityRecord.onWindowsVisible();
+ }
+
boolean isClientHidden() {
return mClientHidden;
}
@@ -401,7 +429,116 @@
sendAppVisibilityToClients();
}
- boolean setVisibility(WindowManager.LayoutParams lp,
+ void setVisibility(boolean visible, boolean deferHidingClient) {
+ final AppTransition appTransition = getDisplayContent().mAppTransition;
+
+ // Don't set visibility to false if we were already not visible. This prevents WM from
+ // adding the app to the closing app list which doesn't make sense for something that is
+ // already not visible. However, set visibility to true even if we are already visible.
+ // This makes sure the app is added to the opening apps list so that the right
+ // transition can be selected.
+ // TODO: Probably a good idea to separate the concept of opening/closing apps from the
+ // concept of setting visibility...
+ if (!visible && hiddenRequested) {
+
+ if (!deferHidingClient && mDeferHidingClient) {
+ // We previously deferred telling the client to hide itself when visibility was
+ // initially set to false. Now we would like it to hide, so go ahead and set it.
+ mDeferHidingClient = deferHidingClient;
+ setClientHidden(true);
+ }
+ return;
+ }
+
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
+ Slog.v(TAG_WM, "setAppVisibility("
+ + appToken + ", visible=" + visible + "): " + appTransition
+ + " hidden=" + isHidden() + " hiddenRequested="
+ + hiddenRequested + " Callers=" + Debug.getCallers(6));
+ }
+
+ final DisplayContent displayContent = getDisplayContent();
+ displayContent.mOpeningApps.remove(this);
+ displayContent.mClosingApps.remove(this);
+ waitingToShow = false;
+ hiddenRequested = !visible;
+ mDeferHidingClient = deferHidingClient;
+
+ if (!visible) {
+ // If the app is dead while it was visible, we kept its dead window on screen.
+ // Now that the app is going invisible, we can remove it. It will be restarted
+ // if made visible again.
+ removeDeadWindows();
+ } else {
+ if (!appTransition.isTransitionSet()
+ && appTransition.isReady()) {
+ // Add the app mOpeningApps if transition is unset but ready. This means
+ // we're doing a screen freeze, and the unfreeze will wait for all opening
+ // apps to be ready.
+ displayContent.mOpeningApps.add(this);
+ }
+ startingMoved = false;
+ // If the token is currently hidden (should be the common case), or has been
+ // stopped, then we need to set up to wait for its windows to be ready.
+ if (isHidden() || mAppStopped) {
+ clearAllDrawn();
+
+ // If the app was already visible, don't reset the waitingToShow state.
+ if (isHidden()) {
+ waitingToShow = true;
+ }
+ }
+
+ // In the case where we are making an app visible but holding off for a transition,
+ // we still need to tell the client to make its windows visible so they get drawn.
+ // Otherwise, we will wait on performing the transition until all windows have been
+ // drawn, they never will be, and we are sad.
+ setClientHidden(false);
+
+ requestUpdateWallpaperIfNeeded();
+
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "No longer Stopped: " + this);
+ mAppStopped = false;
+
+ transferStartingWindowFromHiddenAboveTokenIfNeeded();
+ }
+
+ // If we are preparing an app transition, then delay changing
+ // the visibility of this token until we execute that transition.
+ if (okToAnimate() && appTransition.isTransitionSet()) {
+ inPendingTransaction = true;
+ if (visible) {
+ displayContent.mOpeningApps.add(this);
+ mEnteringAnimation = true;
+ } else {
+ displayContent.mClosingApps.add(this);
+ mEnteringAnimation = false;
+ }
+ if (appTransition.getAppTransition()
+ == WindowManager.TRANSIT_TASK_OPEN_BEHIND) {
+ // We're launchingBehind, add the launching activity to mOpeningApps.
+ final WindowState win = getDisplayContent().findFocusedWindow();
+ if (win != null) {
+ final AppWindowToken focusedToken = win.mAppToken;
+ if (focusedToken != null) {
+ if (DEBUG_APP_TRANSITIONS) {
+ Slog.d(TAG_WM, "TRANSIT_TASK_OPEN_BEHIND, "
+ + " adding " + focusedToken + " to mOpeningApps");
+ }
+ // Force animation to be loaded.
+ focusedToken.setHidden(true);
+ displayContent.mOpeningApps.add(focusedToken);
+ }
+ }
+ }
+ return;
+ }
+
+ commitVisibility(null, visible, TRANSIT_UNSET, true, mVoiceInteraction);
+ updateReportedVisibilityLocked();
+ }
+
+ boolean commitVisibility(WindowManager.LayoutParams lp,
boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
boolean delayed = false;
@@ -461,8 +598,10 @@
forAllWindows(mService::makeWindowFreezingScreenIfNeededLocked, true);
}
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "setVisibility: " + this
- + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
+ if (DEBUG_APP_TRANSITIONS) {
+ Slog.v(TAG_WM, "commitVisibility: " + this
+ + ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
+ }
if (changed) {
getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
@@ -499,10 +638,9 @@
mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
}
- // If we're becoming visible, immediately change client visibility as well although it
- // usually gets changed in AppWindowContainerController.setVisibility already. However,
- // there seem to be some edge cases where we change our visibility but client visibility
- // never gets updated.
+ // If we're becoming visible, immediately change client visibility as well. there seem
+ // to be some edge cases where we change our visibility but client visibility never gets
+ // updated.
// If we're becoming invisible, update the client visibility if we are not running an
// animation. Otherwise, we'll update client visibility in onAnimationFinished.
if (visible || !isReallyAnimating()) {
@@ -596,11 +734,6 @@
return getWindowConfiguration().canReceiveKeys() || mAlwaysFocusable;
}
- AppWindowContainerController getController() {
- final WindowContainerController controller = super.getController();
- return controller != null ? (AppWindowContainerController) controller : null;
- }
-
@Override
boolean isVisible() {
// If the app token isn't hidden then it is considered visible and there is no need to check
@@ -637,7 +770,7 @@
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this);
- boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
+ boolean delayed = commitVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
getDisplayContent().mOpeningApps.remove(this);
getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
@@ -656,8 +789,8 @@
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: "
+ this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
- if (startingData != null && getController() != null) {
- getController().removeStartingWindow();
+ if (startingData != null) {
+ removeStartingWindow();
}
// If this window was animating, then we need to ensure that the app transition notifies
@@ -768,9 +901,7 @@
mAppStopped = true;
destroySurfaces();
// Remove any starting window that was added for this app if they are still around.
- if (getController() != null) {
- getController().removeStartingWindow();
- }
+ removeStartingWindow();
}
void clearAllDrawn() {
@@ -826,9 +957,7 @@
// TODO: Something smells about the code below...Is there a better way?
if (startingWindow == win) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win);
- if (getController() != null) {
- getController().removeStartingWindow();
- }
+ removeStartingWindow();
} else if (mChildren.size() == 0) {
// If this is the last window and we had requested a starting transition window,
// well there is no point now.
@@ -845,9 +974,7 @@
// we need to get rid of the starting transition.
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
+ win);
- if (getController() != null) {
- getController().removeStartingWindow();
- }
+ removeStartingWindow();
}
}
@@ -1021,6 +1148,10 @@
@Override
void removeChild(WindowState child) {
+ if (!mChildren.contains(child)) {
+ // This can be true when testing.
+ return;
+ }
super.removeChild(child);
checkKeyguardFlagsChanged();
updateLetterboxSurface(child);
@@ -1042,6 +1173,20 @@
}
}
+ void reparent(TaskWindowContainerController taskController, int position) {
+ if (DEBUG_ADD_REMOVE) {
+ Slog.i(TAG_WM, "reparent: moving app token=" + this
+ + " to task=" + taskController + " at " + position);
+ }
+ final Task task = taskController.mContainer;
+ if (task == null) {
+ throw new IllegalArgumentException("reparent: could not find task="
+ + taskController);
+ }
+ reparent(task, position);
+ getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ }
+
void reparent(Task task, int position) {
final Task currentTask = getTask();
if (task == currentTask) {
@@ -1300,9 +1445,7 @@
startingData = fromToken.startingData;
fromToken.startingData = null;
fromToken.startingMoved = true;
- if (getController() != null) {
- getController().scheduleAddStartingWindow();
- }
+ scheduleAddStartingWindow();
return true;
}
@@ -1471,6 +1614,10 @@
}
}
+ boolean keyDispatchingTimedOut(String reason, int windowPid) {
+ return mActivityRecord != null && mActivityRecord.keyDispatchingTimedOut(reason, windowPid);
+ }
+
/**
* Updated this app token tracking states for interesting and drawn windows based on the window.
*
@@ -1533,8 +1680,8 @@
}
}
} else if (w.isDrawnLw()) {
- if (getController() != null) {
- getController().reportStartingWindowDrawn();
+ if (mActivityRecord != null) {
+ mActivityRecord.onStartingWindowDrawn(SystemClock.uptimeMillis());
}
startingDisplayed = true;
}
@@ -1601,6 +1748,266 @@
return this;
}
+ boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
+ CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
+ IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
+ // If the display is frozen, we won't do anything until the actual window is
+ // displayed so there is no reason to put in the starting window.
+ if (!okToDisplay()) {
+ return false;
+ }
+
+ if (startingData != null) {
+ return false;
+ }
+
+ final WindowState mainWin = findMainWindow();
+ if (mainWin != null && mainWin.mWinAnimator.getShown()) {
+ // App already has a visible window...why would you want a starting window?
+ return false;
+ }
+
+ final ActivityManager.TaskSnapshot snapshot =
+ mService.mTaskSnapshotController.getSnapshot(
+ getTask().mTaskId, getTask().mUserId,
+ false /* restoreFromDisk */, false /* reducedResolution */);
+ final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
+ allowTaskSnapshot, activityCreated, fromRecents, snapshot);
+
+ if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
+ return createSnapshot(snapshot);
+ }
+
+ // If this is a translucent window, then don't show a starting window -- the current
+ // effect (a full-screen opaque starting window that fades away to the real contents
+ // when it is ready) does not work for this.
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "Checking theme of starting window: 0x" + Integer.toHexString(theme));
+ }
+ if (theme != 0) {
+ AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
+ com.android.internal.R.styleable.Window,
+ mService.mCurrentUserId);
+ if (ent == null) {
+ // Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
+ // see that.
+ return false;
+ }
+ final boolean windowIsTranslucent = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+ final boolean windowIsFloating = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsFloating, false);
+ final boolean windowShowWallpaper = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowShowWallpaper, false);
+ final boolean windowDisableStarting = ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowDisablePreview, false);
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "Translucent=" + windowIsTranslucent
+ + " Floating=" + windowIsFloating
+ + " ShowWallpaper=" + windowShowWallpaper);
+ }
+ if (windowIsTranslucent) {
+ return false;
+ }
+ if (windowIsFloating || windowDisableStarting) {
+ return false;
+ }
+ if (windowShowWallpaper) {
+ if (getDisplayContent().mWallpaperController
+ .getWallpaperTarget() == null) {
+ // If this theme is requesting a wallpaper, and the wallpaper
+ // is not currently visible, then this effectively serves as
+ // an opaque window and our starting window transition animation
+ // can still work. We just need to make sure the starting window
+ // is also showing the wallpaper.
+ windowFlags |= FLAG_SHOW_WALLPAPER;
+ } else {
+ return false;
+ }
+ }
+
+ if (transferStartingWindow(transferFrom)) {
+ return true;
+ }
+
+ // There is no existing starting window, and we don't want to create a splash screen, so
+ // that's it!
+ if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+ return false;
+ }
+
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
+ startingData = new SplashScreenStartingData(mService, pkg,
+ theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
+ getMergedOverrideConfiguration());
+ scheduleAddStartingWindow();
+ }
+ return true;
+ }
+
+
+ private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
+ if (snapshot == null) {
+ return false;
+ }
+
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
+ startingData = new SnapshotStartingData(mService, snapshot);
+ scheduleAddStartingWindow();
+ return true;
+ }
+
+ void scheduleAddStartingWindow() {
+ // Note: we really want to do sendMessageAtFrontOfQueue() because we
+ // want to process the message ASAP, before any other queued
+ // messages.
+ if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
+ mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+ }
+ }
+
+ private final Runnable mAddStartingWindow = new Runnable() {
+
+ @Override
+ public void run() {
+ synchronized (mService.mGlobalLock) {
+ // There can only be one adding request, silly caller!
+ mService.mAnimationHandler.removeCallbacks(this);
+ }
+
+ if (startingData == null) {
+ // Animation has been canceled... do nothing.
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "startingData was nulled out before handling"
+ + " mAddStartingWindow: " + AppWindowToken.this);
+ }
+ return;
+ }
+
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "Add starting " + this + ": startingData=" + startingData);
+ }
+
+ WindowManagerPolicy.StartingSurface surface = null;
+ try {
+ surface = startingData.createStartingSurface(AppWindowToken.this);
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception when adding starting window", e);
+ }
+ if (surface != null) {
+ boolean abort = false;
+ synchronized (mService.mGlobalLock) {
+ // If the window was successfully added, then
+ // we need to remove it.
+ if (removed || startingData == null) {
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "Aborted starting " + AppWindowToken.this
+ + ": removed=" + removed + " startingData=" + startingData);
+ }
+ startingWindow = null;
+ startingData = null;
+ abort = true;
+ } else {
+ startingSurface = surface;
+ }
+ if (DEBUG_STARTING_WINDOW && !abort) {
+ Slog.v(TAG, "Added starting " + AppWindowToken.this + ": startingWindow="
+ + startingWindow + " startingView=" + startingSurface);
+ }
+ }
+ if (abort) {
+ surface.remove();
+ }
+ } else if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG, "Surface returned was null: " + AppWindowToken.this);
+ }
+ }
+ };
+
+ private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents,
+ ActivityManager.TaskSnapshot snapshot) {
+ if (getDisplayContent().mAppTransition.getAppTransition()
+ == TRANSIT_DOCK_TASK_FROM_RECENTS) {
+ // TODO(b/34099271): Remove this statement to add back the starting window and figure
+ // out why it causes flickering, the starting window appears over the thumbnail while
+ // the docked from recents transition occurs
+ return STARTING_WINDOW_TYPE_NONE;
+ } else if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+ return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ } else if (taskSwitch && allowTaskSnapshot) {
+ return snapshot == null ? STARTING_WINDOW_TYPE_NONE
+ : snapshotOrientationSameAsTask(snapshot) || fromRecents
+ ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ } else {
+ return STARTING_WINDOW_TYPE_NONE;
+ }
+ }
+
+
+ private boolean snapshotOrientationSameAsTask(ActivityManager.TaskSnapshot snapshot) {
+ if (snapshot == null) {
+ return false;
+ }
+ return getTask().getConfiguration().orientation == snapshot.getOrientation();
+ }
+
+ void removeStartingWindow() {
+ if (startingWindow == null) {
+ if (startingData != null) {
+ // Starting window has not been added yet, but it is scheduled to be added.
+ // Go ahead and cancel the request.
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "Clearing startingData for token=" + this);
+ }
+ startingData = null;
+ }
+ return;
+ }
+
+ final WindowManagerPolicy.StartingSurface surface;
+ if (startingData != null) {
+ surface = startingSurface;
+ startingData = null;
+ startingSurface = null;
+ startingWindow = null;
+ startingDisplayed = false;
+ if (surface == null) {
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
+ + "remove");
+ }
+ return;
+ }
+ } else {
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
+ + this);
+ }
+ return;
+ }
+
+ if (DEBUG_STARTING_WINDOW) {
+ Slog.v(TAG_WM, "Schedule remove starting " + this
+ + " startingWindow=" + startingWindow
+ + " startingView=" + startingSurface
+ + " Callers=" + Debug.getCallers(5));
+ }
+
+ // Use the same thread to remove the window as we used to add it, as otherwise we end up
+ // with things in the view hierarchy being called from different threads.
+ mService.mAnimationHandler.post(() -> {
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
+ try {
+ surface.remove();
+ } catch (Exception e) {
+ Slog.w(TAG_WM, "Exception when removing starting window", e);
+ }
+ });
+ }
+
@Override
boolean fillsParent() {
return mFillsParent;
@@ -1754,10 +2161,8 @@
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer");
final SurfaceControl.Builder builder = makeAnimationLeash()
.setParent(getAnimationLeashParent())
- .setName(getSurfaceControl() + " - animation-bounds")
- .setSize(getSurfaceWidth(), getSurfaceHeight());
+ .setName(getSurfaceControl() + " - animation-bounds");
final SurfaceControl boundsLayer = builder.build();
- t.setWindowCrop(boundsLayer, getSurfaceWidth(), getSurfaceHeight());
t.show(boundsLayer);
return boundsLayer;
}
@@ -2215,9 +2620,6 @@
if (mPendingRelaunchCount != 0) {
pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
}
- if (getController() != null) {
- pw.print(prefix); pw.print("controller="); pw.println(getController());
- }
if (mRemovingFromDisplay) {
pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
}
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 9633864..c90f5bf 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -48,7 +48,6 @@
surface = dc.makeOverlay()
.setName("BlackSurface")
- .setSize(w, h)
.setColorLayer(true)
.setParent(null) // TODO: Work-around for b/69259549
.build();
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index 2a216ab..c3d6211 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -69,7 +69,7 @@
try {
ctrl = dc.makeOverlay()
.setName("CircularDisplayMask")
- .setSize(mScreenSize.x, mScreenSize.y) // not a typo
+ .setBufferSize(mScreenSize.x, mScreenSize.y) // not a typo
.setFormat(PixelFormat.TRANSLUCENT)
.build();
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index cc14afc..fa3c7ca 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -308,7 +308,6 @@
return false;
} else {
// TODO: Once we use geometry from hierarchy this falls away.
- t.setSize(mDimState.mDimLayer, bounds.width(), bounds.height());
t.setPosition(mDimState.mDimLayer, bounds.left, bounds.top);
t.setWindowCrop(mDimState.mDimLayer, bounds.width(), bounds.height());
if (!mDimState.isVisible) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3acacbc..c0e9836 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -34,6 +34,7 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.InsetsState.TYPE_IME;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -78,7 +79,6 @@
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.STACKS;
-import static com.android.server.wm.DisplayContentProto.SURFACE_SIZE;
import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
@@ -124,6 +124,7 @@
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -151,6 +152,7 @@
import android.view.Gravity;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InsetsState.InternalInsetType;
import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -162,6 +164,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
+import com.android.internal.util.function.TriConsumer;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.DisplayRotationUtil;
import com.android.server.wm.utils.RotationCache;
@@ -470,14 +473,6 @@
private SurfaceControl mWindowingLayer;
/**
- * Specifies the size of the surfaces in {@link #mOverlayLayer} and {@link #mWindowingLayer}.
- * <p>
- * For these surfaces currently we use a surface based on the larger of width or height so we
- * don't have to resize when rotating the display.
- */
- private int mSurfaceSize;
-
- /**
* Sequence number for the current layout pass.
*/
int mLayoutSeq = 0;
@@ -515,6 +510,8 @@
private final PointerEventDispatcher mPointerEventDispatcher;
+ private final InsetsStateController mInsetsStateController;
+
// Last systemUiVisibility we received from status bar.
private int mLastStatusBarVisibility = 0;
// Last systemUiVisibility we dispatched to windows.
@@ -884,18 +881,7 @@
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
- // We use this as our arbitrary surface size for buffer-less parents
- // that don't impose cropping on their children. It may need to be larger
- // than the display size because fullscreen windows can be shifted offscreen
- // due to surfaceInsets. 2 times the largest display dimension feels like an
- // appropriately arbitrary number. Eventually we would like to give SurfaceFlinger
- // layers the ability to match their parent sizes and be able to skip
- // such arbitrary size settings.
- mSurfaceSize = Math.max(mBaseDisplayHeight, mBaseDisplayWidth) * 2;
-
- final SurfaceControl.Builder b = mService.makeSurfaceBuilder(mSession)
- .setSize(mSurfaceSize, mSurfaceSize)
- .setOpaque(true);
+ final SurfaceControl.Builder b = mService.makeSurfaceBuilder(mSession).setOpaque(true);
mWindowingLayer = b.setName("Display Root").build();
mOverlayLayer = b.setName("Display Overlays").build();
@@ -922,6 +908,7 @@
mService.mAnimator.addDisplayLocked(mDisplayId);
mInputMonitor = new InputMonitor(service, mDisplayId);
+ mInsetsStateController = new InsetsStateController(this);
}
boolean isReady() {
@@ -1058,6 +1045,23 @@
return mDisplayRotation;
}
+ /**
+ * Marks a window as providing insets for the rest of the windows in the system.
+ *
+ * @param type The type of inset this window provides.
+ * @param win The window.
+ * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
+ * the window should be taken.
+ */
+ void setInsetProvider(@InternalInsetType int type, WindowState win,
+ @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+ mInsetsStateController.getSourceProvider(type).setWindow(win, frameProvider);
+ }
+
+ InsetsStateController getInsetsStateController() {
+ return mInsetsStateController;
+ }
+
@VisibleForTesting
void setDisplayRotation(DisplayRotation displayRotation) {
mDisplayRotation = displayRotation;
@@ -2400,8 +2404,8 @@
mDisplayReady = false;
mRemovingDisplay = false;
}
+
mDisplayPolicy.onDisplayRemoved();
- mInputMonitor.onRemoved();
mService.mWindowPlacerLocked.requestTraversal();
}
@@ -2612,7 +2616,6 @@
}
mDisplayFrames.writeToProto(proto, DISPLAY_FRAMES);
mAppTransition.writeToProto(proto, APP_TRANSITION);
- proto.write(SURFACE_SIZE, mSurfaceSize);
if (mFocusedApp != null) {
mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
}
@@ -2733,6 +2736,8 @@
mDisplayRotation.dump(prefix, pw);
pw.println();
mInputMonitor.dump(pw, " ");
+ pw.println();
+ mInsetsStateController.dump(prefix, pw);
}
@Override
@@ -3015,6 +3020,8 @@
mInputMethodWindow.getDisplayId());
}
computeImeTarget(true /* updateImeTarget */);
+ mInsetsStateController.getSourceProvider(TYPE_IME).setWindow(win,
+ null /* frameProvider */);
}
/**
@@ -3470,6 +3477,7 @@
pendingLayoutChanges |= mDisplayPolicy.finishPostLayoutPolicyLw();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
"after finishPostLayoutPolicyLw", pendingLayoutChanges);
+ mInsetsStateController.onPostLayout();
} while (pendingLayoutChanges != 0);
mTmpApplySurfaceChangesTransactionState.reset();
@@ -3537,10 +3545,6 @@
}
}
- int getSurfaceSize() {
- return mSurfaceSize;
- }
-
void performLayout(boolean initial, boolean updateInputWindows) {
if (!isLayoutNeeded()) {
return;
@@ -4483,8 +4487,6 @@
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
SurfaceSession s = child != null ? child.getSession() : getSession();
final SurfaceControl.Builder b = mService.makeSurfaceBuilder(s);
- b.setSize(mSurfaceSize, mSurfaceSize);
-
if (child == null) {
return b;
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index c16f95e..0e5947a 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -25,6 +25,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -128,6 +129,7 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
+import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
@@ -804,6 +806,11 @@
if (mDisplayContent.isDefaultDisplay) {
mService.mPolicy.setKeyguardCandidateLw(win);
}
+ mDisplayContent.setInsetProvider(TYPE_TOP_BAR, win,
+ (displayFrames, windowState, rect) -> {
+ rect.top = 0;
+ rect.bottom = getStatusBarHeight(displayFrames);
+ });
break;
case TYPE_NAVIGATION_BAR:
mContext.enforceCallingOrSelfPermission(
@@ -818,6 +825,8 @@
mNavigationBarController.setWindow(win);
mNavigationBarController.setOnBarVisibilityChangedListener(
mNavBarVisibilityListener, true);
+ mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR,
+ win, null /* frameProvider */);
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
case TYPE_NAVIGATION_BAR_PANEL:
@@ -845,9 +854,11 @@
if (mDisplayContent.isDefaultDisplay) {
mService.mPolicy.setKeyguardCandidateLw(null);
}
+ mDisplayContent.setInsetProvider(TYPE_TOP_BAR, null, null);
} else if (mNavigationBar == win) {
mNavigationBar = null;
mNavigationBarController.setWindow(null);
+ mDisplayContent.setInsetProvider(InsetsState.TYPE_NAVIGATION_BAR, null, null);
}
if (mLastFocusedWindow == win) {
mLastFocusedWindow = null;
@@ -855,6 +866,11 @@
mScreenDecorWindows.remove(win);
}
+ private int getStatusBarHeight(DisplayFrames displayFrames) {
+ return Math.max(mStatusBarHeightForRotation[displayFrames.mRotation],
+ displayFrames.mDisplayCutoutSafe.top);
+ }
+
/**
* Control the animation to run when a window's state changes. Return a
* non-0 number to force the animation to a specific resource ID, or 0
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f1d1e49..7aabc15 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,6 +31,7 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -57,6 +59,7 @@
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
private final DisplayPolicy mDisplayPolicy;
+ private final DisplayWindowSettings mDisplayWindowSettings;
private final Context mContext;
private final Object mLock;
@@ -71,10 +74,6 @@
private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver;
- // Default display does not rotate, apps that require non-default orientation will have to
- // have the orientation emulated.
- private boolean mForceDefaultOrientation;
-
private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@VisibleForTesting
@@ -93,6 +92,13 @@
private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
private int mUserRotation = Surface.ROTATION_0;
+ /**
+ * A flag to indicate if the display rotation should be fixed to user specified rotation
+ * regardless of all other states (including app requrested orientation). {@code true} the
+ * display rotation should be fixed to user specified rotation, {@code false} otherwise.
+ */
+ private boolean mFixedToUserRotation;
+
private int mDemoHdmiRotation;
private int mDemoRotation;
private boolean mDemoHdmiRotationLock;
@@ -100,15 +106,17 @@
DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
this(service, displayContent, displayContent.getDisplayPolicy(),
- service.mContext, service.getWindowManagerLock());
+ service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock());
}
@VisibleForTesting
DisplayRotation(WindowManagerService service, DisplayContent displayContent,
- DisplayPolicy displayPolicy, Context context, Object lock) {
+ DisplayPolicy displayPolicy, DisplayWindowSettings displayWindowSettings,
+ Context context, Object lock) {
mService = service;
mDisplayContent = displayContent;
mDisplayPolicy = displayPolicy;
+ mDisplayWindowSettings = displayWindowSettings;
mContext = context;
mLock = lock;
isDefaultDisplay = displayContent.isDefaultDisplay;
@@ -204,12 +212,19 @@
// so if the orientation is forced, we need to respect that no matter what.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
- mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ final boolean forceDefaultOrientationInRes =
+ res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
+ final boolean forceDefaultOrienation =
+ ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv)
+ && forceDefaultOrientationInRes
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ && !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ // Configuration says we force to use the default orientation. We can fall back to fix
+ // rotation to only user rotation. As long as OEM doesn't change user rotation then the
+ // rotation of this display is effectively stuck at 0 deg.
+ setFixedToUserRotation(forceDefaultOrienation);
}
void setRotation(int rotation) {
@@ -227,7 +242,14 @@
}
}
- void restoreUserRotation(int userRotationMode, int userRotation) {
+ void restoreSettings(int userRotationMode, int userRotation,
+ boolean fixedToUserRotation) {
+ mFixedToUserRotation = fixedToUserRotation;
+
+ // We will retrieve user rotation and user rotation mode from settings for default display.
+ if (isDefaultDisplay) {
+ return;
+ }
if (userRotationMode != WindowManagerPolicy.USER_ROTATION_FREE
&& userRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
Slog.w(TAG, "Trying to restore an invalid user rotation mode " + userRotationMode
@@ -243,6 +265,18 @@
mUserRotation = userRotation;
}
+ void setFixedToUserRotation(boolean fixedToUserRotation) {
+ if (mFixedToUserRotation == fixedToUserRotation) {
+ return;
+ }
+
+ mFixedToUserRotation = fixedToUserRotation;
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
+ fixedToUserRotation);
+ mService.updateRotation(true /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ }
+
private void setUserRotation(int userRotationMode, int userRotation) {
if (isDefaultDisplay) {
// We'll be notified via settings listener, so we don't need to update internal values.
@@ -265,7 +299,7 @@
mUserRotation = userRotation;
changed = true;
}
- mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+ mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
mService.updateRotation(true /* alwaysSendConfiguration */,
@@ -291,9 +325,8 @@
Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
}
- /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
- boolean isDefaultOrientationForced() {
- return mForceDefaultOrientation;
+ boolean isFixedToUserRotation() {
+ return mFixedToUserRotation;
}
public int getLandscapeRotation() {
@@ -399,6 +432,12 @@
* screen is switched off.
*/
private boolean needSensorRunning() {
+ if (mFixedToUserRotation) {
+ // We are sure we only respect user rotation settings, so we are sure we will not
+ // support sensor rotation.
+ return false;
+ }
+
if (mSupportAutoRotation) {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -459,8 +498,8 @@
);
}
- if (mForceDefaultOrientation) {
- return Surface.ROTATION_0;
+ if (mFixedToUserRotation) {
+ return mUserRotation;
}
int sensorRotation = mOrientationListener != null
@@ -701,8 +740,8 @@
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mForceDefaultOrientation) {
- return false; // Rotation is forced to default orientation.
+ if (mFixedToUserRotation) {
+ return false; // Rotation is forced to user settings.
}
final int lidState = mDisplayPolicy.getLidState();
@@ -861,6 +900,7 @@
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+ pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
}
private class OrientationListener extends WindowOrientationListener {
@@ -945,4 +985,10 @@
}
}
}
+
+ @VisibleForTesting
+ interface ContentObserverRegister {
+ void registerContentObserver(Uri uri, boolean notifyForDescendants,
+ ContentObserver observer, @UserIdInt int userHandle);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f7dfd3f..45d77de 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -80,6 +80,7 @@
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
+ private boolean mFixedToUserRotation;
private Entry(String name) {
mName = name;
@@ -97,7 +98,8 @@
&& mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
- && !mShouldShowIme;
+ && !mShouldShowIme
+ && !mFixedToUserRotation;
}
}
@@ -186,6 +188,13 @@
writeSettingsIfNeeded(entry, displayInfo);
}
+ void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final Entry entry = getOrCreateEntry(displayInfo);
+ entry.mFixedToUserRotation = fixedToUserRotation;
+ writeSettingsIfNeeded(entry, displayInfo);
+ }
+
private int getWindowingModeLocked(Entry entry, int displayId) {
int windowingMode = entry != null ? entry.mWindowingMode
: WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -331,7 +340,8 @@
displayInfo.overscanRight = entry.mOverscanRight;
displayInfo.overscanBottom = entry.mOverscanBottom;
- dc.getDisplayRotation().restoreUserRotation(entry.mUserRotationMode, entry.mUserRotation);
+ dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
+ entry.mUserRotation, entry.mFixedToUserRotation);
if (entry.mForcedDensity != 0) {
dc.mBaseDisplayDensity = entry.mForcedDensity;
@@ -458,6 +468,8 @@
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
+ entry.mFixedToUserRotation = getBooleanAttribute(parser,
+ "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -541,6 +553,10 @@
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
+ if (entry.mFixedToUserRotation) {
+ out.attribute(null, "fixedToUserRotation",
+ Boolean.toString(entry.mFixedToUserRotation));
+ }
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 7ed078a..e3ddadc 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -74,8 +74,15 @@
return mDragState != null;
}
- InputWindowHandle getInputWindowHandleLocked() {
- return mDragState.getInputWindowHandle();
+ void showInputSurface(SurfaceControl.Transaction t, int displayId) {
+ mDragState.showInputSurface(t, displayId);
+ }
+
+ void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
+ if (mDragState != null) {
+ // TODO: Are we guaranteed to get here?
+ mDragState.hideInputSurface(t, displayId);
+ }
}
void registerCallback(IDragDropCallback callback) {
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index a379266..8f6ed85 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -32,9 +32,11 @@
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.Point;
import android.hardware.input.InputManager;
import android.os.Build;
+import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -118,6 +120,11 @@
private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
private Point mDisplaySize = new Point();
+ // A surface used to catch input events for the drag-and-drop operation.
+ SurfaceControl mInputSurface;
+
+ private final Rect mTmpClipRect = new Rect();
+
DragState(WindowManagerService service, DragDropController controller, IBinder token,
SurfaceControl surface, int flags, IBinder localWin) {
mService = service;
@@ -127,6 +134,42 @@
mFlags = flags;
mLocalWin = localWin;
mNotifiedWindows = new ArrayList<WindowState>();
+
+ }
+
+ void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
+ if (displayId != mDisplayContent.getDisplayId()) {
+ return;
+ }
+
+ if (mInputSurface != null) {
+ t.hide(mInputSurface);
+ }
+ }
+
+ void showInputSurface(SurfaceControl.Transaction t, int displayId) {
+ if (displayId != mDisplayContent.getDisplayId()) {
+ return;
+ }
+
+ if (mInputSurface == null) {
+ mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
+ .getSession()).setContainerLayer(true)
+ .setName("Drag and Drop Input Consumer").build();
+ }
+ final InputWindowHandle h = getInputWindowHandle();
+ if (h == null) {
+ Slog.w(TAG_WM, "Drag is in progress but there is no "
+ + "drag window handle.");
+ return;
+ }
+
+ t.show(mInputSurface);
+ t.setInputWindowInfo(mInputSurface, h);
+ t.setLayer(mInputSurface, Integer.MAX_VALUE);
+
+ mTmpClipRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+ t.setWindowCrop(mInputSurface, mTmpClipRect);
}
/**
@@ -218,7 +261,7 @@
mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
mService.mH.getLooper(), mDragDropController);
- mDragApplicationHandle = new InputApplicationHandle(null);
+ mDragApplicationHandle = new InputApplicationHandle(new Binder());
mDragApplicationHandle.name = "drag";
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
@@ -226,7 +269,7 @@
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
display.getDisplayId());
mDragWindowHandle.name = "drag";
- mDragWindowHandle.inputChannel = mServerChannel;
+ mDragWindowHandle.token = mServerChannel.getToken();
mDragWindowHandle.layer = getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index fddf6ca..7cb4a43 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -32,7 +31,6 @@
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
class EmulatorDisplayOverlay {
private static final String TAG = TAG_WITH_CLASS_NAME ? "EmulatorDisplayOverlay" : TAG_WM;
@@ -59,7 +57,7 @@
try {
ctrl = dc.makeOverlay()
.setName("EmulatorDisplayOverlay")
- .setSize(mScreenSize.x, mScreenSize.y)
+ .setBufferSize(mScreenSize.x, mScreenSize.y)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
ctrl.setLayer(zOrder);
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 49bedc9..4df5a0b 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import android.graphics.Rect;
+import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
@@ -25,6 +27,8 @@
import android.view.InputApplicationHandle;
import android.view.InputWindowHandle;
+import android.view.SurfaceControl;
+import android.util.Slog;
import java.io.PrintWriter;
@@ -39,6 +43,9 @@
final int mClientPid;
final UserHandle mClientUser;
+ final SurfaceControl mInputSurface;
+ Rect mTmpClipRect = new Rect();
+
InputConsumerImpl(WindowManagerService service, IBinder token, String name,
InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) {
mService = service;
@@ -58,14 +65,14 @@
}
mService.mInputManager.registerInputChannel(mServerChannel, null);
- mApplicationHandle = new InputApplicationHandle(null);
+ mApplicationHandle = new InputApplicationHandle(new Binder());
mApplicationHandle.name = name;
mApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId);
mWindowHandle.name = name;
- mWindowHandle.inputChannel = mServerChannel;
+ mWindowHandle.token = mServerChannel.getToken();
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType);
mWindowHandle.layoutParamsFlags = 0;
@@ -80,6 +87,10 @@
mWindowHandle.ownerUid = Process.myUid();
mWindowHandle.inputFeatures = 0;
mWindowHandle.scaleFactor = 1.0f;
+
+ mInputSurface = mService.makeSurfaceBuilder(mService.mRoot.getDisplayContent(displayId)
+ .getSession()).setContainerLayer(true).setName("Input Consumer " + name)
+ .build();
}
void linkToDeathRecipient() {
@@ -102,12 +113,33 @@
mToken.unlinkToDeath(this, 0);
}
- void layout(int dw, int dh) {
- mWindowHandle.touchableRegion.set(0, 0, dw, dh);
- mWindowHandle.frameLeft = 0;
- mWindowHandle.frameTop = 0;
- mWindowHandle.frameRight = dw;
- mWindowHandle.frameBottom = dh;
+ void layout(SurfaceControl.Transaction t, int dw, int dh) {
+ t.setPosition(mInputSurface, 0, 0);
+
+ mTmpClipRect.set(0, 0, dw, dh);
+ t.setWindowCrop(mInputSurface, mTmpClipRect);
+ }
+
+ void layout(SurfaceControl.Transaction t, Rect r) {
+ t.setPosition(mInputSurface, r.left, r.top);
+ mTmpClipRect.set(0, 0, r.width(), r.height());
+ t.setWindowCrop(mInputSurface, mTmpClipRect);
+ }
+
+ void hide(SurfaceControl.Transaction t) {
+ t.hide(mInputSurface);
+ }
+
+ void show(SurfaceControl.Transaction t, WindowState w) {
+ t.show(mInputSurface);
+ t.setInputWindowInfo(mInputSurface, mWindowHandle);
+ t.setRelativeLayer(mInputSurface, w.getSurfaceControl(), 1);
+ }
+
+ void show(SurfaceControl.Transaction t, int layer) {
+ t.show(mInputSurface);
+ t.setInputWindowInfo(mInputSurface, mWindowHandle);
+ t.setLayer(mInputSurface, layer);
}
private int getLayerLw(int windowType) {
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 92ea1a9..639ed02 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -6,21 +6,16 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.app.ActivityManager;
import android.os.Debug;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Slog;
+import android.view.InputApplicationHandle;
import android.view.KeyEvent;
import android.view.WindowManager;
-import android.view.InputApplicationHandle;
import com.android.server.input.InputManagerService;
-import android.view.InputWindowHandle;
-import android.view.InputChannel;
import java.io.PrintWriter;
-import java.util.HashMap;
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
@@ -72,8 +67,7 @@
* Called by the InputManager.
*/
@Override
- public long notifyANR(InputApplicationHandle inputApplicationHandle,
- IBinder token, String reason) {
+ public long notifyANR(IBinder token, String reason) {
AppWindowToken appWindowToken = null;
WindowState windowState = null;
boolean aboveSystem = false;
@@ -84,9 +78,6 @@
appWindowToken = windowState.mAppToken;
}
}
- if (appWindowToken == null && inputApplicationHandle != null) {
- appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
- }
if (windowState != null) {
Slog.i(TAG_WM, "Input event dispatching timed out "
@@ -116,9 +107,7 @@
if (appWindowToken != null && appWindowToken.appToken != null) {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
- final AppWindowContainerController controller = appWindowToken.getController();
- final boolean abort = controller != null
- && controller.keyDispatchingTimedOut(reason,
+ final boolean abort = appWindowToken.keyDispatchingTimedOut(reason,
(windowState != null) ? windowState.mSession.mPid : -1);
if (!abort) {
// The activity manager declined to abort dispatching.
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 83d32c8ad..88b22cb 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -44,6 +44,7 @@
import android.view.InputChannel;
import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
+import android.view.SurfaceControl;
import com.android.server.policy.WindowManagerPolicy;
@@ -61,9 +62,8 @@
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
- // Array of window handles to provide to the input dispatcher.
- private InputWindowHandle[] mInputWindowHandles;
- private int mInputWindowHandleCount;
+ // Currently focused input window handle.
+ private InputWindowHandle mFocusedInputWindowHandle;
private boolean mDisableWallpaperTouchEvents;
private final Rect mTmpRect = new Rect();
@@ -72,6 +72,8 @@
private int mDisplayId;
+ SurfaceControl.Transaction mInputTransaction = new SurfaceControl.Transaction();
+
/**
* The set of input consumer added to the window manager by name, which consumes input events
* for the windows below it.
@@ -126,6 +128,7 @@
private boolean disposeInputConsumer(InputConsumerImpl consumer) {
if (consumer != null) {
consumer.disposeChannelsLw();
+ consumer.hide(mInputTransaction);
return true;
}
return false;
@@ -137,7 +140,16 @@
void layoutInputConsumers(int dw, int dh) {
for (int i = mInputConsumers.size() - 1; i >= 0; i--) {
- mInputConsumers.valueAt(i).layout(dw, dh);
+ mInputConsumers.valueAt(i).layout(mInputTransaction, dw, dh);
+ }
+ }
+
+ // The visibility of the input consumers is recomputed each time we
+ // update the input windows. We use a model where consumers begin invisible
+ // (set so by this function) and must meet some condition for visibility on each update.
+ void resetInputConsumers(SurfaceControl.Transaction t) {
+ for (int i = mInputConsumers.size() - 1; i >= 0; i--) {
+ mInputConsumers.valueAt(i).hide(t);
}
}
@@ -177,18 +189,7 @@
}
- private void addInputWindowHandle(final InputWindowHandle windowHandle) {
- if (mInputWindowHandles == null) {
- mInputWindowHandles = new InputWindowHandle[16];
- }
- if (mInputWindowHandleCount >= mInputWindowHandles.length) {
- mInputWindowHandles = Arrays.copyOf(mInputWindowHandles,
- mInputWindowHandleCount * 2);
- }
- mInputWindowHandles[mInputWindowHandleCount++] = windowHandle;
- }
-
- void addInputWindowHandle(final InputWindowHandle inputWindowHandle,
+ void populateInputWindowHandle(final InputWindowHandle inputWindowHandle,
final WindowState child, int flags, final int type, final boolean isVisible,
final boolean hasFocus, final boolean hasWallpaper) {
// Add a window to our list of input windows.
@@ -214,6 +215,11 @@
inputWindowHandle.frameRight = frame.right;
inputWindowHandle.frameBottom = frame.bottom;
+ // Surface insets are hardcoded to be the same in all directions
+ // and we could probably deprecate the "left/right/top/bottom" concept.
+ // we avoid reintroducing this concept by just choosing one of them here.
+ inputWindowHandle.surfaceInset = child.getAttrs().surfaceInsets.left;
+
if (child.mGlobalScale != 1) {
// If we are scaling the window, input coordinates need
// to be inversely scaled to map from what is on screen
@@ -227,12 +233,9 @@
Slog.d(TAG_WM, "addInputWindowHandle: "
+ child + ", " + inputWindowHandle);
}
- addInputWindowHandle(inputWindowHandle);
- }
- private void clearInputWindowHandlesLw() {
- while (mInputWindowHandleCount != 0) {
- mInputWindowHandles[--mInputWindowHandleCount] = null;
+ if (hasFocus) {
+ mFocusedInputWindowHandle = inputWindowHandle;
}
}
@@ -261,14 +264,9 @@
if (DEBUG_DRAG) {
Log.d(TAG_WM, "Inserting drag window");
}
- final InputWindowHandle dragWindowHandle =
- mService.mDragDropController.getInputWindowHandleLocked();
- if (dragWindowHandle == null) {
- Slog.w(TAG_WM, "Drag is in progress but there is no "
- + "drag window handle.");
- } else if (dragWindowHandle.displayId == mDisplayId) {
- addInputWindowHandle(dragWindowHandle);
- }
+ mService.mDragDropController.showInputSurface(mInputTransaction, mDisplayId);
+ } else {
+ mService.mDragDropController.hideInputSurface(mInputTransaction, mDisplayId);
}
final boolean inPositioning = mService.mTaskPositioningController.isPositioningLocked();
@@ -276,14 +274,9 @@
if (DEBUG_TASK_POSITIONING) {
Log.d(TAG_WM, "Inserting window handle for repositioning");
}
- final InputWindowHandle dragWindowHandle =
- mService.mTaskPositioningController.getDragWindowHandleLocked();
- if (dragWindowHandle == null) {
- Slog.e(TAG_WM,
- "Repositioning is in progress but there is no drag window handle.");
- } else if (dragWindowHandle.displayId == mDisplayId) {
- addInputWindowHandle(dragWindowHandle);
- }
+ mService.mTaskPositioningController.showInputSurface(mInputTransaction, mDisplayId);
+ } else {
+ mService.mTaskPositioningController.hideInputSurface(mInputTransaction, mDisplayId);
}
// Add all windows on the default display.
@@ -362,12 +355,6 @@
}
}
- void onRemoved() {
- // If DisplayContent removed, we need find a way to remove window handles of this display
- // from InputDispatcher, so pass an empty InputWindowHandles to remove them.
- mService.mInputManager.setInputWindows(mInputWindowHandles, mDisplayId);
- }
-
private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
InputConsumerImpl navInputConsumer;
InputConsumerImpl pipInputConsumer;
@@ -401,16 +388,16 @@
final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
wallpaperController = dc.mWallpaperController;
- dc.forAllWindows(this, true /* traverseTopToBottom */);
+ resetInputConsumers(mInputTransaction);
+
+ dc.forAllWindows(this,
+ true /* traverseTopToBottom */);
+
if (mAddWallpaperInputConsumerHandle) {
- // No visible wallpaper found, add the wallpaper input consumer at the end.
- addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ wallpaperInputConsumer.show(mInputTransaction, 0);
}
- // Send windows to native code.
- mService.mInputManager.setInputWindows(mInputWindowHandles, mDisplayId);
-
- clearInputWindowHandlesLw();
+ mInputTransaction.apply();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
@@ -420,7 +407,7 @@
final InputChannel inputChannel = w.mInputChannel;
final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
if (inputChannel == null || inputWindowHandle == null || w.mRemoved
- || w.canReceiveTouchInput()) {
+ || w.cantReceiveTouchInput()) {
// Skip this window because it cannot possibly receive input.
return;
}
@@ -438,41 +425,36 @@
&& recentsAnimationController.shouldApplyInputConsumer(w.mAppToken)) {
if (recentsAnimationController.updateInputConsumerForApp(
recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
- addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
+ recentsAnimationInputConsumer.show(mInputTransaction, w);
mAddRecentsAnimationInputConsumerHandle = false;
}
- // If the target app window does not yet exist, then we don't add the input
- // consumer window, but also don't add the app window below.
- return;
}
}
if (w.inPinnedWindowingMode()) {
- if (mAddPipInputConsumerHandle
- && (inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer)) {
+ if (mAddPipInputConsumerHandle) {
// Update the bounds of the Pip input consumer to match the window bounds.
w.getBounds(mTmpRect);
+ pipInputConsumer.layout(mInputTransaction, mTmpRect);
+
+ // The touchable region is relative to the surface top-left
+ mTmpRect.offsetTo(0, 0);
pipInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
- addInputWindowHandle(pipInputConsumer.mWindowHandle);
+ pipInputConsumer.show(mInputTransaction, w);
mAddPipInputConsumerHandle = false;
}
- // TODO: Fix w.canReceiveTouchInput() to handle this case
- if (!hasFocus) {
- // Skip this pinned stack window if it does not have focus
- return;
- }
}
if (mAddInputConsumerHandle
&& inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
- addInputWindowHandle(navInputConsumer.mWindowHandle);
+ navInputConsumer.show(mInputTransaction, w);
mAddInputConsumerHandle = false;
}
if (mAddWallpaperInputConsumerHandle) {
if (w.mAttrs.type == TYPE_WALLPAPER && w.isVisibleLw()) {
// Add the wallpaper input consumer above the first visible wallpaper.
- addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
+ wallpaperInputConsumer.show(mInputTransaction, w);
mAddWallpaperInputConsumerHandle = false;
}
}
@@ -490,8 +472,13 @@
mService.mDragDropController.sendDragStartedIfNeededLocked(w);
}
- addInputWindowHandle(
+ populateInputWindowHandle(
inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper);
+
+ if (w.mWinAnimator.hasSurface()) {
+ mInputTransaction.setInputWindowInfo(
+ w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
new file mode 100644
index 0000000..e96f0b1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.wm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Rect;
+import android.view.InsetsSource;
+
+import com.android.internal.util.function.TriConsumer;
+import com.android.server.policy.WindowManagerPolicy;
+
+/**
+ * Controller for a specific inset source on the server. It's called provider as it provides the
+ * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}.
+ */
+class InsetsSourceProvider {
+
+ private final Rect mTmpRect = new Rect();
+ private final @NonNull InsetsSource mSource;
+ private WindowState mWin;
+ private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider;
+
+ InsetsSourceProvider(InsetsSource source) {
+ mSource = source;
+ }
+
+ InsetsSource getSource() {
+ return mSource;
+ }
+
+ /**
+ * Updates the window that currently backs this source.
+ *
+ * @param win The window that links to this source.
+ * @param frameProvider Based on display frame state and the window, calculates the resulting
+ * frame that should be reported to clients.
+ */
+ void setWindow(@Nullable WindowState win,
+ @Nullable TriConsumer<DisplayFrames, WindowState, Rect> frameProvider) {
+ if (mWin != null) {
+ mWin.setInsetProvider(null);
+ }
+ mWin = win;
+ mFrameProvider = frameProvider;
+ if (win == null) {
+ mSource.setVisible(false);
+ mSource.setFrame(new Rect());
+ } else {
+ mSource.setVisible(true);
+ mWin.setInsetProvider(this);
+ }
+ }
+
+ /**
+ * Called when a layout pass has occurred.
+ */
+ void onPostLayout() {
+ if (mWin == null) {
+ return;
+ }
+
+ mTmpRect.set(mWin.getFrameLw());
+ if (mFrameProvider != null) {
+ mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
+ } else {
+ mTmpRect.inset(mWin.mGivenContentInsets);
+ }
+ mSource.setFrame(mTmpRect);
+ mSource.setVisible(mWin.isVisible() && !mWin.mGivenInsetsPending);
+
+ }
+}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
new file mode 100644
index 0000000..1189ee6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+
+import android.util.ArrayMap;
+import android.view.InsetsState;
+
+import java.io.PrintWriter;
+import java.util.function.Consumer;
+
+/**
+ * Manages global window inset state in the system represented by {@link InsetsState}.
+ */
+class InsetsStateController {
+
+ private final InsetsState mLastState = new InsetsState();
+ private final InsetsState mState = new InsetsState();
+ private final DisplayContent mDisplayContent;
+ private ArrayMap<Integer, InsetsSourceProvider> mControllers = new ArrayMap<>();
+
+ private final Consumer<WindowState> mDispatchInsetsChanged = w -> {
+ if (w.isVisible()) {
+ w.notifyInsetsChanged();
+ }
+ };
+
+ InsetsStateController(DisplayContent displayContent) {
+ mDisplayContent = displayContent;
+ }
+
+ /**
+ * When dispatching window state to the client, we'll need to exclude the source that represents
+ * the window that is being dispatched.
+ *
+ * @param target The client we dispatch the state to.
+ * @return The state stripped of the necessary information.
+ */
+ InsetsState getInsetsForDispatch(WindowState target) {
+ final InsetsSourceProvider provider = target.getInsetProvider();
+ if (provider == null) {
+ return mState;
+ }
+
+ final InsetsState state = new InsetsState();
+ state.set(mState);
+ final int type = provider.getSource().getType();
+ state.removeSource(type);
+
+ // Navigation bar doesn't get influenced by anything else
+ if (type == TYPE_NAVIGATION_BAR) {
+ state.removeSource(TYPE_IME);
+ state.removeSource(TYPE_TOP_BAR);
+ }
+ return state;
+ }
+
+ /**
+ * @return The provider of a specific type.
+ */
+ InsetsSourceProvider getSourceProvider(int type) {
+ return mControllers.computeIfAbsent(type,
+ key -> new InsetsSourceProvider(mState.getSource(key)));
+ }
+
+ /**
+ * Called when a layout pass has occurred.
+ */
+ void onPostLayout() {
+ for (int i = mControllers.size() - 1; i>= 0; i--) {
+ mControllers.valueAt(i).onPostLayout();
+ }
+ if (!mLastState.equals(mState)) {
+ mLastState.set(mState, true /* copySources */);
+ notifyInsetsChanged();
+ }
+ }
+
+ private void notifyInsetsChanged() {
+ mDisplayContent.forAllWindows(mDispatchInsetsChanged, true /* traverseTopToBottom */);
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "WindowInsetsStateController");
+ mState.dump(prefix + " ", pw);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index c91af73..4ef3513 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -72,6 +72,7 @@
private int mVisibilityTransactionDepth;
private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
private final ActivityTaskManagerService mService;
+ private RootActivityContainer mRootActivityContainer;
KeyguardController(ActivityTaskManagerService service,
ActivityStackSupervisor stackSupervisor) {
@@ -81,6 +82,7 @@
void setWindowManager(WindowManagerService windowManager) {
mWindowManager = windowManager;
+ mRootActivityContainer = mService.mRootActivityContainer;
}
/**
@@ -146,7 +148,7 @@
mDismissalRequested = false;
}
}
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
updateKeyguardSleepToken();
}
@@ -172,16 +174,17 @@
mWindowManager.deferSurfaceLayout();
try {
setKeyguardGoingAway(true);
- mStackSupervisor.getDefaultDisplay().getWindowContainerController()
+ mRootActivityContainer.getDefaultDisplay().getWindowContainerController()
.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
false /* alwaysKeepCurrent */, convertTransitFlags(flags),
false /* forceOverride */);
updateKeyguardSleepToken();
// Some stack visibility might change (e.g. docked stack)
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
+ mRootActivityContainer.resumeFocusedStacksTopActivities();
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.addStartingWindowsForVisibleActivities(
+ true /* taskSwitch */);
mWindowManager.executeAppTransition();
} finally {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
@@ -277,8 +280,9 @@
private void visibilitiesUpdated() {
boolean requestDismissKeyguard = false;
- for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
- final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
+ for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
+ displayNdx >= 0; displayNdx--) {
+ final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
final KeyguardDisplayState state = getDisplay(display.mDisplayId);
state.visibilitiesUpdated(this, display);
requestDismissKeyguard |= state.mRequestDismissKeyguard;
@@ -298,12 +302,12 @@
if (isKeyguardLocked()) {
mWindowManager.deferSurfaceLayout();
try {
- mStackSupervisor.getDefaultDisplay().getWindowContainerController()
+ mRootActivityContainer.getDefaultDisplay().getWindowContainerController()
.prepareAppTransition(resolveOccludeTransit(),
false /* alwaysKeepCurrent */, 0 /* flags */,
true /* forceOverride */);
updateKeyguardSleepToken();
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mWindowManager.executeAppTransition();
} finally {
mWindowManager.continueSurfaceLayout();
@@ -319,21 +323,23 @@
// We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
// reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
// insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
- if (mWindowManager.isKeyguardSecure()) {
- mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
- mDismissalRequested = true;
+ if (!mWindowManager.isKeyguardSecure()) {
+ return;
+ }
- // If we are about to unocclude the Keyguard, but we can dismiss it without security,
- // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
- final DisplayWindowController dwc =
- mStackSupervisor.getDefaultDisplay().getWindowContainerController();
- if (mKeyguardShowing && canDismissKeyguard()
- && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
- dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
- 0 /* flags */, true /* forceOverride */);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mWindowManager.executeAppTransition();
- }
+ mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
+ mDismissalRequested = true;
+
+ // If we are about to unocclude the Keyguard, but we can dismiss it without security,
+ // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
+ final DisplayWindowController dwc =
+ mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
+ if (mKeyguardShowing && canDismissKeyguard()
+ && dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
+ dwc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
+ 0 /* flags */, true /* forceOverride */);
+ mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.executeAppTransition();
}
}
@@ -350,7 +356,7 @@
private int resolveOccludeTransit() {
final DisplayWindowController dwc =
- mStackSupervisor.getDefaultDisplay().getWindowContainerController();
+ mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
if (mBeforeUnoccludeTransit != TRANSIT_UNSET
&& dwc.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
// TODO(b/113840485): Handle app transition for individual display.
@@ -377,7 +383,8 @@
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
+ final ActivityStack stack =
+ mRootActivityContainer.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
return;
}
@@ -387,8 +394,9 @@
}
private void updateKeyguardSleepToken() {
- for (int displayNdx = mStackSupervisor.getChildCount() - 1; displayNdx >= 0; displayNdx--) {
- final ActivityDisplay display = mStackSupervisor.getChildAt(displayNdx);
+ for (int displayNdx = mRootActivityContainer.getChildCount() - 1;
+ displayNdx >= 0; displayNdx--) {
+ final ActivityDisplay display = mRootActivityContainer.getChildAt(displayNdx);
final KeyguardDisplayState state = getDisplay(display.mDisplayId);
if (isKeyguardOrAodShowing(display.mDisplayId) && state.mSleepToken == null) {
state.acquiredSleepToken();
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index 72d5143..bc6a690 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -223,7 +223,8 @@
private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) {
final ActivityStack<?> stack = task.getStack();
final int displayId = stack.mDisplayId;
- final ActivityDisplay display = mSupervisor.getActivityDisplay(displayId);
+ final ActivityDisplay display =
+ mSupervisor.mRootActivityContainer.getActivityDisplay(displayId);
final DisplayInfo info = new DisplayInfo();
display.mDisplay.getDisplayInfo(info);
@@ -259,7 +260,7 @@
return;
}
- final ActivityDisplay display = mSupervisor.getActivityDisplay(
+ final ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay(
persistableParams.mDisplayUniqueId);
if (display != null) {
outParams.mPreferredDisplayId = display.mDisplayId;
@@ -268,7 +269,7 @@
outParams.mBounds.set(persistableParams.mBounds);
}
- private void onPackageRemoved(String packageName) {
+ void removeRecordForPackage(String packageName) {
final List<File> fileToDelete = new ArrayList<>();
for (int i = 0; i < mMap.size(); ++i) {
int userId = mMap.keyAt(i);
@@ -309,7 +310,7 @@
@Override
public void onPackageRemoved(String packageName) {
- LaunchParamsPersister.this.onPackageRemoved(packageName);
+ removeRecordForPackage(packageName);
}
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index b49d304..1a2aa2f 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -186,7 +186,6 @@
createSurface();
}
t.setPosition(mSurface, mSurfaceFrame.left, mSurfaceFrame.top);
- t.setSize(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
t.setWindowCrop(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
t.show(mSurface);
} else if (mSurface != null) {
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 41d0777..80dc245 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -447,7 +447,7 @@
return;
}
task.performClearTaskLocked();
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
/**
@@ -579,7 +579,7 @@
if (andResume) {
mSupervisor.findTaskToMoveToFront(task, 0, null, reason,
lockTaskModeState != LOCK_TASK_MODE_NONE);
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
final ActivityStack stack = task.getStack();
if (stack != null) {
stack.getDisplay().getWindowContainerController().executeAppTransition();
@@ -641,11 +641,12 @@
taskChanged = true;
}
- for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
+ for (int displayNdx = mSupervisor.mRootActivityContainer.getChildCount() - 1;
+ displayNdx >= 0; --displayNdx) {
+ mSupervisor.mRootActivityContainer.getChildAt(displayNdx).onLockTaskPackagesUpdated();
}
- final ActivityRecord r = mSupervisor.topRunningActivityLocked();
+ final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
final TaskRecord task = (r != null) ? r.getTask() : null;
if (mLockTaskModeTasks.isEmpty() && task!= null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
@@ -657,7 +658,7 @@
}
if (taskChanged) {
- mSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java
index 3ef42e7..1c7ebd6 100644
--- a/services/core/java/com/android/server/wm/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/wm/PinnedActivityStack.java
@@ -41,7 +41,7 @@
PinnedStackWindowController createStackWindowController(int displayId, boolean onTop,
Rect outBounds) {
return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds,
- mStackSupervisor.mWindowManager);
+ mRootActivityContainer.mWindowManager);
}
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 476c1f9..24c5228 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -79,7 +79,7 @@
int callingPid) {
mService = atm;
mStackSupervisor = stackSupervisor;
- mDefaultDisplay = stackSupervisor.getDefaultDisplay();
+ mDefaultDisplay = mService.mRootActivityContainer.getDefaultDisplay();
mActivityStartController = activityStartController;
mWindowManager = wm;
mCallingPid = callingPid;
@@ -94,7 +94,7 @@
// TODO(multi-display) currently only support recents animation in default display.
final DisplayWindowController dwc =
- mStackSupervisor.getDefaultDisplay().getWindowContainerController();
+ mService.mRootActivityContainer.getDefaultDisplay().getWindowContainerController();
if (!mWindowManager.canStartRecentsAnimation()) {
notifyAnimationCancelBeforeStart(recentsAnimationRunner);
if (DEBUG) Slog.d(TAG, "Can't start recents animation, nextAppTransition="
@@ -124,8 +124,8 @@
// Send launch hint if we are actually launching the target. If it's already visible
// (shouldn't happen in general) we don't need to send it.
if (targetActivity == null || !targetActivity.visible) {
- mStackSupervisor.sendPowerHintForLaunchStartIfNeeded(true /* forceSend */,
- targetActivity);
+ mService.mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
+ true /* forceSend */, targetActivity);
}
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
@@ -192,7 +192,7 @@
// If we updated the launch-behind state, update the visibility of the activities after
// we fetch the visible tasks to be controlled by the animation
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
+ mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunched(START_TASK_TO_FRONT,
targetActivity);
@@ -215,7 +215,8 @@
@Deprecated IAssistDataReceiver assistDataReceiver, int userId) {
final AppOpsManager appOpsManager = (AppOpsManager)
mService.mContext.getSystemService(Context.APP_OPS_SERVICE);
- final List<IBinder> topActivities = mStackSupervisor.getTopVisibleActivities();
+ final List<IBinder> topActivities =
+ mService.mRootActivityContainer.getTopVisibleActivities();
final AssistDataRequester.AssistDataRequesterCallbacks assistDataCallbacks;
if (assistDataReceiver != null) {
assistDataCallbacks = new AssistDataReceiverProxy(assistDataReceiver,
@@ -283,7 +284,7 @@
// Just to be sure end the launch hint in case the target activity was never launched.
// However, if we're keeping the activity and making it visible, we can leave it on.
if (reorderMode != REORDER_KEEP_IN_PLACE) {
- mStackSupervisor.sendPowerHintForLaunchEndIfNeeded();
+ mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
}
mService.mH.post(
@@ -343,8 +344,8 @@
}
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, false);
- mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
+ mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
// No reason to wait for the pausing activity in this case, as the hiding of
// surfaces needs to be done immediately.
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
new file mode 100644
index 0000000..4dd48c4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -0,0 +1,2297 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
+import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
+import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
+import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
+import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
+import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
+import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
+import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+
+import static java.lang.Integer.MAX_VALUE;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.AppGlobals;
+import android.app.WindowConfiguration;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.power.V1_0.PowerHint;
+import android.os.Build;
+import android.os.FactoryTest;
+import android.os.IBinder;
+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;
+import android.util.DisplayMetrics;
+import android.util.IntArray;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.am.AppTimeTracker;
+import com.android.server.am.UserState;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Root node for activity containers.
+ * TODO: This class is mostly temporary to separate things out of ActivityStackSupervisor.java. The
+ * intention is to have this merged with RootWindowContainer.java as part of unifying the hierarchy.
+ */
+class RootActivityContainer extends ConfigurationContainer
+ implements DisplayManager.DisplayListener {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "RootActivityContainer" : TAG_ATM;
+ static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
+ static final String TAG_STATES = TAG + POSTFIX_STATES;
+ private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
+
+ /**
+ * The modes which affect which tasks are returned when calling
+ * {@link RootActivityContainer#anyTaskForId(int)}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ MATCH_TASK_IN_STACKS_ONLY,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
+ })
+ public @interface AnyTaskForIdMatchTaskMode {}
+ // Match only tasks in the current stacks
+ static final int MATCH_TASK_IN_STACKS_ONLY = 0;
+ // Match either tasks in the current stacks, or in the recent tasks if not found in the stacks
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS = 1;
+ // Match either tasks in the current stacks, or in the recent tasks, restoring it to the
+ // provided stack id
+ static final int MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE = 2;
+
+ ActivityTaskManagerService mService;
+ ActivityStackSupervisor mStackSupervisor;
+ WindowManagerService mWindowManager;
+ DisplayManager mDisplayManager;
+ private DisplayManagerInternal mDisplayManagerInternal;
+ // TODO: Remove after object merge with RootWindowContainer.
+ private RootWindowContainer mRootWindowContainer;
+
+ /**
+ * List of displays which contain activities, sorted by z-order.
+ * The last entry in the list is the topmost.
+ */
+ private final ArrayList<ActivityDisplay> mActivityDisplays = new ArrayList<>();
+
+ /** Reference to default display so we can quickly look it up. */
+ private ActivityDisplay mDefaultDisplay;
+ private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>();
+
+ /** The current user */
+ int mCurrentUser;
+ /** Stack id of the front stack when user switched, indexed by userId. */
+ SparseIntArray mUserStackInFront = new SparseIntArray(2);
+
+ /**
+ * A list of tokens that cause the top activity to be put to sleep.
+ * They are used by components that may hide and block interaction with underlying
+ * activities.
+ */
+ final ArrayList<ActivityTaskManagerInternal.SleepToken> mSleepTokens = new ArrayList<>();
+
+ /** Is dock currently minimized. */
+ boolean mIsDockMinimized;
+
+ /** Set when a power hint has started, but not ended. */
+ private boolean mPowerHintSent;
+
+ // The default minimal size that will be used if the activity doesn't specify its minimal size.
+ // It will be calculated when the default display gets added.
+ int mDefaultMinSizeOfResizeableTaskDp = -1;
+
+ // Whether tasks have moved and we need to rank the tasks before next OOM scoring
+ private boolean mTaskLayersChanged = true;
+
+ private final ArrayList<ActivityRecord> mTmpActivityList = new ArrayList<>();
+
+ private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
+ static class FindTaskResult {
+ ActivityRecord mRecord;
+ boolean mIdealMatch;
+
+ void clear() {
+ mRecord = null;
+ mIdealMatch = false;
+ }
+
+ void setTo(FindTaskResult result) {
+ mRecord = result.mRecord;
+ mIdealMatch = result.mIdealMatch;
+ }
+ }
+
+ RootActivityContainer(ActivityTaskManagerService service) {
+ mService = service;
+ mStackSupervisor = service.mStackSupervisor;
+ mStackSupervisor.mRootActivityContainer = this;
+ }
+
+ @VisibleForTesting
+ void setWindowContainer(RootWindowContainer container) {
+ mRootWindowContainer = container;
+ mRootWindowContainer.setRootActivityContainer(this);
+ }
+
+ void setWindowManager(WindowManagerService wm) {
+ mWindowManager = wm;
+ setWindowContainer(mWindowManager.mRoot);
+ mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
+ mDisplayManager.registerDisplayListener(this, mService.mH);
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+
+ final Display[] displays = mDisplayManager.getDisplays();
+ for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {
+ final Display display = displays[displayNdx];
+ final ActivityDisplay activityDisplay = new ActivityDisplay(this, display);
+ if (activityDisplay.mDisplayId == DEFAULT_DISPLAY) {
+ mDefaultDisplay = activityDisplay;
+ }
+ addChild(activityDisplay, ActivityDisplay.POSITION_TOP);
+ }
+ calculateDefaultMinimalSizeOfResizeableTasks();
+
+ final ActivityDisplay defaultDisplay = getDefaultDisplay();
+
+ defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP);
+ }
+
+ // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display.
+ ActivityDisplay getDefaultDisplay() {
+ return mDefaultDisplay;
+ }
+
+ /**
+ * Get an existing instance of {@link ActivityDisplay} that has the given uniqueId. Unique ID is
+ * defined in {@link DisplayInfo#uniqueId}.
+ *
+ * @param uniqueId the unique ID of the display
+ * @return the {@link ActivityDisplay} or {@code null} if nothing is found.
+ */
+ ActivityDisplay getActivityDisplay(String uniqueId) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ final boolean isValid = display.mDisplay.isValid();
+ if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
+ return display;
+ }
+ }
+
+ return null;
+ }
+
+ // TODO: Look into consolidating with getActivityDisplayOrCreate()
+ ActivityDisplay getActivityDisplay(int displayId) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
+ if (activityDisplay.mDisplayId == displayId) {
+ return activityDisplay;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get an existing instance of {@link ActivityDisplay} or create new if there is a
+ * corresponding record in display manager.
+ */
+ // TODO: Look into consolidating with getActivityDisplay()
+ ActivityDisplay getActivityDisplayOrCreate(int displayId) {
+ ActivityDisplay activityDisplay = getActivityDisplay(displayId);
+ if (activityDisplay != null) {
+ return activityDisplay;
+ }
+ if (mDisplayManager == null) {
+ // The system isn't fully initialized yet.
+ return null;
+ }
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display == null) {
+ // The display is not registered in DisplayManager.
+ return null;
+ }
+ // The display hasn't been added to ActivityManager yet, create a new record now.
+ activityDisplay = new ActivityDisplay(this, display);
+ addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM);
+ return activityDisplay;
+ }
+
+ /** Check if display with specified id is added to the list. */
+ boolean isDisplayAdded(int displayId) {
+ return getActivityDisplayOrCreate(displayId) != null;
+ }
+
+ ActivityRecord getDefaultDisplayHomeActivity() {
+ return getDefaultDisplayHomeActivityForUser(mCurrentUser);
+ }
+
+ ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
+ return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
+ }
+
+ boolean startHomeOnAllDisplays(int userId, String reason) {
+ boolean homeStarted = false;
+ for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
+ final int displayId = mActivityDisplays.get(i).mDisplayId;
+ homeStarted |= startHomeOnDisplay(userId, reason, displayId);
+ }
+ return homeStarted;
+ }
+
+ /**
+ * This starts home activity on displays that can have system decorations and only if the
+ * home activity can have multiple instances.
+ */
+ boolean startHomeOnDisplay(int userId, String reason, int displayId) {
+ final Intent homeIntent = mService.getHomeIntent();
+ final ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);
+ if (aInfo == null) {
+ return false;
+ }
+
+ if (!canStartHomeOnDisplay(aInfo, displayId,
+ false /* allowInstrumenting */)) {
+ return false;
+ }
+
+ // Update the reason for ANR debugging to verify if the user activity is the one that
+ // actually launched.
+ final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
+ aInfo.applicationInfo.uid);
+ mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
+ displayId);
+ return true;
+ }
+
+ /**
+ * This resolves the home activity info and updates the home component of the given intent.
+ * @return the home activity info if any.
+ */
+ private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
+ final int flags = ActivityManagerService.STOCK_PM_FLAGS;
+ final ComponentName comp = homeIntent.getComponent();
+ ActivityInfo aInfo = null;
+ try {
+ if (comp != null) {
+ // Factory test.
+ aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
+ } else {
+ final String resolvedType =
+ homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
+ final ResolveInfo info = AppGlobals.getPackageManager()
+ .resolveIntent(homeIntent, resolvedType, flags, userId);
+ if (info != null) {
+ aInfo = info.activityInfo;
+ }
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
+
+ if (aInfo == null) {
+ Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
+ return null;
+ }
+
+ homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
+ aInfo = new ActivityInfo(aInfo);
+ aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
+ homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
+ return aInfo;
+ }
+
+ boolean resumeHomeActivity(ActivityRecord prev, String reason, int displayId) {
+ if (!mService.isBooting() && !mService.isBooted()) {
+ // Not ready yet!
+ return false;
+ }
+
+ if (displayId == INVALID_DISPLAY) {
+ displayId = DEFAULT_DISPLAY;
+ }
+
+ final ActivityRecord r = getActivityDisplay(displayId).getHomeActivity();
+ final String myReason = reason + " resumeHomeActivity";
+
+ // Only resume home activity if isn't finishing.
+ if (r != null && !r.finishing) {
+ r.moveFocusableActivityToTop(myReason);
+ return resumeFocusedStacksTopActivities(r.getStack(), prev, null);
+ }
+ return startHomeOnDisplay(mCurrentUser, myReason, displayId);
+ }
+
+ /**
+ * Check if home activity start should be allowed on a display.
+ * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
+ * @param displayId The id of the target display.
+ * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
+ * @return {@code true} if allow to launch, {@code false} otherwise.
+ */
+ boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
+ boolean allowInstrumenting) {
+ if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
+ && mService.mTopAction == null) {
+ // We are running in factory test mode, but unable to find the factory test app, so
+ // just sit around displaying the error message and don't try to start anything.
+ return false;
+ }
+
+ final WindowProcessController app =
+ mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
+ if (!allowInstrumenting && app != null && app.isInstrumenting()) {
+ // Don't do this if the home app is currently being instrumented.
+ return false;
+ }
+
+ if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
+ && displayId == mService.mVr2dDisplayId)) {
+ // No restrictions to default display or vr 2d display.
+ return true;
+ }
+
+ final ActivityDisplay display = getActivityDisplay(displayId);
+ if (display == null || display.isRemoved() || !display.supportsSystemDecorations()) {
+ // Can't launch home on display that doesn't support system decorations.
+ return false;
+ }
+
+ final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
+ && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE
+ && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+ if (!supportMultipleInstance) {
+ // Can't launch home on other displays if it requested to be single instance. Also we
+ // don't allow home applications that target before Q to have multiple home activity
+ // instances because they may not be expected to have multiple home scenario and
+ // haven't explicitly request for single instance.
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Ensure all activities visibility, update orientation and configuration.
+ *
+ * @param starting The currently starting activity or {@code null} if there is none.
+ * @param displayId The id of the display where operation is executed.
+ * @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
+ * {@code true} if config changed.
+ * @param deferResume Whether to defer resume while updating config.
+ * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
+ * because of configuration update.
+ */
+ boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
+ boolean markFrozenIfConfigChanged, boolean deferResume) {
+ // First ensure visibility without updating the config just yet. We need this to know what
+ // activities are affecting configuration now.
+ // Passing null here for 'starting' param value, so that visibility of actual starting
+ // activity will be properly updated.
+ ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */, false /* notifyClients */);
+
+ if (displayId == INVALID_DISPLAY) {
+ // The caller didn't provide a valid display id, skip updating config.
+ return true;
+ }
+
+ // Force-update the orientation from the WindowManager, since we need the true configuration
+ // to send to the client now.
+ final Configuration config = mWindowManager.updateOrientationFromAppTokens(
+ getDisplayOverrideConfiguration(displayId),
+ starting != null && starting.mayFreezeScreenLocked(starting.app)
+ ? starting.appToken : null,
+ displayId, true /* forceUpdate */);
+ if (starting != null && markFrozenIfConfigChanged && config != null) {
+ starting.frozenBeforeDestroy = true;
+ }
+
+ // Update the configuration of the activities on the display.
+ return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
+ displayId);
+ }
+
+ /**
+ * @return a list of activities which are the top ones in each visible stack. The first
+ * entry will be the focused activity.
+ */
+ List<IBinder> getTopVisibleActivities() {
+ final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+ final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
+ // Traverse all displays.
+ for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ // Traverse all stacks on a display.
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
+ // Get top activity from a visible stack and add it to the list.
+ if (stack.shouldBeVisible(null /* starting */)) {
+ final ActivityRecord top = stack.getTopActivity();
+ if (top != null) {
+ if (stack == topFocusedStack) {
+ topActivityTokens.add(0, top.appToken);
+ } else {
+ topActivityTokens.add(top.appToken);
+ }
+ }
+ }
+ }
+ }
+ return topActivityTokens;
+ }
+
+ ActivityStack getTopDisplayFocusedStack() {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityStack focusedStack = mActivityDisplays.get(i).getFocusedStack();
+ if (focusedStack != null) {
+ return focusedStack;
+ }
+ }
+ return null;
+ }
+
+ ActivityRecord getTopResumedActivity() {
+ final ActivityStack focusedStack = getTopDisplayFocusedStack();
+ if (focusedStack == null) {
+ return null;
+ }
+ final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+ if (resumedActivity != null && resumedActivity.app != null) {
+ return resumedActivity;
+ }
+ // The top focused stack might not have a resumed activity yet - look on all displays in
+ // focus order.
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
+ if (resumedActivityOnDisplay != null) {
+ return resumedActivityOnDisplay;
+ }
+ }
+ return null;
+ }
+
+ boolean isFocusable(ConfigurationContainer container, boolean alwaysFocusable) {
+ if (container.inSplitScreenPrimaryWindowingMode() && mIsDockMinimized) {
+ return false;
+ }
+
+ return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable;
+ }
+
+ boolean isTopDisplayFocusedStack(ActivityStack stack) {
+ return stack != null && stack == getTopDisplayFocusedStack();
+ }
+
+ void updatePreviousProcess(ActivityRecord r) {
+ // Now that this process has stopped, we may want to consider it to be the previous app to
+ // try to keep around in case the user wants to return to it.
+
+ // First, found out what is currently the foreground app, so that we don't blow away the
+ // previous app if this activity is being hosted by the process that is actually still the
+ // foreground.
+ WindowProcessController fgApp = null;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ if (isTopDisplayFocusedStack(stack)) {
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity != null) {
+ fgApp = resumedActivity.app;
+ } else if (stack.mPausingActivity != null) {
+ fgApp = stack.mPausingActivity.app;
+ }
+ break;
+ }
+ }
+ }
+
+ // Now set this one as the previous process, only if that really makes sense to.
+ if (r.hasProcess() && fgApp != null && r.app != fgApp
+ && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
+ && r.app != mService.mHomeProcess) {
+ mService.mPreviousProcess = r.app;
+ mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
+ }
+ }
+
+ boolean attachApplication(WindowProcessController app) throws RemoteException {
+ final String processName = app.mName;
+ boolean didSomething = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ final ActivityStack stack = display.getFocusedStack();
+ if (stack != null) {
+ stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
+ final ActivityRecord top = stack.topRunningActivityLocked();
+ final int size = mTmpActivityList.size();
+ for (int i = 0; i < size; i++) {
+ final ActivityRecord activity = mTmpActivityList.get(i);
+ if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
+ && processName.equals(activity.processName)) {
+ try {
+ if (mStackSupervisor.realStartActivityLocked(activity, app,
+ top == activity /* andResume */, true /* checkConfig */)) {
+ didSomething = true;
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception in new application when starting activity "
+ + top.intent.getComponent().flattenToShortString(), e);
+ throw e;
+ }
+ }
+ }
+ }
+ }
+ if (!didSomething) {
+ ensureActivitiesVisible(null, 0, false /* preserve_windows */);
+ }
+ return didSomething;
+ }
+
+ /**
+ * Make sure that all activities that need to be visible in the system actually are and update
+ * their configuration.
+ */
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows) {
+ ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
+ }
+
+ /**
+ * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
+ */
+ void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
+ boolean preserveWindows, boolean notifyClients) {
+ mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
+ try {
+ // First the front stacks. In case any are not fullscreen and are in front of home.
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
+ notifyClients);
+ }
+ }
+ } finally {
+ mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
+ }
+ }
+
+ boolean switchUser(int userId, UserState uss) {
+ final int focusStackId = getTopDisplayFocusedStack().getStackId();
+ // We dismiss the docked stack whenever we switch users.
+ final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
+ if (dockedStack != null) {
+ mStackSupervisor.moveTasksToFullscreenStackLocked(
+ dockedStack, dockedStack.isFocusedStackOnDisplay());
+ }
+ // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
+ // also cause all tasks to be moved to the fullscreen stack at a position that is
+ // appropriate.
+ removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
+
+ mUserStackInFront.put(mCurrentUser, focusStackId);
+ final int restoreStackId =
+ mUserStackInFront.get(userId, getDefaultDisplay().getHomeStack().mStackId);
+ mCurrentUser = userId;
+
+ mStackSupervisor.mStartingUsers.add(uss);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.switchUserLocked(userId);
+ TaskRecord task = stack.topTask();
+ if (task != null) {
+ stack.positionChildWindowContainerAtTop(task);
+ }
+ }
+ }
+
+ ActivityStack stack = getStack(restoreStackId);
+ if (stack == null) {
+ stack = getDefaultDisplay().getHomeStack();
+ }
+ final boolean homeInFront = stack.isActivityTypeHome();
+ if (stack.isOnHomeDisplay()) {
+ stack.moveToFront("switchUserOnHomeDisplay");
+ } else {
+ // Stack was moved to another display while user was swapped out.
+ resumeHomeActivity(null, "switchUserOnOtherDisplay", DEFAULT_DISPLAY);
+ }
+ return homeInFront;
+ }
+
+ void removeUser(int userId) {
+ mUserStackInFront.delete(userId);
+ }
+
+ /**
+ * Update the last used stack id for non-current user (current user's last
+ * used stack is the focused stack)
+ */
+ void updateUserStack(int userId, ActivityStack stack) {
+ if (userId != mCurrentUser) {
+ mUserStackInFront.put(userId, stack != null ? stack.getStackId()
+ : getDefaultDisplay().getHomeStack().mStackId);
+ }
+ }
+
+ void resizeStack(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
+ Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode,
+ boolean deferResume) {
+
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
+ mStackSupervisor.resizeDockedStackLocked(bounds, tempTaskBounds,
+ tempTaskInsetBounds, null, null, preserveWindows, deferResume);
+ return;
+ }
+
+ final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack();
+ if (!allowResizeInDockedMode
+ && !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) {
+ // If the docked stack exists, don't resize non-floating stacks independently of the
+ // size computed from the docked stack size (otherwise they will be out of sync)
+ return;
+ }
+
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId);
+ mWindowManager.deferSurfaceLayout();
+ try {
+ if (stack.affectedBySplitScreenResize()) {
+ if (bounds == null && stack.inSplitScreenWindowingMode()) {
+ // null bounds = fullscreen windowing mode...at least for now.
+ stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ } else if (splitScreenActive) {
+ // If we are in split-screen mode and this stack support split-screen, then
+ // it should be split-screen secondary mode. i.e. adjacent to the docked stack.
+ stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ }
+ }
+ stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds);
+ if (!deferResume) {
+ stack.ensureVisibleActivitiesConfigurationLocked(
+ stack.topRunningActivityLocked(), preserveWindows);
+ }
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+
+ /**
+ * Move stack with all its existing content to specified display.
+ * @param stackId Id of stack to move.
+ * @param displayId Id of display to move stack to.
+ * @param onTop Indicates whether container should be place on top or on bottom.
+ */
+ void moveStackToDisplay(int stackId, int displayId, boolean onTop) {
+ final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException("moveStackToDisplay: Unknown displayId="
+ + displayId);
+ }
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("moveStackToDisplay: Unknown stackId="
+ + stackId);
+ }
+
+ final ActivityDisplay currentDisplay = stack.getDisplay();
+ if (currentDisplay == null) {
+ throw new IllegalStateException("moveStackToDisplay: Stack with stack=" + stack
+ + " is not attached to any display.");
+ }
+
+ if (currentDisplay.mDisplayId == displayId) {
+ throw new IllegalArgumentException("Trying to move stack=" + stack
+ + " to its current displayId=" + displayId);
+ }
+
+ stack.reparent(activityDisplay, onTop, false /* displayRemoved */);
+ // TODO(multi-display): resize stacks properly if moved from split-screen.
+ }
+
+ boolean moveTopStackActivityToPinnedStack(int stackId) {
+ final ActivityStack stack = getStack(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException(
+ "moveTopStackActivityToPinnedStack: Unknown stackId=" + stackId);
+ }
+
+ final ActivityRecord r = stack.topRunningActivityLocked();
+ if (r == null) {
+ Slog.w(TAG, "moveTopStackActivityToPinnedStack: No top running activity"
+ + " in stack=" + stack);
+ return false;
+ }
+
+ if (!mService.mForceResizableActivities && !r.supportsPictureInPicture()) {
+ Slog.w(TAG, "moveTopStackActivityToPinnedStack: Picture-In-Picture not supported for "
+ + " r=" + r);
+ return false;
+ }
+
+ moveActivityToPinnedStack(r, null /* sourceBounds */, 0f /* aspectRatio */,
+ "moveTopActivityToPinnedStack");
+ return true;
+ }
+
+ void moveActivityToPinnedStack(ActivityRecord r, Rect sourceHintBounds, float aspectRatio,
+ String reason) {
+
+ mWindowManager.deferSurfaceLayout();
+
+ final ActivityDisplay display = r.getStack().getDisplay();
+ PinnedActivityStack stack = display.getPinnedStack();
+
+ // This will clear the pinned stack by moving an existing task to the full screen stack,
+ // ensuring only one task is present.
+ if (stack != null) {
+ mStackSupervisor.moveTasksToFullscreenStackLocked(stack, !ON_TOP);
+ }
+
+ // Need to make sure the pinned stack exist so we can resize it below...
+ stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP);
+
+ // Calculate the target bounds here before the task is reparented back into pinned windowing
+ // mode (which will reset the saved bounds)
+ final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio);
+
+ try {
+ final TaskRecord task = r.getTask();
+ // Resize the pinned stack to match the current size of the task the activity we are
+ // going to be moving is currently contained in. We do this to have the right starting
+ // animation bounds for the pinned stack to the desired bounds the caller wants.
+ resizeStack(stack, task.getOverrideBounds(), null /* tempTaskBounds */,
+ null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
+ true /* allowResizeInDockedMode */, !DEFER_RESUME);
+
+ if (task.mActivities.size() == 1) {
+ // Defer resume until below, and do not schedule PiP changes until we animate below
+ task.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE, DEFER_RESUME,
+ false /* schedulePictureInPictureModeChange */, reason);
+ } else {
+ // There are multiple activities in the task and moving the top activity should
+ // reveal/leave the other activities in their original task.
+
+ // Currently, we don't support reparenting activities across tasks in two different
+ // stacks, so instead, just create a new task in the same stack, reparent the
+ // activity into that task, and then reparent the whole task to the new stack. This
+ // ensures that all the necessary work to migrate states in the old and new stacks
+ // is also done.
+ final TaskRecord newTask = task.getStack().createTaskRecord(
+ mStackSupervisor.getNextTaskIdForUserLocked(r.userId), r.info,
+ r.intent, null, null, true);
+ r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+
+ // Defer resume until below, and do not schedule PiP changes until we animate below
+ newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
+ DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
+ }
+
+ // Reset the state that indicates it can enter PiP while pausing after we've moved it
+ // to the pinned stack
+ r.supportsEnterPipOnTaskSwitch = false;
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+
+ stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
+ true /* fromFullscreen */);
+
+ // Update the visibility of all activities after the they have been reparented to the new
+ // stack. This MUST run after the animation above is scheduled to ensure that the windows
+ // drawn signal is scheduled after the bounds animation start call on the bounds animator
+ // thread.
+ ensureActivitiesVisible(null, 0, false /* preserveWindows */);
+ resumeFocusedStacksTopActivities();
+
+ mService.getTaskChangeNotificationController().notifyActivityPinned(r);
+ }
+
+ void executeAppTransitionForAllDisplay() {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ display.getWindowContainerController().executeAppTransition();
+ }
+ }
+
+ void setDockedStackMinimized(boolean minimized) {
+ // Get currently focused stack before setting mIsDockMinimized. We do this because if
+ // split-screen is active, primary stack will not be focusable (see #isFocusable) while
+ // still occluding other stacks. This will cause getTopDisplayFocusedStack() to return null.
+ final ActivityStack current = getTopDisplayFocusedStack();
+ mIsDockMinimized = minimized;
+ if (mIsDockMinimized) {
+ if (current.inSplitScreenPrimaryWindowingMode()) {
+ // The primary split-screen stack can't be focused while it is minimize, so move
+ // focus to something else.
+ current.adjustFocusToNextFocusableStack("setDockedStackMinimized");
+ }
+ }
+ }
+
+ ActivityRecord findTask(ActivityRecord r, int preferredDisplayId) {
+ if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
+ mTmpFindTaskResult.clear();
+
+ // Looking up task on preferred display first
+ final ActivityDisplay preferredDisplay = getActivityDisplay(preferredDisplayId);
+ if (preferredDisplay != null) {
+ preferredDisplay.findTaskLocked(r, true /* isPreferredDisplay */, mTmpFindTaskResult);
+ if (mTmpFindTaskResult.mIdealMatch) {
+ return mTmpFindTaskResult.mRecord;
+ }
+ }
+
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ if (display.mDisplayId == preferredDisplayId) {
+ continue;
+ }
+
+ display.findTaskLocked(r, false /* isPreferredDisplay */, mTmpFindTaskResult);
+ if (mTmpFindTaskResult.mIdealMatch) {
+ return mTmpFindTaskResult.mRecord;
+ }
+ }
+
+ if (DEBUG_TASKS && mTmpFindTaskResult.mRecord == null) Slog.d(TAG_TASKS, "No task found");
+ return mTmpFindTaskResult.mRecord;
+ }
+
+ /**
+ * Finish the topmost activities in all stacks that belong to the crashed app.
+ * @param app The app that crashed.
+ * @param reason Reason to perform this action.
+ * @return The task id that was finished in this stack, or INVALID_TASK_ID if none was finished.
+ */
+ int finishTopCrashedActivities(WindowProcessController app, String reason) {
+ TaskRecord finishedTask = null;
+ ActivityStack focusedStack = getTopDisplayFocusedStack();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ // It is possible that request to finish activity might also remove its task and stack,
+ // so we need to be careful with indexes in the loop and check child count every time.
+ for (int stackNdx = 0; stackNdx < display.getChildCount(); ++stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final TaskRecord t = stack.finishTopCrashedActivityLocked(app, reason);
+ if (stack == focusedStack || finishedTask == null) {
+ finishedTask = t;
+ }
+ }
+ }
+ return finishedTask != null ? finishedTask.taskId : INVALID_TASK_ID;
+ }
+
+ boolean resumeFocusedStacksTopActivities() {
+ return resumeFocusedStacksTopActivities(null, null, null);
+ }
+
+ boolean resumeFocusedStacksTopActivities(
+ ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
+
+ if (!mStackSupervisor.readyToResume()) {
+ return false;
+ }
+
+ if (targetStack != null && (targetStack.isTopStackOnDisplay()
+ || getTopDisplayFocusedStack() == targetStack)) {
+ return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
+ }
+
+ // Resume all top activities in focused stacks on all displays.
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ final ActivityStack focusedStack = display.getFocusedStack();
+ if (focusedStack == null) {
+ continue;
+ }
+ final ActivityRecord r = focusedStack.topRunningActivityLocked();
+ if (r == null || !r.isState(RESUMED)) {
+ focusedStack.resumeTopActivityUncheckedLocked(null, null);
+ } else if (r.isState(RESUMED)) {
+ // Kick off any lingering app transitions form the MoveTaskToFront operation.
+ focusedStack.executeAppTransition(targetOptions);
+ }
+ }
+
+ return false;
+ }
+
+ void applySleepTokens(boolean applyToStacks) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ // Set the sleeping state of the display.
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ final boolean displayShouldSleep = display.shouldSleep();
+ if (displayShouldSleep == display.isSleeping()) {
+ continue;
+ }
+ display.setIsSleeping(displayShouldSleep);
+
+ if (!applyToStacks) {
+ continue;
+ }
+
+ // Set the sleeping state of the stacks on the display.
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ if (displayShouldSleep) {
+ stack.goToSleepIfPossible(false /* shuttingDown */);
+ } else {
+ stack.awakeFromSleepingLocked();
+ if (stack.isFocusedStackOnDisplay()
+ && !mStackSupervisor.getKeyguardController()
+ .isKeyguardOrAodShowing(display.mDisplayId)) {
+ // If the keyguard is unlocked - resume immediately.
+ // It is possible that the display will not be awake at the time we
+ // process the keyguard going away, which can happen before the sleep token
+ // is released. As a result, it is important we resume the activity here.
+ resumeFocusedStacksTopActivities();
+ }
+ }
+ }
+
+ if (displayShouldSleep || mStackSupervisor.mGoingToSleepActivities.isEmpty()) {
+ continue;
+ }
+ // The display is awake now, so clean up the going to sleep list.
+ for (Iterator<ActivityRecord> it =
+ mStackSupervisor.mGoingToSleepActivities.iterator(); it.hasNext(); ) {
+ final ActivityRecord r = it.next();
+ if (r.getDisplayId() == display.mDisplayId) {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ protected <T extends ActivityStack> T getStack(int stackId) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final T stack = mActivityDisplays.get(i).getStack(stackId);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ /** @see ActivityDisplay#getStack(int, int) */
+ private <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final T stack = mActivityDisplays.get(i).getStack(windowingMode, activityType);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ private ActivityManager.StackInfo getStackInfo(ActivityStack stack) {
+ final int displayId = stack.mDisplayId;
+ final ActivityDisplay display = getActivityDisplay(displayId);
+ ActivityManager.StackInfo info = new ActivityManager.StackInfo();
+ stack.getWindowContainerBounds(info.bounds);
+ info.displayId = displayId;
+ info.stackId = stack.mStackId;
+ info.userId = stack.mCurrentUser;
+ info.visible = stack.shouldBeVisible(null);
+ // A stack might be not attached to a display.
+ info.position = display != null ? display.getIndexOf(stack) : 0;
+ info.configuration.setTo(stack.getConfiguration());
+
+ ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final int numTasks = tasks.size();
+ int[] taskIds = new int[numTasks];
+ String[] taskNames = new String[numTasks];
+ Rect[] taskBounds = new Rect[numTasks];
+ int[] taskUserIds = new int[numTasks];
+ for (int i = 0; i < numTasks; ++i) {
+ final TaskRecord task = tasks.get(i);
+ taskIds[i] = task.taskId;
+ taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
+ : task.realActivity != null ? task.realActivity.flattenToString()
+ : task.getTopActivity() != null ? task.getTopActivity().packageName
+ : "unknown";
+ taskBounds[i] = new Rect();
+ task.getWindowContainerBounds(taskBounds[i]);
+ taskUserIds[i] = task.userId;
+ }
+ info.taskIds = taskIds;
+ info.taskNames = taskNames;
+ info.taskBounds = taskBounds;
+ info.taskUserIds = taskUserIds;
+
+ final ActivityRecord top = stack.topRunningActivityLocked();
+ info.topActivity = top != null ? top.intent.getComponent() : null;
+ return info;
+ }
+
+ ActivityManager.StackInfo getStackInfo(int stackId) {
+ ActivityStack stack = getStack(stackId);
+ if (stack != null) {
+ return getStackInfo(stack);
+ }
+ return null;
+ }
+
+ ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
+ final ActivityStack stack = getStack(windowingMode, activityType);
+ return (stack != null) ? getStackInfo(stack) : null;
+ }
+
+ ArrayList<ActivityManager.StackInfo> getAllStackInfos() {
+ ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ list.add(getStackInfo(stack));
+ }
+ }
+ return list;
+ }
+
+ void deferUpdateBounds(int activityType) {
+ final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+ if (stack != null) {
+ stack.deferUpdateBounds();
+ }
+ }
+
+ void continueUpdateBounds(int activityType) {
+ final ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
+ if (stack != null) {
+ stack.continueUpdateBounds();
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
+ synchronized (mService.mGlobalLock) {
+ getActivityDisplayOrCreate(displayId);
+ // Do not start home before booting, or it may accidentally finish booting before it
+ // starts. Instead, we expect home activities to be launched when the system is ready
+ // (ActivityManagerService#systemReady).
+ if (mService.isBooted() || mService.isBooting()) {
+ startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
+ if (displayId == DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException("Can't remove the primary display.");
+ }
+
+ synchronized (mService.mGlobalLock) {
+ final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
+ if (activityDisplay == null) {
+ return;
+ }
+
+ activityDisplay.remove();
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
+ synchronized (mService.mGlobalLock) {
+ final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
+ if (activityDisplay != null) {
+ activityDisplay.onDisplayChanged();
+ }
+ }
+ }
+
+ /** Update lists of UIDs that are present on displays and have access to them. */
+ void updateUIDsPresentOnDisplay() {
+ mDisplayAccessUIDs.clear();
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
+ // Only bother calculating the whitelist for private displays
+ if (activityDisplay.isPrivate()) {
+ mDisplayAccessUIDs.append(
+ activityDisplay.mDisplayId, activityDisplay.getPresentUIDs());
+ }
+ }
+ // Store updated lists in DisplayManager. Callers from outside of AM should get them there.
+ mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs);
+ }
+
+ ActivityStack findStackBehind(ActivityStack stack) {
+ final ActivityDisplay display = getActivityDisplay(stack.mDisplayId);
+ if (display != null) {
+ for (int i = display.getChildCount() - 1; i >= 0; i--) {
+ if (display.getChildAt(i) == stack && i > 0) {
+ return display.getChildAt(i - 1);
+ }
+ }
+ }
+ throw new IllegalStateException("Failed to find a stack behind stack=" + stack
+ + " in=" + display);
+ }
+
+ @Override
+ protected int getChildCount() {
+ return mActivityDisplays.size();
+ }
+
+ @Override
+ protected ActivityDisplay getChildAt(int index) {
+ return mActivityDisplays.get(index);
+ }
+
+ @Override
+ protected ConfigurationContainer getParent() {
+ return null;
+ }
+
+ // TODO: remove after object merge with RootWindowContainer
+ void onChildPositionChanged(DisplayWindowController childController, int position) {
+ // Assume AM lock is held from positionChildAt of controller in each hierarchy.
+ final ActivityDisplay display = getActivityDisplay(childController.getDisplayId());
+ if (display != null) {
+ positionChildAt(display, position);
+ }
+ }
+
+ /** Change the z-order of the given display. */
+ private void positionChildAt(ActivityDisplay display, int position) {
+ if (position >= mActivityDisplays.size()) {
+ position = mActivityDisplays.size() - 1;
+ } else if (position < 0) {
+ position = 0;
+ }
+
+ if (mActivityDisplays.isEmpty()) {
+ mActivityDisplays.add(display);
+ } else if (mActivityDisplays.get(position) != display) {
+ mActivityDisplays.remove(display);
+ mActivityDisplays.add(position, display);
+ }
+ }
+
+ @VisibleForTesting
+ void addChild(ActivityDisplay activityDisplay, int position) {
+ positionChildAt(activityDisplay, position);
+ mRootWindowContainer.positionChildAt(position,
+ activityDisplay.getWindowContainerController().mContainer);
+ }
+
+ void removeChild(ActivityDisplay activityDisplay) {
+ // The caller must tell the controller of {@link ActivityDisplay} to release its container
+ // {@link DisplayContent}. That is done in {@link ActivityDisplay#releaseSelfIfNeeded}).
+ mActivityDisplays.remove(activityDisplay);
+ }
+
+ Configuration getDisplayOverrideConfiguration(int displayId) {
+ final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ return activityDisplay.getOverrideConfiguration();
+ }
+
+ void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
+ final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException("No display found with id: " + displayId);
+ }
+
+ activityDisplay.onOverrideConfigurationChanged(overrideConfiguration);
+ }
+
+ void prepareForShutdown() {
+ for (int i = 0; i < mActivityDisplays.size(); i++) {
+ createSleepToken("shutdown", mActivityDisplays.get(i).mDisplayId);
+ }
+ }
+
+ ActivityTaskManagerInternal.SleepToken createSleepToken(String tag, int displayId) {
+ final ActivityDisplay display = getActivityDisplay(displayId);
+ if (display == null) {
+ throw new IllegalArgumentException("Invalid display: " + displayId);
+ }
+
+ final SleepTokenImpl token = new SleepTokenImpl(tag, displayId);
+ mSleepTokens.add(token);
+ display.mAllSleepTokens.add(token);
+ return token;
+ }
+
+ private void removeSleepToken(SleepTokenImpl token) {
+ mSleepTokens.remove(token);
+
+ final ActivityDisplay display = getActivityDisplay(token.mDisplayId);
+ if (display != null) {
+ display.mAllSleepTokens.remove(token);
+ if (display.mAllSleepTokens.isEmpty()) {
+ mService.updateSleepIfNeededLocked();
+ }
+ }
+ }
+
+ void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.addStartingWindowsForVisibleActivities(taskSwitch);
+ }
+ }
+ }
+
+ void invalidateTaskLayers() {
+ mTaskLayersChanged = true;
+ }
+
+ void rankTaskLayersIfNeeded() {
+ if (!mTaskLayersChanged) {
+ return;
+ }
+ mTaskLayersChanged = false;
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ int baseLayer = 0;
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ baseLayer += stack.rankTaskLayers(baseLayer);
+ }
+ }
+ }
+
+ void clearOtherAppTimeTrackers(AppTimeTracker except) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.clearOtherAppTimeTrackers(except);
+ }
+ }
+ }
+
+ void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.scheduleDestroyActivities(app, reason);
+ }
+ }
+ }
+
+ void releaseSomeActivitiesLocked(WindowProcessController app, String reason) {
+ // Tasks is non-null only if two or more tasks are found.
+ ArraySet<TaskRecord> tasks = app.getReleaseSomeActivitiesTasks();
+ if (tasks == null) {
+ if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Didn't find two or more tasks to release");
+ return;
+ }
+ // If we have activities in multiple tasks that are in a position to be destroyed,
+ // let's iterate through the tasks and release the oldest one.
+ final int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ final int stackCount = display.getChildCount();
+ // Step through all stacks starting from behind, to hit the oldest things first.
+ for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ // Try to release activities in this stack; if we manage to, we are done.
+ if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
+ return;
+ }
+ }
+ }
+ }
+
+ // Tries to put all activity stacks to sleep. Returns true if all stacks were
+ // successfully put to sleep.
+ boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
+ boolean allSleep = true;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ if (allowDelay) {
+ allSleep &= stack.goToSleepIfPossible(shuttingDown);
+ } else {
+ stack.goToSleep();
+ }
+ }
+ }
+ return allSleep;
+ }
+
+ void handleAppCrash(WindowProcessController app) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.handleAppCrash(app);
+ }
+ }
+ }
+
+ ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord ar = stack.findActivityLocked(
+ intent, info, compareIntentFilters);
+ if (ar != null) {
+ return ar;
+ }
+ }
+ }
+ return null;
+ }
+
+ boolean hasAwakeDisplay() {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ if (!display.shouldSleep()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
+ return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */);
+ }
+
+ /**
+ * Returns the right stack to use for launching factoring in all the input parameters.
+ *
+ * @param r The activity we are trying to launch. Can be null.
+ * @param options The activity options used to the launch. Can be null.
+ * @param candidateTask The possible task the activity might be launched in. Can be null.
+ * @params launchParams The resolved launch params to use.
+ *
+ * @return The stack to use for the launch or INVALID_STACK_ID.
+ */
+ <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
+ @Nullable LaunchParamsController.LaunchParams launchParams) {
+ int taskId = INVALID_TASK_ID;
+ int displayId = INVALID_DISPLAY;
+ //Rect bounds = null;
+
+ // We give preference to the launch preference in activity options.
+ if (options != null) {
+ taskId = options.getLaunchTaskId();
+ displayId = options.getLaunchDisplayId();
+ }
+
+ // First preference for stack goes to the task Id set in the activity options. Use the stack
+ // associated with that if possible.
+ if (taskId != INVALID_TASK_ID) {
+ // Temporarily set the task id to invalid in case in re-entry.
+ options.setLaunchTaskId(INVALID_TASK_ID);
+ final TaskRecord task = anyTaskForId(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options, onTop);
+ options.setLaunchTaskId(taskId);
+ if (task != null) {
+ return task.getStack();
+ }
+ }
+
+ final int activityType = resolveActivityType(r, options, candidateTask);
+ T stack;
+
+ // Next preference for stack goes to the display Id set the candidate display.
+ if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
+ displayId = launchParams.mPreferredDisplayId;
+ }
+ if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
+ if (r != null) {
+ stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
+ launchParams);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ final ActivityDisplay display = getActivityDisplayOrCreate(displayId);
+ if (display != null) {
+ stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ }
+
+ // Give preference to the stack and display of the input task and activity if they match the
+ // mode we want to launch into.
+ stack = null;
+ ActivityDisplay display = null;
+ if (candidateTask != null) {
+ stack = candidateTask.getStack();
+ }
+ if (stack == null && r != null) {
+ stack = r.getStack();
+ }
+ if (stack != null) {
+ display = stack.getDisplay();
+ if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
+ int windowingMode = launchParams != null ? launchParams.mWindowingMode
+ : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ windowingMode = display.resolveWindowingMode(r, options, candidateTask,
+ activityType);
+ }
+ if (stack.isCompatible(windowingMode, activityType)) {
+ return stack;
+ }
+ if (windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
+ && display.getSplitScreenPrimaryStack() == stack
+ && candidateTask == stack.topTask()) {
+ // This is a special case when we try to launch an activity that is currently on
+ // top of split-screen primary stack, but is targeting split-screen secondary.
+ // In this case we don't want to move it to another stack.
+ // TODO(b/78788972): Remove after differentiating between preferred and required
+ // launch options.
+ return stack;
+ }
+ }
+ }
+
+ if (display == null || !canLaunchOnDisplay(r, display.mDisplayId)) {
+ display = getDefaultDisplay();
+ }
+
+ return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
+ }
+
+ /** @return true if activity record is null or can be launched on provided display. */
+ private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) {
+ if (r == null) {
+ return true;
+ }
+ return r.canBeLaunchedOnDisplay(displayId);
+ }
+
+ /**
+ * Get a topmost stack on the display, that is a valid launch stack for specified activity.
+ * If there is no such stack, new dynamic stack can be created.
+ * @param displayId Target display.
+ * @param r Activity that should be launched there.
+ * @param candidateTask The possible task the activity might be put in.
+ * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
+ */
+ private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+ @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options,
+ @Nullable LaunchParamsController.LaunchParams launchParams) {
+ final ActivityDisplay activityDisplay = getActivityDisplayOrCreate(displayId);
+ if (activityDisplay == null) {
+ throw new IllegalArgumentException(
+ "Display with displayId=" + displayId + " not found.");
+ }
+
+ if (!r.canBeLaunchedOnDisplay(displayId)) {
+ return null;
+ }
+
+ // If {@code r} is already in target display and its task is the same as the candidate task,
+ // the intention should be getting a launch stack for the reusable activity, so we can use
+ // the existing stack.
+ if (r.getDisplayId() == displayId && r.getTask() == candidateTask) {
+ return candidateTask.getStack();
+ }
+
+ // Return the topmost valid stack on the display.
+ for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = activityDisplay.getChildAt(i);
+ if (isValidLaunchStack(stack, r)) {
+ return stack;
+ }
+ }
+
+ // If there is no valid stack on the external display - check if new dynamic stack will do.
+ if (displayId != DEFAULT_DISPLAY) {
+ final int windowingMode;
+ if (launchParams != null) {
+ // When launch params is not null, we always defer to its windowing mode. Sometimes
+ // it could be unspecified, which indicates it should inherit windowing mode from
+ // display.
+ windowingMode = launchParams.mWindowingMode;
+ } else {
+ windowingMode = options != null ? options.getLaunchWindowingMode()
+ : r.getWindowingMode();
+ }
+ final int activityType =
+ options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
+ ? options.getLaunchActivityType() : r.getActivityType();
+ return activityDisplay.createStack(windowingMode, activityType, true /*onTop*/);
+ }
+
+ Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId);
+ return null;
+ }
+
+ ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+ @Nullable ActivityOptions options,
+ @Nullable LaunchParamsController.LaunchParams launchParams) {
+ return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
+ launchParams);
+ }
+
+ // TODO: Can probably be consolidated into getLaunchStack()...
+ private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r) {
+ switch (stack.getActivityType()) {
+ case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
+ case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
+ case ACTIVITY_TYPE_ASSISTANT: return r.isActivityTypeAssistant();
+ }
+ // There is a 1-to-1 relationship between stack and task when not in
+ // primary split-windowing mode.
+ if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ return false;
+ } else {
+ return r.supportsSplitScreenWindowingMode();
+ }
+ }
+
+ int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord task) {
+ // Preference is given to the activity type for the activity then the task since the type
+ // once set shouldn't change.
+ int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED;
+ if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) {
+ activityType = task.getActivityType();
+ }
+ if (activityType != ACTIVITY_TYPE_UNDEFINED) {
+ return activityType;
+ }
+ if (options != null) {
+ activityType = options.getLaunchActivityType();
+ }
+ return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD;
+ }
+
+ /**
+ * Get next focusable stack in the system. This will search through the stack on the same
+ * display as the current focused stack, looking for a focusable and visible stack, different
+ * from the target stack. If no valid candidates will be found, it will then go through all
+ * displays and stacks in last-focused order.
+ *
+ * @param currentFocus The stack that previously had focus.
+ * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next
+ * candidate.
+ * @return Next focusable {@link ActivityStack}, {@code null} if not found.
+ */
+ ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
+ boolean ignoreCurrent) {
+ // First look for next focusable stack on the same display
+ final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
+ currentFocus, ignoreCurrent);
+ if (preferredFocusableStack != null) {
+ return preferredFocusableStack;
+ }
+ if (preferredDisplay.supportsSystemDecorations()) {
+ // Stop looking for focusable stack on other displays because the preferred display
+ // supports system decorations. Home activity would be launched on the same display if
+ // no focusable stack found.
+ return null;
+ }
+
+ // Now look through all displays
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ if (display == preferredDisplay) {
+ // We've already checked this one
+ continue;
+ }
+ final ActivityStack nextFocusableStack = display.getNextFocusableStack(currentFocus,
+ ignoreCurrent);
+ if (nextFocusableStack != null) {
+ return nextFocusableStack;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get next valid stack for launching provided activity in the system. This will search across
+ * displays and stacks in last-focused order for a focusable and visible stack, except those
+ * that are on a currently focused display.
+ *
+ * @param r The activity that is being launched.
+ * @param currentFocus The display that previously had focus and thus needs to be ignored when
+ * searching for the next candidate.
+ * @return Next valid {@link ActivityStack}, null if not found.
+ */
+ ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ if (display.mDisplayId == currentFocus) {
+ continue;
+ }
+ final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
+ null /* options */, null /* launchParams */);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
+ boolean handleAppDied(WindowProcessController app) {
+ boolean hasVisibleActivities = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ hasVisibleActivities |= stack.handleAppDiedLocked(app);
+ }
+ }
+ return hasVisibleActivities;
+ }
+
+ void closeSystemDialogs() {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.closeSystemDialogsLocked();
+ }
+ }
+ }
+
+ /** @return true if some activity was finished (or would have finished if doit were true). */
+ boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses,
+ boolean doit, boolean evenPersistent, int userId) {
+ boolean didSomething = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ if (stack.finishDisabledPackageActivitiesLocked(
+ packageName, filterByClasses, doit, evenPersistent, userId)) {
+ didSomething = true;
+ }
+ }
+ }
+ return didSomething;
+ }
+
+ void updateActivityApplicationInfo(ApplicationInfo aInfo) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.updateActivityApplicationInfoLocked(aInfo);
+ }
+ }
+ }
+
+ void finishVoiceTask(IVoiceInteractionSession session) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ final int numStacks = display.getChildCount();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.finishVoiceTask(session);
+ }
+ }
+ }
+
+ /**
+ * Removes stacks in the input windowing modes from the system if they are of activity type
+ * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
+ */
+ void removeStacksInWindowingModes(int... windowingModes) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ mActivityDisplays.get(i).removeStacksInWindowingModes(windowingModes);
+ }
+ }
+
+ void removeStacksWithActivityTypes(int... activityTypes) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ mActivityDisplays.get(i).removeStacksWithActivityTypes(activityTypes);
+ }
+ }
+
+ ActivityRecord topRunningActivity() {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityRecord topActivity = mActivityDisplays.get(i).topRunningActivity();
+ if (topActivity != null) {
+ return topActivity;
+ }
+ }
+ return null;
+ }
+
+ boolean allResumedActivitiesIdle() {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ // TODO(b/117135575): Check resumed activities on all visible stacks.
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ if (display.isSleeping()) {
+ // No resumed activities while display is sleeping.
+ continue;
+ }
+
+ // If the focused stack is not null or not empty, there should have some activities
+ // resuming or resumed. Make sure these activities are idle.
+ final ActivityStack stack = display.getFocusedStack();
+ if (stack == null || stack.numActivities() == 0) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.getResumedActivity();
+ if (resumedActivity == null || !resumedActivity.idle) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+ + stack.mStackId + " " + resumedActivity + " not idle");
+ }
+ return false;
+ }
+ }
+ // Send launch end powerhint when idle
+ sendPowerHintForLaunchEndIfNeeded();
+ return true;
+ }
+
+ boolean allResumedActivitiesVisible() {
+ boolean foundResumed = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord r = stack.getResumedActivity();
+ if (r != null) {
+ if (!r.nowVisible
+ || mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
+ return false;
+ }
+ foundResumed = true;
+ }
+ }
+ }
+ return foundResumed;
+ }
+
+ boolean allPausedActivitiesComplete() {
+ boolean pausing = true;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord r = stack.mPausingActivity;
+ if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG_STATES,
+ "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
+ pausing = false;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+ return pausing;
+ }
+
+ /**
+ * Find all visible task stacks containing {@param userId} and intercept them with an activity
+ * to block out the contents and possibly start a credential-confirming intent.
+ *
+ * @param userId user handle for the locked managed profile.
+ */
+ void lockAllProfileTasks(@UserIdInt int userId) {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final List<TaskRecord> tasks = stack.getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
+ final TaskRecord task = tasks.get(taskNdx);
+
+ // Check the task for a top activity belonging to userId, or returning a
+ // result to an activity belonging to userId. Example case: a document
+ // picker for personal files, opened by a work app, should still get locked.
+ if (taskTopActivityIsUser(task, userId)) {
+ mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
+ task.taskId, userId);
+ }
+ }
+ }
+ }
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ /**
+ * Detects whether we should show a lock screen in front of this task for a locked user.
+ * <p>
+ * We'll do this if either of the following holds:
+ * <ul>
+ * <li>The top activity explicitly belongs to {@param userId}.</li>
+ * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
+ * </ul>
+ *
+ * @return {@code true} if the top activity looks like it belongs to {@param userId}.
+ */
+ private boolean taskTopActivityIsUser(TaskRecord task, @UserIdInt int userId) {
+ // To handle the case that work app is in the task but just is not the top one.
+ final ActivityRecord activityRecord = task.getTopActivity();
+ final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
+
+ return (activityRecord != null && activityRecord.userId == userId)
+ || (resultTo != null && resultTo.userId == userId);
+ }
+
+ void cancelInitializingActivities() {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.cancelInitializingActivities();
+ }
+ }
+ }
+
+ TaskRecord anyTaskForId(int id) {
+ return anyTaskForId(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
+ }
+
+ TaskRecord anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode) {
+ return anyTaskForId(id, matchMode, null, !ON_TOP);
+ }
+
+ /**
+ * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
+ * @param id Id of the task we would like returned.
+ * @param matchMode The mode to match the given task id in.
+ * @param aOptions The activity options to use for restoration. Can be null.
+ * @param onTop If the stack for the task should be the topmost on the display.
+ */
+ TaskRecord anyTaskForId(int id, @AnyTaskForIdMatchTaskMode int matchMode,
+ @Nullable ActivityOptions aOptions, boolean onTop) {
+ // If options are set, ensure that we are attempting to actually restore a task
+ if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
+ throw new IllegalArgumentException("Should not specify activity options for non-restore"
+ + " lookup");
+ }
+
+ int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final TaskRecord task = stack.taskForIdLocked(id);
+ if (task == null) {
+ continue;
+ }
+ if (aOptions != null) {
+ // Resolve the stack the task should be placed in now based on options
+ // and reparent if needed.
+ final ActivityStack launchStack =
+ getLaunchStack(null, aOptions, task, onTop);
+ if (launchStack != null && stack != launchStack) {
+ final int reparentMode = onTop
+ ? REPARENT_MOVE_STACK_TO_FRONT : REPARENT_LEAVE_STACK_IN_PLACE;
+ task.reparent(launchStack, onTop, reparentMode, ANIMATE, DEFER_RESUME,
+ "anyTaskForId");
+ }
+ }
+ return task;
+ }
+ }
+
+ // If we are matching stack tasks only, return now
+ if (matchMode == MATCH_TASK_IN_STACKS_ONLY) {
+ return null;
+ }
+
+ // Otherwise, check the recent tasks and return if we find it there and we are not restoring
+ // the task from recents
+ if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
+ final TaskRecord task = mStackSupervisor.mRecentTasks.getTask(id);
+
+ if (task == null) {
+ if (DEBUG_RECENTS) {
+ Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
+ }
+
+ return null;
+ }
+
+ if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
+ return task;
+ }
+
+ // Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
+ if (!mStackSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) {
+ if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
+ "Couldn't restore task id=" + id + " found in recents");
+ return null;
+ }
+ if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents");
+ return task;
+ }
+
+ ActivityRecord isInAnyStack(IBinder token) {
+ int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord r = stack.isInStackLocked(token);
+ if (r != null) {
+ return r;
+ }
+ }
+ }
+ return null;
+ }
+
+ @VisibleForTesting
+ void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
+ @WindowConfiguration.ActivityType int ignoreActivityType,
+ @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid,
+ boolean allowed) {
+ mStackSupervisor.mRunningTasks.getTasks(maxNum, list, ignoreActivityType,
+ ignoreWindowingMode, mActivityDisplays, callingUid, allowed);
+ }
+
+ void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) {
+ boolean sendHint = forceSend;
+
+ if (!sendHint) {
+ // Send power hint if we don't know what we're launching yet
+ sendHint = targetActivity == null || targetActivity.app == null;
+ }
+
+ if (!sendHint) { // targetActivity != null
+ // Send power hint when the activity's process is different than the current resumed
+ // activity on all displays, or if there are no resumed activities in the system.
+ boolean noResumedActivities = true;
+ boolean allFocusedProcessesDiffer = true;
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
+ final ActivityRecord resumedActivity = activityDisplay.getResumedActivity();
+ final WindowProcessController resumedActivityProcess =
+ resumedActivity == null ? null : resumedActivity.app;
+
+ noResumedActivities &= resumedActivityProcess == null;
+ if (resumedActivityProcess != null) {
+ allFocusedProcessesDiffer &= !resumedActivityProcess.equals(targetActivity.app);
+ }
+ }
+ sendHint = noResumedActivities || allFocusedProcessesDiffer;
+ }
+
+ if (sendHint && mService.mPowerManagerInternal != null) {
+ mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 1);
+ mPowerHintSent = true;
+ }
+ }
+
+ void sendPowerHintForLaunchEndIfNeeded() {
+ // Trigger launch power hint if activity is launched
+ if (mPowerHintSent && mService.mPowerManagerInternal != null) {
+ mService.mPowerManagerInternal.powerHint(PowerHint.LAUNCH, 0);
+ mPowerHintSent = false;
+ }
+ }
+
+ private void calculateDefaultMinimalSizeOfResizeableTasks() {
+ final Resources res = mService.mContext.getResources();
+ final float minimalSize = res.getDimension(
+ com.android.internal.R.dimen.default_minimal_size_resizable_task);
+ final DisplayMetrics dm = res.getDisplayMetrics();
+
+ mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
+ }
+
+ /**
+ * Dumps the activities matching the given {@param name} in the either the focused stack
+ * or all visible stacks if {@param dumpVisibleStacks} is true.
+ */
+ ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleStacksOnly,
+ boolean dumpFocusedStackOnly) {
+ if (dumpFocusedStackOnly) {
+ return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
+ } else {
+ ArrayList<ActivityRecord> activities = new ArrayList<>();
+ int numDisplays = mActivityDisplays.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
+ activities.addAll(stack.getDumpActivitiesLocked(name));
+ }
+ }
+ }
+ return activities;
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix);
+ pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ display.dump(pw, prefix);
+ }
+ }
+
+ /**
+ * Dump all connected displays' configurations.
+ * @param prefix Prefix to apply to each line of the dump.
+ */
+ void dumpDisplayConfigs(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println("Display override configurations:");
+ final int displayCount = mActivityDisplays.size();
+ for (int i = 0; i < displayCount; i++) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(i);
+ pw.print(prefix); pw.print(" "); pw.print(activityDisplay.mDisplayId); pw.print(": ");
+ pw.println(activityDisplay.getOverrideConfiguration());
+ }
+ }
+
+ public void dumpDisplays(PrintWriter pw) {
+ for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+ final ActivityDisplay display = mActivityDisplays.get(i);
+ pw.print("[id:" + display.mDisplayId + " stacks:");
+ display.dumpStacks(pw);
+ pw.print("]");
+ }
+ }
+
+ boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
+ String dumpPackage) {
+ boolean printed = false;
+ boolean needSep = false;
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
+ pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
+ pw.println(" (activities from top to bottom):");
+ final ActivityDisplay display = mActivityDisplays.get(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ pw.println();
+ pw.println(" Stack #" + stack.mStackId
+ + ": type=" + activityTypeToString(stack.getActivityType())
+ + " mode=" + windowingModeToString(stack.getWindowingMode()));
+ pw.println(" isSleeping=" + stack.shouldSleepActivities());
+ pw.println(" mBounds=" + stack.getOverrideBounds());
+
+ printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
+ needSep);
+
+ printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
+ !dumpAll, false, dumpPackage, true,
+ " Running activities (most recent first):", null);
+
+ needSep = printed;
+ boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+ " mPausingActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ pr = printThisActivity(pw, stack.getResumedActivity(), dumpPackage, needSep,
+ " mResumedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ if (dumpAll) {
+ pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+ " mLastPausedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = true;
+ }
+ printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
+ needSep, " mLastNoHistoryActivity: ");
+ }
+ needSep = printed;
+ }
+ printThisActivity(pw, activityDisplay.getResumedActivity(), dumpPackage, needSep,
+ " ResumedActivity:");
+ }
+
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mFinishingActivities, " ",
+ "Fin", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to finish:", null);
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mStoppingActivities, " ",
+ "Stop", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to stop:", null);
+ printed |= dumpHistoryList(fd, pw,
+ mStackSupervisor.mActivitiesWaitingForVisibleActivity, " ", "Wait",
+ false, !dumpAll, false, dumpPackage, true,
+ " Activities waiting for another to become visible:", null);
+ printed |= dumpHistoryList(fd, pw, mStackSupervisor.mGoingToSleepActivities,
+ " ", "Sleep", false, !dumpAll,
+ false, dumpPackage, true, " Activities waiting to sleep:", null);
+
+ return printed;
+ }
+
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
+ for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayNdx);
+ activityDisplay.writeToProto(proto, DISPLAYS);
+ }
+ mStackSupervisor.getKeyguardController().writeToProto(proto, KEYGUARD_CONTROLLER);
+ // TODO(b/111541062): Update tests to look for resumed activities on all displays
+ final ActivityStack focusedStack = getTopDisplayFocusedStack();
+ if (focusedStack != null) {
+ proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
+ final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
+ if (focusedActivity != null) {
+ focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
+ }
+ } else {
+ proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
+ }
+ proto.write(IS_HOME_RECENTS_COMPONENT,
+ mStackSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser));
+ mService.getActivityStartController().writeToProto(proto, PENDING_ACTIVITIES);
+ proto.end(token);
+ }
+
+ private final class SleepTokenImpl extends ActivityTaskManagerInternal.SleepToken {
+ private final String mTag;
+ private final long mAcquireTime;
+ private final int mDisplayId;
+
+ public SleepTokenImpl(String tag, int displayId) {
+ mTag = tag;
+ mDisplayId = displayId;
+ mAcquireTime = SystemClock.uptimeMillis();
+ }
+
+ @Override
+ public void release() {
+ synchronized (mService.mGlobalLock) {
+ removeSleepToken(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "{\"" + mTag + "\", display " + mDisplayId
+ + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b483fd3..80d1368 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -82,12 +82,16 @@
import java.util.function.Consumer;
/** Root {@link WindowContainer} for the device. */
-class RootWindowContainer extends WindowContainer<DisplayContent> {
+class RootWindowContainer extends WindowContainer<DisplayContent>
+ implements ConfigurationContainerListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
+ // TODO: Remove after object merge with RootActivityContainer.
+ private RootActivityContainer mRootActivityContainer;
+
private Object mLastWindowFreezeSource = null;
private Session mHoldScreen = null;
private float mScreenBrightness = -1;
@@ -145,6 +149,13 @@
mHandler = new MyHandler(service.mH.getLooper());
}
+ void setRootActivityContainer(RootActivityContainer container) {
+ mRootActivityContainer = container;
+ if (container != null) {
+ container.registerConfigurationChangeListener(this);
+ }
+ }
+
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
boolean changed = false;
int topFocusedDisplayId = INVALID_DISPLAY;
@@ -189,9 +200,7 @@
mService.mH.sendMessage(msg);
}
});
- final WindowState topFocusedWindow = getTopFocusedDisplayContent().mCurrentFocus;
- mService.mInputManager.setFocusedWindow(
- topFocusedWindow != null ? topFocusedWindow.mInputWindowHandle : null);
+
return changed;
}
@@ -224,6 +233,7 @@
final DisplayContent existing = getDisplayContent(displayId);
if (existing != null) {
+ initializeDisplayOverrideConfiguration(controller, existing);
existing.setController(controller);
return existing;
}
@@ -233,6 +243,7 @@
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
+ initializeDisplayOverrideConfiguration(controller, dc);
if (mService.mDisplayManagerInternal != null) {
mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
@@ -245,6 +256,19 @@
return dc;
}
+ /**
+ * The display content may have configuration set from {@link #DisplayWindowSettings}. This
+ * callback let the owner of container know there is existing configuration to prevent the
+ * values from being replaced by the initializing {@link #ActivityDisplay}.
+ */
+ private void initializeDisplayOverrideConfiguration(DisplayWindowController controller,
+ DisplayContent displayContent) {
+ if (controller != null && controller.mListener != null) {
+ controller.mListener.onInitializeOverrideConfiguration(
+ displayContent.getOverrideConfiguration());
+ }
+ }
+
boolean isLayoutNeeded() {
final int numDisplays = mChildren.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
@@ -497,9 +521,8 @@
if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin,
"RECOVER DESTROY", false);
winAnimator.destroySurface();
- if (winAnimator.mWin.mAppToken != null
- && winAnimator.mWin.mAppToken.getController() != null) {
- winAnimator.mWin.mAppToken.getController().removeStartingWindow();
+ if (winAnimator.mWin.mAppToken != null) {
+ winAnimator.mWin.mAppToken.removeStartingWindow();
}
}
@@ -1015,9 +1038,8 @@
@Override
void positionChildAt(int position, DisplayContent child, boolean includingParents) {
super.positionChildAt(position, child, includingParents);
- final RootWindowContainerController controller = getController();
- if (controller != null) {
- controller.onChildPositionChanged(child, position);
+ if (mRootActivityContainer != null) {
+ mRootActivityContainer.onChildPositionChanged(child.getController(), position);
}
}
@@ -1027,11 +1049,6 @@
}
@Override
- RootWindowContainerController getController() {
- return (RootWindowContainerController) super.getController();
- }
-
- @Override
void scheduleAnimation() {
mService.scheduleAnimationLocked();
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainerController.java b/services/core/java/com/android/server/wm/RootWindowContainerController.java
deleted file mode 100644
index 1176220..0000000
--- a/services/core/java/com/android/server/wm/RootWindowContainerController.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.android.server.wm;
-
-/**
- * Controller for the root container. This is created by activity manager to link activity
- * stack supervisor to the root window container they use in window manager.
- */
-public class RootWindowContainerController
- extends WindowContainerController<RootWindowContainer, RootWindowContainerListener> {
-
- public RootWindowContainerController(RootWindowContainerListener listener) {
- super(listener, WindowManagerService.getInstance());
- synchronized (mGlobalLock) {
- mRoot.setController(this);
- }
- }
-
- void onChildPositionChanged(DisplayContent child, int position) {
- // This callback invokes to AM directly so here assumes AM lock is held. If there is another
- // path called only with WM lock, it should change to use handler to post or move outside of
- // WM lock with adding AM lock.
- mListener.onChildPositionChanged(child.getController(), position);
- }
-
- /** Move the display to the given position. */
- public void positionChildAt(DisplayWindowController child, int position) {
- synchronized (mGlobalLock) {
- mContainer.positionChildAt(position, child.mContainer);
- }
- }
-}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainerListener.java b/services/core/java/com/android/server/wm/RootWindowContainerListener.java
deleted file mode 100644
index f413e3f7..0000000
--- a/services/core/java/com/android/server/wm/RootWindowContainerListener.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-package com.android.server.wm;
-
-/**
- * Interface used by the creator of {@link RootWindowContainerController} to notify the changes to
- * the display container in activity manager.
- */
-public interface RootWindowContainerListener extends WindowContainerListener {
- /** Called when the z-order of display is changed. */
- void onChildPositionChanged(DisplayWindowController childController, int position);
-}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index df97027..3947bd4 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -222,7 +222,7 @@
}
public ScreenRotationAnimation(Context context, DisplayContent displayContent,
- boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
+ boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) {
mService = service;
mContext = context;
mDisplayContent = displayContent;
@@ -234,7 +234,7 @@
final int originalWidth;
final int originalHeight;
DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (forceDefaultOrientation) {
+ if (fixedToUserRotation) {
// Emulated orientation.
mForceDefaultOrientation = true;
originalWidth = displayContent.mBaseDisplayWidth;
@@ -261,7 +261,7 @@
try {
mSurfaceControl = displayContent.makeOverlay()
.setName("ScreenshotSurface")
- .setSize(mWidth, mHeight)
+ .setBufferSize(mWidth, mHeight)
.setSecure(isSecure)
.build();
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 6838c55..37b5a7c 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -50,6 +50,7 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import android.view.InsetsState;
import android.view.WindowManager;
import com.android.internal.os.logging.MetricsLoggerWrapper;
@@ -153,17 +154,21 @@
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+ InsetsState outInsetsState) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
- outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
+ outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,
+ outInsetsState);
}
@Override
public int addToDisplayWithoutInputChannel(IWindow window, int seq, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets) {
+ int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
+ InsetsState outInsetsState) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
new Rect() /* outFrame */, outContentInsets, outStableInsets, null /* outOutsets */,
- new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */);
+ new DisplayCutout.ParcelableWrapper() /* cutout */, null /* outInputChannel */,
+ outInsetsState);
}
@Override
@@ -182,7 +187,7 @@
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
- Surface outSurface) {
+ Surface outSurface, InsetsState outInsetsState) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -190,7 +195,7 @@
requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, cutout,
- mergedConfiguration, outSurface);
+ mergedConfiguration, outSurface, outInsetsState);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index e97b366..82f2ad8 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -24,12 +23,9 @@
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.Region;
-import android.view.Display;
-import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
class StrictModeFlash {
private static final String TAG = TAG_WITH_CLASS_NAME ? "StrictModeFlash" : TAG_WM;
@@ -46,7 +42,7 @@
try {
ctrl = dc.makeOverlay()
.setName("StrictModeFlash")
- .setSize(1, 1)
+ .setBufferSize(1, 1)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101); // one more than Watermark? arbitrary.
@@ -122,7 +118,7 @@
}
mLastDW = dw;
mLastDH = dh;
- mSurfaceControl.setSize(dw, dh);
+ mSurfaceControl.setBufferSize(dw, dh);
mDrawNeeded = true;
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 31c0c7f..11068ce 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -302,8 +302,7 @@
if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
final SurfaceControl.Builder builder = mAnimatable.makeAnimationLeash()
.setParent(mAnimatable.getAnimationLeashParent())
- .setName(surface + " - animation-leash")
- .setSize(width, height);
+ .setName(surface + " - animation-leash");
final SurfaceControl leash = builder.build();
t.setWindowCrop(leash, width, height);
if (!hidden) {
diff --git a/services/core/java/com/android/server/wm/TEST_MAPPING b/services/core/java/com/android/server/wm/TEST_MAPPING
index 0c9a14b..bbe5424 100644
--- a/services/core/java/com/android/server/wm/TEST_MAPPING
+++ b/services/core/java/com/android/server/wm/TEST_MAPPING
@@ -1,17 +1,6 @@
{
"presubmit": [
{
- "name": "CtsWindowManagerDeviceTestCases",
- "options": [
- {
- "include-annotation": "android.platform.test.annotations.Presubmit"
- },
- {
- "exclude-annotation": "android.support.test.filters.FlakyTest"
- }
- ]
- },
- {
"name": "FrameworksServicesTests",
"options": [
{
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c9800f8..6904ef5 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -302,7 +302,6 @@
@Override
void onDisplayChanged(DisplayContent dc) {
- updateSurfaceSize(dc);
adjustBoundsForDisplayChangeIfNeeded(dc);
super.onDisplayChanged(dc);
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 117984a..4ae2a79 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -138,7 +138,7 @@
// STEP 1: Determine the display to launch the activity/task.
final int displayId = getPreferredLaunchDisplay(task, options, source, currentParams);
outParams.mPreferredDisplayId = displayId;
- ActivityDisplay display = mSupervisor.getActivityDisplay(displayId);
+ ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay(displayId);
if (DEBUG) {
appendLog("display-id=" + outParams.mPreferredDisplayId + " display-windowing-mode="
+ display.getWindowingMode());
@@ -300,12 +300,14 @@
displayId = stack.mDisplayId;
}
- if (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) == null) {
+ if (displayId != INVALID_DISPLAY
+ && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) == null) {
displayId = currentParams.mPreferredDisplayId;
}
displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;
- return (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) != null)
+ return (displayId != INVALID_DISPLAY
+ && mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) != null)
? displayId : DEFAULT_DISPLAY;
}
@@ -606,7 +608,8 @@
|| displayBounds.height() < inOutBounds.height()) {
// There is no way for us to fit the bounds in the display without changing width
// or height. Just move the start to align with the display.
- final int layoutDirection = mSupervisor.getConfiguration().getLayoutDirection();
+ final int layoutDirection =
+ mSupervisor.mRootActivityContainer.getConfiguration().getLayoutDirection();
final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
? displayBounds.width() - inOutBounds.width()
: 0;
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index 8120dec..d50af38 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import android.annotation.NonNull;
import android.graphics.Bitmap;
@@ -330,7 +330,7 @@
// mWriteQueue.add(new TaskWriteQueueItem(task));
final int taskId = task.taskId;
- if (mStackSupervisor.anyTaskForIdLocked(taskId,
+ if (mService.mRootActivityContainer.anyTaskForId(taskId,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
// Should not happen.
Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 7182ad6..b88e581 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -33,6 +33,7 @@
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Binder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
@@ -261,7 +262,7 @@
mClientChannel, mService.mAnimationHandler.getLooper(),
mService.mAnimator.getChoreographer());
- mDragApplicationHandle = new InputApplicationHandle(null);
+ mDragApplicationHandle = new InputApplicationHandle(new Binder());
mDragApplicationHandle.name = TAG;
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
@@ -269,7 +270,7 @@
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
display.getDisplayId());
mDragWindowHandle.name = TAG;
- mDragWindowHandle.inputChannel = mServerChannel;
+ mDragWindowHandle.token = mServerChannel.getToken();
mDragWindowHandle.layer = mService.getDragLayerLocked();
mDragWindowHandle.layoutParamsFlags = 0;
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 51567a0..5a70325 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -21,10 +21,14 @@
import android.annotation.Nullable;
import android.app.IActivityTaskManager;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Slog;
+import android.view.Display;
+import android.view.SurfaceControl;
import android.view.IWindow;
import com.android.internal.annotations.GuardedBy;
@@ -39,10 +43,14 @@
private final InputManagerService mInputManager;
private final IActivityTaskManager mActivityManager;
private final Handler mHandler;
+ private SurfaceControl mInputSurface;
+ private DisplayContent mPositioningDisplay;
@GuardedBy("WindowManagerSerivce.mWindowMap")
private @Nullable TaskPositioner mTaskPositioner;
+ private final Rect mTmpClipRect = new Rect();
+
boolean isPositioningLocked() {
return mTaskPositioner != null;
}
@@ -59,6 +67,43 @@
mHandler = new Handler(looper);
}
+ void hideInputSurface(SurfaceControl.Transaction t, int displayId) {
+ if (mPositioningDisplay != null && mPositioningDisplay.getDisplayId() == displayId
+ && mInputSurface != null) {
+ t.hide(mInputSurface);
+ }
+ }
+
+ void showInputSurface(SurfaceControl.Transaction t, int displayId) {
+ if (mPositioningDisplay == null || mPositioningDisplay.getDisplayId() != displayId) {
+ return;
+ }
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
+ if (mInputSurface == null) {
+ mInputSurface = mService.makeSurfaceBuilder(dc.getSession())
+ .setContainerLayer(true)
+ .setName("Drag and Drop Input Consumer").build();
+ }
+
+ final InputWindowHandle h = getDragWindowHandleLocked();
+ if (h == null) {
+ Slog.w(TAG_WM, "Drag is in progress but there is no "
+ + "drag window handle.");
+ return;
+ }
+
+ t.show(mInputSurface);
+ t.setInputWindowInfo(mInputSurface, h);
+ t.setLayer(mInputSurface, Integer.MAX_VALUE);
+
+ final Display display = dc.getDisplay();
+ final Point p = new Point();
+ display.getRealSize(p);
+
+ mTmpClipRect.set(0, 0, p.x, p.y);
+ t.setWindowCrop(mInputSurface, mTmpClipRect);
+ }
+
boolean startMovingTask(IWindow window, float startX, float startY) {
WindowState win = null;
synchronized (mService.mGlobalLock) {
@@ -122,6 +167,7 @@
Slog.w(TAG_WM, "startPositioningLocked: Invalid display content " + win);
return false;
}
+ mPositioningDisplay = displayContent;
mTaskPositioner = TaskPositioner.create(mService);
mTaskPositioner.register(displayContent);
@@ -157,6 +203,7 @@
mTaskPositioner.unregister();
mTaskPositioner = null;
}
+ mPositioningDisplay = null;
}
});
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index eec10ab..8a3dbad 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -472,8 +472,8 @@
}
mResizeMode = resizeMode;
mWindowContainerController.setResizeable(resizeMode);
- mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
void setTaskDockedResizing(boolean resizing) {
@@ -544,10 +544,9 @@
// this won't cause tons of irrelevant windows being preserved because only
// activities in this task may experience a bounds change. Configs for other
// activities stay the same.
- mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
- preserveWindow);
+ mService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
if (!kept) {
- mService.mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
+ mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -623,6 +622,7 @@
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
+ final RootActivityContainer root = mService.mRootActivityContainer;
final WindowManagerService windowManager = mService.mWindowManager;
final ActivityStack sourceStack = getStack();
final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
@@ -655,7 +655,7 @@
boolean kept = true;
try {
final ActivityRecord r = topRunningActivityLocked();
- final boolean wasFocused = r != null && supervisor.isTopDisplayFocusedStack(sourceStack)
+ final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
&& (topRunningActivityLocked() == r);
final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
@@ -748,8 +748,8 @@
if (!deferResume) {
// The task might have already been running and its visibility needs to be synchronized
// with the visibility of the stack / windows.
- supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
- supervisor.resumeFocusedStacksTopActivitiesLocked();
+ root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
+ root.resumeFocusedStacksTopActivities();
}
// TODO: Handle incorrect request to move before the actual move, not after.
@@ -982,7 +982,7 @@
@Override
protected void onParentChanged() {
super.onParentChanged();
- mService.mStackSupervisor.updateUIDsPresentOnDisplay();
+ mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
// Close up recents linked list.
@@ -1143,7 +1143,7 @@
}
boolean okToShowLocked() {
- // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
+ // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is
// okay to show the activity when locked.
return mService.mStackSupervisor.isCurrentProfileLocked(userId)
|| topRunningActivityLocked() != null;
@@ -1182,7 +1182,7 @@
mActivities.add(newTop);
// Make sure window manager is aware of the position change.
- mWindowContainerController.positionChildAtTop(newTop.mWindowContainerController);
+ mWindowContainerController.positionChildAtTop(newTop.mAppWindowToken);
updateEffectiveIntent();
setFrontOfTask();
@@ -1264,17 +1264,15 @@
mService.notifyTaskPersisterLocked(this, false);
}
- // Sync. with window manager
- final AppWindowContainerController appController = r.getWindowContainerController();
- if (appController != null) {
+ if (r.mAppWindowToken != null) {
// Only attempt to move in WM if the child has a controller. It is possible we haven't
// created controller for the activity we are starting yet.
- mWindowContainerController.positionChildAt(appController, index);
+ mWindowContainerController.positionChildAt(r.mAppWindowToken, index);
}
// Make sure the list of display UID whitelists is updated
// now that this record is in a new task.
- mService.mStackSupervisor.updateUIDsPresentOnDisplay();
+ mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
/**
@@ -1683,9 +1681,9 @@
// to do this for the pinned stack as the bounds are controlled by the system.
if (!inPinnedWindowingMode()) {
final int defaultMinSizeDp =
- mService.mStackSupervisor.mDefaultMinSizeOfResizeableTaskDp;
+ mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
final ActivityDisplay display =
- mService.mStackSupervisor.getActivityDisplay(mStack.mDisplayId);
+ mService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
final float density =
(float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
final int defaultMinSize = (int) (defaultMinSizeDp * density);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index a7b0272..9a56606 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -32,6 +32,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.getColorViewLeftInset;
@@ -65,6 +66,7 @@
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -141,6 +143,7 @@
final Rect taskBounds;
final Rect tmpContentInsets = new Rect();
final Rect tmpStableInsets = new Rect();
+ final InsetsState mTmpInsetsState = new InsetsState();
final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
int backgroundColor = WHITE;
int statusBarColor = 0;
@@ -201,7 +204,7 @@
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
View.GONE, token.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, tmpRect,
- tmpRect, tmpCutout, null);
+ tmpRect, tmpCutout, null, mTmpInsetsState);
if (res < 0) {
Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
return null;
@@ -217,7 +220,7 @@
try {
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
tmpFrame, tmpRect, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, tmpRect,
- tmpCutout, tmpMergedConfiguration, surface);
+ tmpCutout, tmpMergedConfiguration, surface, mTmpInsetsState);
} catch (RemoteException e) {
// Local call.
}
@@ -312,7 +315,7 @@
// Keep a reference to it such that it doesn't get destroyed when finalized.
mChildSurfaceControl = new SurfaceControl.Builder(session)
.setName(mTitle + " - task-snapshot-surface")
- .setSize(buffer.getWidth(), buffer.getHeight())
+ .setBufferSize(buffer.getWidth(), buffer.getHeight())
.setFormat(buffer.getFormat())
.build();
Surface surface = new Surface();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 64f4ba5..5deb4f1 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -248,7 +248,6 @@
getRawBounds(mTmpRect);
final Rect stackBounds = getBounds();
getPendingTransaction()
- .setSize(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
.setWindowCrop(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
.setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
mTmpRect.top - stackBounds.top);
@@ -751,7 +750,6 @@
if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
return;
}
- transaction.setSize(mSurfaceControl, width, height);
transaction.setWindowCrop(mSurfaceControl, width, height);
mLastSurfaceSize.set(width, height);
}
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index 59b2055..ec64d2e 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -16,6 +16,14 @@
package com.android.server.wm;
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.wm.ConfigurationContainer.BOUNDS_CHANGE_NONE;
+import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
+import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Rect;
@@ -24,18 +32,11 @@
import android.os.Message;
import android.util.EventLog;
import android.util.Slog;
+
import com.android.internal.annotations.VisibleForTesting;
import java.lang.ref.WeakReference;
-import static com.android.server.EventLogTags.WM_TASK_CREATED;
-import static com.android.server.wm.ConfigurationContainer.BOUNDS_CHANGE_NONE;
-import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-
/**
* Controller for the task container. This is created by activity manager to link task records to
* the task container they use in window manager.
@@ -103,16 +104,15 @@
}
}
- public void positionChildAtTop(AppWindowContainerController childController) {
- positionChildAt(childController, POSITION_TOP);
+ void positionChildAtTop(AppWindowToken aToken) {
+ positionChildAt(aToken, POSITION_TOP);
}
- public void positionChildAt(AppWindowContainerController childController, int position) {
+ void positionChildAt(AppWindowToken aToken, int position) {
synchronized (mService.mGlobalLock) {
- final AppWindowToken aToken = childController.mContainer;
if (aToken == null) {
Slog.w(TAG_WM,
- "Attempted to position of non-existing app : " + childController);
+ "Attempted to position of non-existing app");
return;
}
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 9216b66..e6ac059 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -20,19 +20,18 @@
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Paint.FontMetricsInt;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
-import android.graphics.Paint.FontMetricsInt;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
-import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
/**
* Displays a watermark on top of the window manager's windows.
@@ -116,7 +115,7 @@
try {
ctrl = dc.makeOverlay()
.setName("WatermarkSurface")
- .setSize(1, 1)
+ .setBufferSize(1, 1)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
ctrl.setLayerStack(mDisplay.getLayerStack());
@@ -133,7 +132,7 @@
if (mLastDW != dw || mLastDH != dh) {
mLastDW = dw;
mLastDH = dh;
- mSurfaceControl.setSize(dw, dh);
+ mSurfaceControl.setBufferSize(dw, dh);
mDrawNeeded = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 266006d..7e4c629 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -515,24 +515,6 @@
}
}
- /**
- * Update the surface size when display changed in order to avoid children being bound by the
- * old display size.
- *
- * Note that we don't want to apply this to all layers, but only limiting this to layers that
- * don't set their own size ({@link Task}, {@link WindowState} and {@link WindowToken}).
- */
- void updateSurfaceSize(DisplayContent dc) {
- if (mSurfaceControl == null) {
- return;
- }
-
- final int newSurfaceSize = dc.getSurfaceSize();
- if (mSurfaceControl.getWidth() != newSurfaceSize) {
- getPendingTransaction().setSize(mSurfaceControl, newSurfaceSize, newSurfaceSize);
- }
- }
-
void setWaitingForDrawnIfResizingChanged() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/WindowContainerListener.java b/services/core/java/com/android/server/wm/WindowContainerListener.java
index 4b3cd36..3d3d2e0 100644
--- a/services/core/java/com/android/server/wm/WindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/WindowContainerListener.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import android.content.res.Configuration;
+
/**
* Interface used by the owner/creator of the container to listen to changes with the container.
* @see WindowContainerController
@@ -23,4 +25,5 @@
public interface WindowContainerListener {
void registerConfigurationChangeListener(ConfigurationContainerListener listener);
void unregisterConfigurationChangeListener(ConfigurationContainerListener listener);
+ default void onInitializeOverrideConfiguration(Configuration config) {}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5df3451..4085f3d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -218,6 +218,7 @@
import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowContentFrameStats;
+import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.RemoveContentMode;
@@ -1111,7 +1112,8 @@
public int addWindow(Session session, IWindow client, int seq,
LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
- DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
+ DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
+ InsetsState outInsetsState) {
int[] appOp = new int[1];
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
@@ -1459,6 +1461,7 @@
outFrame, outContentInsets, outStableInsets, outOutsets, outDisplayCutout)) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR;
}
+ outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
if (mInTouchMode) {
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
@@ -1856,7 +1859,7 @@
long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
- Surface outSurface) {
+ Surface outSurface, InsetsState outInsetsState) {
int result = 0;
boolean configChanged;
final boolean hasStatusBarPermission =
@@ -2157,6 +2160,7 @@
outStableInsets, outOutsets);
outCutout.set(win.getWmDisplayCutout().getDisplayCutout());
outBackdropFrame.set(win.getBackdropFrame(win.getFrameLw()));
+ outInsetsState.set(displayContent.getInsetsStateController().getInsetsForDispatch(win));
if (localLOGV) Slog.v(
TAG_WM, "Relayout given client " + client.asBinder()
+ ", requestedWidth=" + requestedWidth
@@ -3587,6 +3591,17 @@
}
}
+ void setRotateForApp(int displayId, boolean enabled) {
+ synchronized (mGlobalLock) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to set rotate for app for a missing display.");
+ return;
+ }
+ display.getDisplayRotation().setFixedToUserRotation(enabled);
+ }
+ }
+
@Override
public void freezeRotation(int rotation) {
freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
@@ -5393,7 +5408,7 @@
displayContent.updateDisplayInfo();
screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
+ displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
this);
mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
screenRotationAnimation);
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bf77ba8..6865ce3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -76,6 +76,8 @@
getNextArgRequired());
case "set-user-rotation":
return runSetDisplayUserRotation(pw);
+ case "set-fix-to-user-rotation":
+ return runSetFixToUserRotation(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -297,6 +299,32 @@
}
}
+ private int runSetFixToUserRotation(PrintWriter pw) {
+ int displayId = Display.DEFAULT_DISPLAY;
+ String arg = getNextArgRequired();
+ if ("-d".equals(arg)) {
+ displayId = Integer.parseInt(getNextArgRequired());
+ arg = getNextArgRequired();
+ }
+
+ final boolean enabled;
+ switch (arg) {
+ case "enabled":
+ enabled = true;
+ break;
+ case "disabled":
+ enabled = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
+ + arg);
+ return -1;
+ }
+
+ mInternal.setRotateForApp(displayId, enabled);
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -316,6 +344,8 @@
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
pw.println(" Set user rotation mode and user rotation.");
+ pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
+ pw.println(" Enable or disable rotating display for app requested orientation.");
if (!IS_USER) {
pw.println(" tracing (start | stop)");
pw.println(" Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 484bd8c..578af2e 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -755,9 +755,9 @@
return;
}
final ActivityDisplay activityDisplay =
- mAtm.mStackSupervisor.getActivityDisplay(mDisplayId);
+ mAtm.mRootActivityContainer.getActivityDisplay(mDisplayId);
if (activityDisplay != null) {
- mAtm.mStackSupervisor.getActivityDisplay(
+ mAtm.mRootActivityContainer.getActivityDisplay(
mDisplayId).unregisterConfigurationChangeListener(this);
}
mDisplayId = INVALID_DISPLAY;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 6f044f3..cfd1f86 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -143,6 +143,7 @@
import static com.android.server.wm.WindowStateProto.WINDOW_FRAMES;
import android.annotation.CallSuper;
+import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -194,6 +195,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.policy.WindowManagerPolicy.DisplayContentInfo;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.utils.InsetUtils;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -578,6 +580,8 @@
*/
private boolean mIsDimming = false;
+ private @Nullable InsetsSourceProvider mInsetProvider;
+
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
void seamlesslyRotateIfAllowed(Transaction transaction, @Rotation int oldRotation,
@@ -1261,7 +1265,6 @@
@Override
void onDisplayChanged(DisplayContent dc) {
- updateSurfaceSize(dc);
super.onDisplayChanged(dc);
// Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
if (dc != null) {
@@ -2037,7 +2040,7 @@
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
- mInputWindowHandle.inputChannel = inputChannels[0];
+ mInputWindowHandle.token = mClient.asBinder();
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
@@ -2068,7 +2071,7 @@
mClientChannel.dispose();
mClientChannel = null;
}
- mInputWindowHandle.inputChannel = null;
+ mInputWindowHandle.token = null;
}
/** Returns true if the replacement window was removed. */
@@ -2167,11 +2170,15 @@
mTmpRect.inset(-delta, -delta);
}
region.set(mTmpRect);
- cropRegionToStackBoundsIfNeeded(region);
+ region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
} else {
// Not modal or full screen modal
getTouchableRegion(region);
}
+
+ // The area containing the shadows is not touchable.
+ region.translate(mAttrs.surfaceInsets.left, mAttrs.surfaceInsets.top);
+
return flags;
}
@@ -2392,11 +2399,11 @@
&& (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
&& ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
&& (mAppToken == null || mAppToken.windowsAreFocusable())
- && !canReceiveTouchInput();
+ && !cantReceiveTouchInput();
}
- /** @return true if this window desires touch events. */
- boolean canReceiveTouchInput() {
+ /** @return false if this window desires touch events. */
+ boolean cantReceiveTouchInput() {
return mAppToken != null && mAppToken.getTask() != null
&& mAppToken.getTask().mStack.shouldIgnoreInput();
}
@@ -2803,25 +2810,32 @@
}
void getTouchableRegion(Region outRegion) {
+ if (inPinnedWindowingMode() && !isFocused()) {
+ outRegion.setEmpty();
+ return;
+ }
+
final Rect frame = mWindowFrames.mFrame;
switch (mTouchableInsets) {
default:
case TOUCHABLE_INSETS_FRAME:
outRegion.set(frame);
+ outRegion.translate(-frame.left, -frame.top);
break;
case TOUCHABLE_INSETS_CONTENT:
applyInsets(outRegion, frame, mGivenContentInsets);
+ outRegion.translate(-frame.left, -frame.top);
break;
case TOUCHABLE_INSETS_VISIBLE:
applyInsets(outRegion, frame, mGivenVisibleInsets);
+ outRegion.translate(-frame.left, -frame.top);
break;
case TOUCHABLE_INSETS_REGION: {
outRegion.set(mGivenTouchableRegion);
- outRegion.translate(frame.left, frame.top);
break;
}
}
- cropRegionToStackBoundsIfNeeded(outRegion);
+ outRegion.translate(mAttrs.surfaceInsets.left, mAttrs.surfaceInsets.top);
}
private void cropRegionToStackBoundsIfNeeded(Region region) {
@@ -2945,6 +2959,18 @@
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ /**
+ * Called when the insets state changed.
+ */
+ void notifyInsetsChanged() {
+ try {
+ mClient.insetsChanged(
+ getDisplayContent().getInsetsStateController().getInsetsForDispatch(this));
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to deliver inset state change", e);
+ }
+ }
+
Rect getBackdropFrame(Rect frame) {
// When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
// start even if we haven't received the relayout window, so that the client requests
@@ -4766,6 +4792,14 @@
mWindowFrames.setContentChanged(false);
}
+ void setInsetProvider(InsetsSourceProvider insetProvider) {
+ mInsetProvider = insetProvider;
+ }
+
+ InsetsSourceProvider getInsetProvider() {
+ return mInsetProvider;
+ }
+
private final class MoveAnimationSpec implements AnimationSpec {
private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e090cc5..78a3fe5 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -861,7 +861,7 @@
// to find the surface size changed underneath it.
final boolean relayout = !w.mRelayoutCalled || w.mInRelayout;
if (relayout) {
- mSurfaceResized = mSurfaceController.setSizeInTransaction(
+ mSurfaceResized = mSurfaceController.setBufferSizeInTransaction(
mTmpSize.width(), mTmpSize.height(), recoveringMemory);
} else {
mSurfaceResized = false;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 6821e94..ce627e2 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -19,34 +19,28 @@
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowSurfaceControllerProto.LAYER;
import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN;
-import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.IBinder;
import android.os.Debug;
+import android.os.IBinder;
import android.os.Trace;
+import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowContentFrameStats;
-import android.view.Surface.OutOfResourcesException;
-import android.util.Slog;
-
-import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
class WindowSurfaceController {
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowSurfaceController" : TAG_WM;
@@ -106,7 +100,7 @@
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
- .setSize(w, h)
+ .setBufferSize(w, h)
.setFormat(format)
.setFlags(flags)
.setMetadata(windowType, ownerUid);
@@ -303,7 +297,7 @@
}
}
- boolean setSizeInTransaction(int width, int height, boolean recoveringMemory) {
+ boolean setBufferSizeInTransaction(int width, int height, boolean recoveringMemory) {
final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
if (surfaceResized) {
mSurfaceW = width;
@@ -312,7 +306,7 @@
try {
if (SHOW_TRANSACTIONS) logSurface(
"SIZE " + width + "x" + height, null);
- mSurfaceControl.setSize(width, height);
+ mSurfaceControl.setBufferSize(width, height);
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 0cf79b6..d8242f8 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -265,7 +265,6 @@
// to another display before the window behind
// it is ready.
- updateSurfaceSize(dc);
super.onDisplayChanged(dc);
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index ee8a08b..fcd9335 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -86,6 +86,7 @@
jmethodID notifySwitch;
jmethodID notifyInputChannelBroken;
jmethodID notifyANR;
+ jmethodID notifyFocusChanged;
jmethodID filterInputEvent;
jmethodID interceptKeyBeforeQueueing;
jmethodID interceptMotionBeforeQueueingNonInteractive;
@@ -147,15 +148,6 @@
return value ? "true" : "false";
}
-static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
- const sp<InputApplicationHandle>& inputApplicationHandle) {
- if (inputApplicationHandle == nullptr) {
- return nullptr;
- }
- return static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get())->
- getInputApplicationHandleObjLocalRef(env);
-}
-
static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, int32_t style,
PointerIcon* outPointerIcon, SpriteIcon* outSpriteIcon) {
status_t status = android_view_PointerIcon_loadSystemIcon(env,
@@ -249,6 +241,7 @@
const sp<IBinder>& token,
const std::string& reason);
virtual void notifyInputChannelBroken(const sp<IBinder>& token);
+ virtual void notifyFocusChanged(const sp<IBinder>& token);
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
@@ -342,6 +335,8 @@
mInteractive = true;
mInputManager = new InputManager(this, this);
+ defaultServiceManager()->addService(String16("inputflinger"),
+ mInputManager, false);
}
NativeInputManager::~NativeInputManager() {
@@ -656,13 +651,11 @@
JNIEnv* env = jniEnv();
- jobject inputApplicationHandleObj =
- getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
jobject tokenObj = javaObjectForIBinder(env, token);
jstring reasonObj = env->NewStringUTF(reason.c_str());
jlong newTimeout = env->CallLongMethod(mServiceObj,
- gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj,
+ gServiceClassInfo.notifyANR, tokenObj,
reasonObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
@@ -671,7 +664,6 @@
}
env->DeleteLocalRef(reasonObj);
- env->DeleteLocalRef(inputApplicationHandleObj);
return newTimeout;
}
@@ -691,6 +683,22 @@
}
}
+void NativeInputManager::notifyFocusChanged(const sp<IBinder>& token) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifyFocusChanged");
+#endif
+ ATRACE_CALL();
+
+ JNIEnv* env = jniEnv();
+
+ jobject tokenObj = javaObjectForIBinder(env, token);
+ if (tokenObj) {
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyFocusChanged,
+ tokenObj);
+ checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
+ }
+}
+
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
@@ -1715,10 +1723,13 @@
GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
"notifyInputChannelBroken", "(Landroid/os/IBinder;)V");
+
+ GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
+ "notifyFocusChanged", "(Landroid/os/IBinder;)V");
GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
"notifyANR",
- "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
+ "(Landroid/os/IBinder;Ljava/lang/String;)J");
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 6462d16..b9dabb9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -23,6 +23,9 @@
import com.android.server.SystemService;
+import java.util.Collections;
+import java.util.List;
+
/**
* Defines the required interface for IDevicePolicyManager implemenation.
*
@@ -97,4 +100,24 @@
@Override
public void installUpdateFromFile(ComponentName admin,
ParcelFileDescriptor updateFileDescriptor, StartInstallingUpdateCallback listener) {}
+
+ @Override
+ public void addCrossProfileCalendarPackage(ComponentName admin, String packageName) {
+ }
+
+ @Override
+ public boolean removeCrossProfileCalendarPackage(ComponentName admin, String packageName) {
+ return false;
+ }
+
+ @Override
+ public List<String> getCrossProfileCalendarPackages(ComponentName admin) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isPackageAllowedToAccessCalendarForUser(String packageName,
+ int userHandle) {
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7751b4a..6fbb850 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -74,8 +74,10 @@
.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker
.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
-import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_DEVICE_OWNER;
-import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
+import static com.android.server.devicepolicy.TransferOwnershipMetadataManager
+ .ADMIN_TYPE_DEVICE_OWNER;
+import static com.android.server.devicepolicy.TransferOwnershipMetadataManager
+ .ADMIN_TYPE_PROFILE_OWNER;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -908,8 +910,12 @@
private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
- private static final String TAG_METERED_DATA_DISABLED_PACKAGES
- = "metered_data_disabled_packages";
+ private static final String TAG_METERED_DATA_DISABLED_PACKAGES =
+ "metered_data_disabled_packages";
+ private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES =
+ "cross-profile-calendar-packages";
+ private static final String TAG_PACKAGE = "package";
+
DeviceAdminInfo info;
@@ -1030,6 +1036,9 @@
String startUserSessionMessage = null;
String endUserSessionMessage = null;
+ // The whitelist of packages that can access cross profile calendar APIs.
+ final Set<String> mCrossProfileCalendarPackages = new ArraySet<>();
+
ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
info = _info;
isParent = parent;
@@ -1299,6 +1308,12 @@
out.text(endUserSessionMessage);
out.endTag(null, TAG_END_USER_SESSION_MESSAGE);
}
+ if (!mCrossProfileCalendarPackages.isEmpty()) {
+ out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES);
+ writeAttributeValuesToXml(
+ out, TAG_PACKAGE, mCrossProfileCalendarPackages);
+ out.endTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES);
+ }
}
void writePackageListToXml(XmlSerializer out, String outerTag,
@@ -1491,6 +1506,9 @@
} else {
Log.w(LOG_TAG, "Missing text when loading end session message");
}
+ } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
+ readAttributeValues(
+ parser, TAG_PACKAGE, mCrossProfileCalendarPackages);
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -1706,6 +1724,8 @@
pw.print(prefix); pw.println("parentAdmin:");
parentAdmin.dump(prefix + " ", pw);
}
+ pw.print(prefix); pw.print("mCrossProfileCalendarPackages=");
+ pw.println(mCrossProfileCalendarPackages);
}
}
@@ -13339,9 +13359,77 @@
}
}
-
private boolean isDeviceAB() {
return "true".equalsIgnoreCase(android.os.SystemProperties
.get(AB_DEVICE_KEY, ""));
}
+
+ @Override
+ public void addCrossProfileCalendarPackage(ComponentName who, String packageName) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkStringNotEmpty(packageName, "Package name is null or empty");
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(
+ who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (admin.mCrossProfileCalendarPackages.add(packageName)) {
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ }
+ }
+ }
+
+ @Override
+ public boolean removeCrossProfileCalendarPackage(ComponentName who, String packageName) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkStringNotEmpty(packageName, "Package name is null or empty");
+
+ boolean isRemoved = false;
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(
+ who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ isRemoved = admin.mCrossProfileCalendarPackages.remove(packageName);
+ if (isRemoved) {
+ saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ }
+ }
+ return isRemoved;
+ }
+
+ @Override
+ public List<String> getCrossProfileCalendarPackages(ComponentName who) {
+ if (!mHasFeature) {
+ return Collections.emptyList();
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(
+ who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return new ArrayList<String>(admin.mCrossProfileCalendarPackages);
+ }
+ }
+
+ @Override
+ public boolean isPackageAllowedToAccessCalendarForUser(String packageName,
+ int userHandle) {
+ if (!mHasFeature) {
+ return false;
+ }
+ Preconditions.checkStringNotEmpty(packageName, "Package name is null or empty");
+
+ enforceCrossUsersPermission(userHandle);
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
+ if (admin != null && admin.mCrossProfileCalendarPackages != null) {
+ return admin.mCrossProfileCalendarPackages.contains(packageName);
+ }
+ }
+ return false;
+ }
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
index 38810dd..9fd797d 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
@@ -19,6 +19,7 @@
import static android.content.Context.INTELLIGENCE_MANAGER_SERVICE;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.content.ComponentName;
@@ -134,12 +135,13 @@
}
@Override
- public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId) {
+ public void finishSession(@UserIdInt int userId, @NonNull InteractionSessionId sessionId,
+ @Nullable List<ContentCaptureEvent> events) {
Preconditions.checkNotNull(sessionId);
synchronized (mLock) {
final IntelligencePerUserService service = getServiceForUserLocked(userId);
- service.finishSessionLocked(sessionId);
+ service.finishSessionLocked(sessionId, events);
}
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
index 051f0d6..9ab7e58 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
@@ -22,6 +22,7 @@
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.app.assist.AssistContent;
@@ -146,7 +147,8 @@
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
- public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
+ public void finishSessionLocked(@NonNull InteractionSessionId sessionId,
+ @Nullable List<ContentCaptureEvent> events) {
if (!isEnabledLocked()) {
return;
}
@@ -158,8 +160,18 @@
}
return;
}
+ if (events != null && !events.isEmpty()) {
+ // TODO(b/111276913): for now we're sending the events and the onDestroy() in 2 separate
+ // calls because it's not clear yet whether we'll change the manager to send events
+ // to the service directly (i.e., without passing through system server). Once we
+ // decide, we might need to split IIntelligenceService.onSessionLifecycle() in 2
+ // methods, one for start and another for finish (and passing the events to finish),
+ // otherwise the service might receive the 2 calls out of order.
+ session.sendEventsLocked(events);
+ }
if (mMaster.verbose) {
- Slog.v(TAG, "finishSession(): " + session);
+ Slog.v(TAG, "finishSession(" + (events == null ? 0 : events.size()) + " events): "
+ + session);
}
session.removeSelfLocked(true);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d6e6208..56f7cff 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -177,7 +177,7 @@
* them from the build system somehow.
*/
private static final String BACKUP_MANAGER_SERVICE_CLASS =
- "com.android.server.backup.GlobalBackupManagerService$Lifecycle";
+ "com.android.server.backup.BackupManagerService$Lifecycle";
private static final String APPWIDGET_SERVICE_CLASS =
"com.android.server.appwidget.AppWidgetService";
private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index dc55179b..c9b9f3e 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -146,13 +146,14 @@
final long identity = Binder.clearCallingIdentity();
try {
disabledMessage = dpmi.getPrintingDisabledReasonForUser(callingUserId);
+
+ if (disabledMessage != null) {
+ Toast.makeText(mContext, Looper.getMainLooper(), disabledMessage,
+ Toast.LENGTH_LONG).show();
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
- if (disabledMessage != null) {
- Toast.makeText(mContext, Looper.getMainLooper(), disabledMessage,
- Toast.LENGTH_LONG).show();
- }
try {
adapter.start();
} catch (RemoteException re) {
diff --git a/services/robotests/src/com/android/server/backup/GlobalBackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
similarity index 85%
rename from services/robotests/src/com/android/server/backup/GlobalBackupManagerServiceTest.java
rename to services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index 3108c80..ba4caf44 100644
--- a/services/robotests/src/com/android/server/backup/GlobalBackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -49,43 +49,43 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-/** Tests for the user-aware backup/restore system service {@link GlobalBackupManagerService}. */
+/** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */
@RunWith(RobolectricTestRunner.class)
@Presubmit
-public class GlobalBackupManagerServiceTest {
+public class BackupManagerServiceTest {
private static final String TEST_PACKAGE = "package";
private static final String TEST_TRANSPORT = "transport";
@Mock private UserBackupManagerService mUserBackupManagerService;
@Mock private TransportManager mTransportManager;
- private GlobalBackupManagerService mGlobalBackupManagerService;
+ private BackupManagerService mBackupManagerService;
private Context mContext;
- /** Initialize {@link GlobalBackupManagerService}. */
+ /** Initialize {@link BackupManagerService}. */
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
Application application = RuntimeEnvironment.application;
mContext = application;
- mGlobalBackupManagerService =
- new GlobalBackupManagerService(
+ mBackupManagerService =
+ new BackupManagerService(
application,
new Trampoline(application),
BackupManagerServiceTestUtils.startBackupThread(null),
new File(application.getCacheDir(), "base_state"),
new File(application.getCacheDir(), "data"),
mTransportManager);
- mGlobalBackupManagerService.setUserBackupManagerService(mUserBackupManagerService);
+ mBackupManagerService.setUserBackupManagerService(mUserBackupManagerService);
}
/**
- * Test verifying that {@link GlobalBackupManagerService#MORE_DEBUG} is set to {@code false}.
+ * Test verifying that {@link BackupManagerService#MORE_DEBUG} is set to {@code false}.
* This is specifically to prevent overloading the logs in production.
*/
@Test
public void testMoreDebug_isFalse() throws Exception {
- boolean moreDebug = GlobalBackupManagerService.MORE_DEBUG;
+ boolean moreDebug = BackupManagerService.MORE_DEBUG;
assertThat(moreDebug).isFalse();
}
@@ -101,7 +101,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testDataChanged_callsDataChangedForUser() throws Exception {
- mGlobalBackupManagerService.dataChanged(TEST_PACKAGE);
+ mBackupManagerService.dataChanged(TEST_PACKAGE);
verify(mUserBackupManagerService).dataChanged(TEST_PACKAGE);
}
@@ -111,7 +111,7 @@
public void testAgentConnected_callsAgentConnectedForUser() throws Exception {
IBinder agentBinder = mock(IBinder.class);
- mGlobalBackupManagerService.agentConnected(TEST_PACKAGE, agentBinder);
+ mBackupManagerService.agentConnected(TEST_PACKAGE, agentBinder);
verify(mUserBackupManagerService).agentConnected(TEST_PACKAGE, agentBinder);
}
@@ -119,7 +119,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testAgentDisconnected_callsAgentDisconnectedForUser() throws Exception {
- mGlobalBackupManagerService.agentDisconnected(TEST_PACKAGE);
+ mBackupManagerService.agentDisconnected(TEST_PACKAGE);
verify(mUserBackupManagerService).agentDisconnected(TEST_PACKAGE);
}
@@ -127,7 +127,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testOpComplete_callsOpCompleteForUser() throws Exception {
- mGlobalBackupManagerService.opComplete(/* token */ 0, /* result */ 0L);
+ mBackupManagerService.opComplete(/* token */ 0, /* result */ 0L);
verify(mUserBackupManagerService).opComplete(/* token */ 0, /* result */ 0L);
}
@@ -141,7 +141,7 @@
public void testInitializeTransports_callsInitializeTransportsForUser() throws Exception {
String[] transports = {TEST_TRANSPORT};
- mGlobalBackupManagerService.initializeTransports(transports, /* observer */ null);
+ mBackupManagerService.initializeTransports(transports, /* observer */ null);
verify(mUserBackupManagerService).initializeTransports(transports, /* observer */ null);
}
@@ -149,7 +149,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testClearBackupData_callsClearBackupDataForUser() throws Exception {
- mGlobalBackupManagerService.clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
+ mBackupManagerService.clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
verify(mUserBackupManagerService).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
}
@@ -157,7 +157,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetCurrentTransport_callsGetCurrentTransportForUser() throws Exception {
- mGlobalBackupManagerService.getCurrentTransport();
+ mBackupManagerService.getCurrentTransport();
verify(mUserBackupManagerService).getCurrentTransport();
}
@@ -166,7 +166,7 @@
@Test
public void testGetCurrentTransportComponent_callsGetCurrentTransportComponentForUser()
throws Exception {
- mGlobalBackupManagerService.getCurrentTransportComponent();
+ mBackupManagerService.getCurrentTransportComponent();
verify(mUserBackupManagerService).getCurrentTransportComponent();
}
@@ -174,7 +174,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testListAllTransports_callsListAllTransportsForUser() throws Exception {
- mGlobalBackupManagerService.listAllTransports();
+ mBackupManagerService.listAllTransports();
verify(mUserBackupManagerService).listAllTransports();
}
@@ -183,7 +183,7 @@
@Test
public void testListAllTransportComponents_callsListAllTransportComponentsForUser()
throws Exception {
- mGlobalBackupManagerService.listAllTransportComponents();
+ mBackupManagerService.listAllTransportComponents();
verify(mUserBackupManagerService).listAllTransportComponents();
}
@@ -191,7 +191,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetTransportWhitelist_callsGetTransportWhitelistForUser() throws Exception {
- mGlobalBackupManagerService.getTransportWhitelist();
+ mBackupManagerService.getTransportWhitelist();
verify(mUserBackupManagerService).getTransportWhitelist();
}
@@ -204,7 +204,7 @@
Intent configurationIntent = new Intent();
Intent dataManagementIntent = new Intent();
- mGlobalBackupManagerService.updateTransportAttributes(
+ mBackupManagerService.updateTransportAttributes(
transport.getTransportComponent(),
transport.transportName,
configurationIntent,
@@ -225,7 +225,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testSelectBackupTransport_callsSelectBackupTransportForUser() throws Exception {
- mGlobalBackupManagerService.selectBackupTransport(TEST_TRANSPORT);
+ mBackupManagerService.selectBackupTransport(TEST_TRANSPORT);
verify(mUserBackupManagerService).selectBackupTransport(TEST_TRANSPORT);
}
@@ -236,7 +236,7 @@
TransportData transport = backupTransport();
ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
- mGlobalBackupManagerService.selectBackupTransportAsync(
+ mBackupManagerService.selectBackupTransportAsync(
transport.getTransportComponent(), callback);
verify(mUserBackupManagerService)
@@ -246,7 +246,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetConfigurationIntent_callsGetConfigurationIntentForUser() throws Exception {
- mGlobalBackupManagerService.getConfigurationIntent(TEST_TRANSPORT);
+ mBackupManagerService.getConfigurationIntent(TEST_TRANSPORT);
verify(mUserBackupManagerService).getConfigurationIntent(TEST_TRANSPORT);
}
@@ -254,7 +254,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetDestinationString_callsGetDestinationStringForUser() throws Exception {
- mGlobalBackupManagerService.getDestinationString(TEST_TRANSPORT);
+ mBackupManagerService.getDestinationString(TEST_TRANSPORT);
verify(mUserBackupManagerService).getDestinationString(TEST_TRANSPORT);
}
@@ -262,7 +262,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetDataManagementIntent_callsGetDataManagementIntentForUser() throws Exception {
- mGlobalBackupManagerService.getDataManagementIntent(TEST_TRANSPORT);
+ mBackupManagerService.getDataManagementIntent(TEST_TRANSPORT);
verify(mUserBackupManagerService).getDataManagementIntent(TEST_TRANSPORT);
}
@@ -270,7 +270,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testGetDataManagementLabel_callsGetDataManagementLabelForUser() throws Exception {
- mGlobalBackupManagerService.getDataManagementLabel(TEST_TRANSPORT);
+ mBackupManagerService.getDataManagementLabel(TEST_TRANSPORT);
verify(mUserBackupManagerService).getDataManagementLabel(TEST_TRANSPORT);
}
@@ -282,7 +282,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void setBackupEnabled_callsSetBackupEnabledForUser() throws Exception {
- mGlobalBackupManagerService.setBackupEnabled(true);
+ mBackupManagerService.setBackupEnabled(true);
verify(mUserBackupManagerService).setBackupEnabled(true);
}
@@ -290,7 +290,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void setAutoRestore_callsSetAutoRestoreForUser() throws Exception {
- mGlobalBackupManagerService.setAutoRestore(true);
+ mBackupManagerService.setAutoRestore(true);
verify(mUserBackupManagerService).setAutoRestore(true);
}
@@ -298,7 +298,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testSetBackupProvisioned_callsSetBackupProvisionedForUser() throws Exception {
- mGlobalBackupManagerService.setBackupProvisioned(true);
+ mBackupManagerService.setBackupProvisioned(true);
verify(mUserBackupManagerService).setBackupProvisioned(true);
}
@@ -306,7 +306,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testIsBackupEnabled_callsIsBackupEnabledForUser() throws Exception {
- mGlobalBackupManagerService.isBackupEnabled();
+ mBackupManagerService.isBackupEnabled();
verify(mUserBackupManagerService).isBackupEnabled();
}
@@ -318,7 +318,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testIsAppEligibleForBackup_callsIsAppEligibleForBackupForUser() throws Exception {
- mGlobalBackupManagerService.isAppEligibleForBackup(TEST_PACKAGE);
+ mBackupManagerService.isAppEligibleForBackup(TEST_PACKAGE);
verify(mUserBackupManagerService).isAppEligibleForBackup(TEST_PACKAGE);
}
@@ -329,7 +329,7 @@
throws Exception {
String[] packages = {TEST_PACKAGE};
- mGlobalBackupManagerService.filterAppsEligibleForBackup(packages);
+ mBackupManagerService.filterAppsEligibleForBackup(packages);
verify(mUserBackupManagerService).filterAppsEligibleForBackup(packages);
}
@@ -337,7 +337,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testBackupNow_callsBackupNowForUser() throws Exception {
- mGlobalBackupManagerService.backupNow();
+ mBackupManagerService.backupNow();
verify(mUserBackupManagerService).backupNow();
}
@@ -349,7 +349,7 @@
IBackupObserver observer = mock(IBackupObserver.class);
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
- mGlobalBackupManagerService.requestBackup(packages, observer, monitor, /* flags */ 0);
+ mBackupManagerService.requestBackup(packages, observer, monitor, /* flags */ 0);
verify(mUserBackupManagerService).requestBackup(packages, observer, monitor, /* flags */ 0);
}
@@ -357,7 +357,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testCancelBackups_callsCancelBackupsForUser() throws Exception {
- mGlobalBackupManagerService.cancelBackups();
+ mBackupManagerService.cancelBackups();
verify(mUserBackupManagerService).cancelBackups();
}
@@ -367,7 +367,7 @@
public void testBeginFullBackup_callsBeginFullBackupForUser() throws Exception {
FullBackupJob job = new FullBackupJob();
- mGlobalBackupManagerService.beginFullBackup(job);
+ mBackupManagerService.beginFullBackup(job);
verify(mUserBackupManagerService).beginFullBackup(job);
}
@@ -375,7 +375,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testEndFullBackup_callsEndFullBackupForUser() throws Exception {
- mGlobalBackupManagerService.endFullBackup();
+ mBackupManagerService.endFullBackup();
verify(mUserBackupManagerService).endFullBackup();
}
@@ -385,7 +385,7 @@
public void testFullTransportBackup_callsFullTransportBackupForUser() throws Exception {
String[] packages = {TEST_PACKAGE};
- mGlobalBackupManagerService.fullTransportBackup(packages);
+ mBackupManagerService.fullTransportBackup(packages);
verify(mUserBackupManagerService).fullTransportBackup(packages);
}
@@ -397,7 +397,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testRestoreAtInstall_callsRestoreAtInstallForUser() throws Exception {
- mGlobalBackupManagerService.restoreAtInstall(TEST_PACKAGE, /* token */ 0);
+ mBackupManagerService.restoreAtInstall(TEST_PACKAGE, /* token */ 0);
verify(mUserBackupManagerService).restoreAtInstall(TEST_PACKAGE, /* token */ 0);
}
@@ -405,7 +405,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testBeginRestoreSession_callsBeginRestoreSessionForUser() throws Exception {
- mGlobalBackupManagerService.beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
+ mBackupManagerService.beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
verify(mUserBackupManagerService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
}
@@ -414,7 +414,7 @@
@Test
public void testGetAvailableRestoreToken_callsGetAvailableRestoreTokenForUser()
throws Exception {
- mGlobalBackupManagerService.getAvailableRestoreToken(TEST_PACKAGE);
+ mBackupManagerService.getAvailableRestoreToken(TEST_PACKAGE);
verify(mUserBackupManagerService).getAvailableRestoreToken(TEST_PACKAGE);
}
@@ -426,7 +426,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testSetBackupPassword_callsSetBackupPasswordForUser() throws Exception {
- mGlobalBackupManagerService.setBackupPassword("currentPassword", "newPassword");
+ mBackupManagerService.setBackupPassword("currentPassword", "newPassword");
verify(mUserBackupManagerService).setBackupPassword("currentPassword", "newPassword");
}
@@ -434,7 +434,7 @@
/** Test that the backup service routes methods correctly to the user that requests it. */
@Test
public void testHasBackupPassword_callsHasBackupPasswordForUser() throws Exception {
- mGlobalBackupManagerService.hasBackupPassword();
+ mBackupManagerService.hasBackupPassword();
verify(mUserBackupManagerService).hasBackupPassword();
}
@@ -448,7 +448,7 @@
ParcelFileDescriptor.open(testFile, ParcelFileDescriptor.MODE_READ_WRITE);
String[] packages = {TEST_PACKAGE};
- mGlobalBackupManagerService.adbBackup(
+ mBackupManagerService.adbBackup(
parcelFileDescriptor,
/* includeApks */ true,
/* includeObbs */ true,
@@ -482,7 +482,7 @@
ParcelFileDescriptor parcelFileDescriptor =
ParcelFileDescriptor.open(testFile, ParcelFileDescriptor.MODE_READ_WRITE);
- mGlobalBackupManagerService.adbRestore(parcelFileDescriptor);
+ mBackupManagerService.adbRestore(parcelFileDescriptor);
verify(mUserBackupManagerService).adbRestore(parcelFileDescriptor);
}
@@ -493,7 +493,7 @@
throws Exception {
IFullBackupRestoreObserver observer = mock(IFullBackupRestoreObserver.class);
- mGlobalBackupManagerService.acknowledgeAdbBackupOrRestore(
+ mBackupManagerService.acknowledgeAdbBackupOrRestore(
/* token */ 0, /* allow */ true, "currentPassword", "encryptionPassword", observer);
verify(mUserBackupManagerService)
@@ -518,7 +518,7 @@
PrintWriter printWriter = new PrintWriter(testFile);
String[] args = {"1", "2"};
- mGlobalBackupManagerService.dump(fileDescriptor, printWriter, args);
+ mBackupManagerService.dump(fileDescriptor, printWriter, args);
verify(mUserBackupManagerService).dump(fileDescriptor, printWriter, args);
}
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index 8ec0759..a14cc51 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -44,7 +44,7 @@
import android.util.Log;
import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.GlobalBackupManagerService;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.testing.TransportData;
@@ -212,7 +212,7 @@
performInitializeTask.run();
assertLogcatContains(
- GlobalBackupManagerService.TAG,
+ BackupManagerService.TAG,
log -> log.msg.contains("finishBackup()") && log.type >= Log.ERROR);
}
@@ -225,7 +225,7 @@
performInitializeTask.run();
assertLogcatContains(
- GlobalBackupManagerService.TAG,
+ BackupManagerService.TAG,
log -> log.msg.contains("initializeDevice()") && log.type >= Log.ERROR);
}
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index c99e2a8..7c00299 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -83,7 +83,7 @@
};
private final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
- @Mock private GlobalBackupManagerService mBackupManagerServiceMock;
+ @Mock private BackupManagerService mBackupManagerServiceMock;
@Mock private Context mContextMock;
@Mock private File mSuppressFileMock;
@Mock private File mSuppressFileParentMock;
@@ -864,7 +864,7 @@
static boolean sBackupDisabled = false;
static File sSuppressFile = null;
static int sCallingUid = -1;
- static GlobalBackupManagerService sBackupManagerServiceMock = null;
+ static BackupManagerService sBackupManagerServiceMock = null;
private int mCreateServiceCallsCount = 0;
TrampolineTestable(Context context) {
@@ -887,7 +887,7 @@
}
@Override
- protected GlobalBackupManagerService createBackupManagerService() {
+ protected BackupManagerService createBackupManagerService() {
mCreateServiceCallsCount++;
return sBackupManagerServiceMock;
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 113ee2d..99b827c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -72,7 +72,6 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -142,12 +141,14 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
-import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.net.NetworkStatsManagerInternal;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
import com.google.common.util.concurrent.AbstractFuture;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -162,9 +163,6 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
@@ -195,15 +193,6 @@
/**
* Tests for {@link NetworkPolicyManagerService}.
- *
- * <p>Typical usage:
- *
- * <pre><code>
- m -j32 FrameworksServicesTests && adb install -r -g \
- ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
- adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
- "com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner"
- * </code></pre>
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -376,7 +365,7 @@
return null;
}
}).when(mActivityManager).registerUidObserver(any(), anyInt(),
- eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), isNull(String.class));
+ eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
mFutureIntent = newRestrictBackgroundChangedFuture();
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
@@ -425,7 +414,7 @@
// catch INetworkManagementEventObserver during systemReady()
final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
- ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
@@ -843,6 +832,18 @@
assertTrue(mService.isUidForeground(UID_B));
}
+ @Test
+ public void testAppIdleTempWhitelisting() throws Exception {
+ mService.setAppIdleWhitelist(UID_A, true);
+ mService.setAppIdleWhitelist(UID_B, false);
+ int[] whitelistedIds = mService.getAppIdleWhitelist();
+ assertTrue(Arrays.binarySearch(whitelistedIds, UID_A) >= 0);
+ assertTrue(Arrays.binarySearch(whitelistedIds, UID_B) < 0);
+ assertFalse(mService.isUidIdle(UID_A));
+ // Can't currently guarantee UID_B's app idle state.
+ // TODO: expand with multiple app idle states.
+ }
+
private static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
RecurrenceRule.sClock = Clock.fixed(Instant.ofEpochMilli(currentTime),
ZoneId.systemDefault());
@@ -1770,7 +1771,7 @@
}
private static NetworkPolicy buildFakeMobilePolicy(int cycleDay, long warningBytes,
- long limitBytes, boolean inferred){
+ long limitBytes, boolean inferred) {
final NetworkTemplate template = buildTemplateMobileAll(FAKE_SUBSCRIBER_ID);
return new NetworkPolicy(template, cycleDay, new Time().timezone, warningBytes,
limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
@@ -1868,7 +1869,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals("notification type mismatch for '" + actualTag +"'",
+ assertEquals("notification type mismatch for '" + actualTag + "'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1902,7 +1903,8 @@
final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
final Intent intent = future.get(5, TimeUnit.SECONDS);
assertNotNull("Didn't get a " + action + "intent in 5 seconds");
- assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
+ assertEquals("Wrong package on " + action + " intent",
+ expectedPackage, intent.getPackage());
}
// TODO: replace by Truth, Hamcrest, or a similar tool.
@@ -1923,7 +1925,7 @@
}
if (errors.length() > 0) {
fail("assertContainsInAnyOrder(expected=" + Arrays.toString(expected)
- + ", actual=" + Arrays.toString(actual) +") failed: \n" + errors);
+ + ", actual=" + Arrays.toString(actual) + ") failed: \n" + errors);
}
}
@@ -1986,7 +1988,7 @@
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
- Log.d(TAG,"counting down on answer: " + invocation);
+ Log.d(TAG, "counting down on answer: " + invocation);
latch.countDown();
return null;
}
@@ -2024,8 +2026,8 @@
final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
final File netConfigFile = new File(mPolicyDir, "netpolicy.xml");
Log.d(TAG, "Creating " + netConfigFile + " from asset " + assetPath);
- try (final InputStream in = context.getResources().getAssets().open(assetPath);
- final OutputStream out = new FileOutputStream(netConfigFile)) {
+ try (InputStream in = context.getResources().getAssets().open(assetPath);
+ OutputStream out = new FileOutputStream(netConfigFile)) {
Streams.copy(in, out);
}
}
@@ -2037,9 +2039,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NetPolicyXml {
-
- public String value() default "";
-
+ String value() default "";
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
index f12619c..19d18ca 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
@@ -35,7 +35,6 @@
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
-import android.view.IApplicationToken;
import androidx.test.filters.SmallTest;
@@ -111,16 +110,9 @@
final WindowTestUtils.TestAppWindowToken token2 = createTestAppWindowToken(dc2,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- // Set TestAppWindowContainerController & assign first app token state to be good to go.
- final WindowTestUtils.TestAppWindowContainerController controller1 =
- createAppWindowController(dc1, token1.appToken);
- final WindowTestUtils.TestAppWindowContainerController controller2 =
- createAppWindowController(dc1, token2.appToken);
- controller1.setContainer(token1);
token1.allDrawn = true;
token1.startingDisplayed = true;
token1.startingMoved = true;
- controller2.setContainer(token2);
// Simulate activity resume / finish flows to prepare app transition & set visibility,
// make sure transition is set as expected for each display.
@@ -132,8 +124,8 @@
assertEquals(TRANSIT_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransition());
// One activity window is visible for resuming & the other activity window is invisible
// for finishing in different display.
- controller1.setVisibility(true, false);
- controller2.setVisibility(false, false);
+ token1.setVisibility(true, false);
+ token2.setVisibility(false, false);
// Make sure each display is in animating stage.
assertTrue(dc1.mOpeningApps.size() > 0);
@@ -174,16 +166,4 @@
assertFalse(dc1.mOpeningApps.contains(token1));
}
- private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
- DisplayContent dc, IApplicationToken token) {
- return createAppWindowController(
- new WindowTestUtils.TestTaskWindowContainerController(
- createStackControllerOnDisplay(dc)), token);
- }
-
- private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
- WindowTestUtils.TestTaskWindowContainerController taskController,
- IApplicationToken token) {
- return new WindowTestUtils.TestAppWindowContainerController(taskController, token);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
deleted file mode 100644
index 415b5d9..0000000
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 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
- */
-
-package com.android.server.wm;
-
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController;
-
-import org.junit.Test;
-
-/**
- * Test class for {@link AppWindowContainerController}.
- *
- * atest FrameworksServicesTests:AppWindowContainerControllerTests
- */
-@FlakyTest(bugId = 74078662)
-@SmallTest
-@Presubmit
-public class AppWindowContainerControllerTests extends WindowTestsBase {
-
- private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();
-
- @Test
- public void testRemoveContainer() {
- final WindowTestUtils.TestAppWindowContainerController controller =
- createAppWindowController();
-
- // Assert token was added to display.
- assertNotNull(mDisplayContent.getWindowToken(controller.mToken.asBinder()));
- // Assert that the container was created and linked.
- assertNotNull(controller.mContainer);
-
- controller.removeContainer(mDisplayContent.getDisplayId());
-
- // Assert token was remove from display.
- assertNull(mDisplayContent.getWindowToken(controller.mToken.asBinder()));
- // Assert that the container was removed.
- assertNull(controller.mContainer);
- }
-
- @Test
- public void testSetOrientation() {
- final WindowTestUtils.TestAppWindowContainerController controller =
- createAppWindowController();
-
- // Assert orientation is unspecified to start.
- assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
-
- controller.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getDisplayId(),
- EMPTY /* displayConfig */, false /* freezeScreenIfNeeded */);
- assertEquals(SCREEN_ORIENTATION_LANDSCAPE, controller.getOrientation());
-
- controller.removeContainer(mDisplayContent.getDisplayId());
- // Assert orientation is unspecified to after container is removed.
- assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, controller.getOrientation());
-
- // Reset display frozen state
- mWm.mDisplayFrozen = false;
- }
-
- private void assertHasStartingWindow(AppWindowToken atoken) {
- assertNotNull(atoken.startingSurface);
- assertNotNull(atoken.startingData);
- assertNotNull(atoken.startingWindow);
- }
-
- private void assertNoStartingWindow(AppWindowToken atoken) {
- assertNull(atoken.startingSurface);
- assertNull(atoken.startingWindow);
- assertNull(atoken.startingData);
- atoken.forAllWindows(windowState -> {
- assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
- }, true);
- }
-
- @Test
- public void testCreateRemoveStartingWindow() {
- final WindowTestUtils.TestAppWindowContainerController controller =
- createAppWindowController();
- controller.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false);
- waitUntilHandlersIdle();
- final AppWindowToken atoken = controller.getAppWindowToken(mDisplayContent);
- assertHasStartingWindow(atoken);
- controller.removeStartingWindow();
- waitUntilHandlersIdle();
- assertNoStartingWindow(atoken);
- }
-
- @Test
- public void testAddRemoveRace() {
- // There was once a race condition between adding and removing starting windows
- for (int i = 0; i < 1000; i++) {
- final WindowTestUtils.TestAppWindowContainerController controller =
- createAppWindowController();
- controller.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false);
- controller.removeStartingWindow();
- waitUntilHandlersIdle();
- assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent));
-
- controller.getAppWindowToken(
- mDisplayContent).getParent().getParent().removeImmediately();
- }
- }
-
- @Test
- public void testTransferStartingWindow() {
- final WindowTestUtils.TestAppWindowContainerController controller1 =
- createAppWindowController();
- final WindowTestUtils.TestAppWindowContainerController controller2 =
- createAppWindowController();
- controller1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false);
- waitUntilHandlersIdle();
- controller2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false, true, false, false);
- waitUntilHandlersIdle();
- assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
- assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
- }
-
- @Test
- public void testTransferStartingWindowWhileCreating() {
- final WindowTestUtils.TestAppWindowContainerController controller1 =
- createAppWindowController();
- final WindowTestUtils.TestAppWindowContainerController controller2 =
- createAppWindowController();
- ((TestWindowManagerPolicy) mWm.mPolicy).setRunnableWhenAddingSplashScreen(() -> {
-
- // Surprise, ...! Transfer window in the middle of the creation flow.
- controller2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, controller1.mToken.asBinder(),
- true, true, false, true, false, false);
- });
- controller1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false);
- waitUntilHandlersIdle();
- assertNoStartingWindow(controller1.getAppWindowToken(mDisplayContent));
- assertHasStartingWindow(controller2.getAppWindowToken(mDisplayContent));
- }
-
- @Test
- public void testTryTransferStartingWindowFromHiddenAboveToken() {
-
- // Add two tasks on top of each other.
- TestTaskWindowContainerController taskController =
- new WindowTestUtils.TestTaskWindowContainerController(this);
- final WindowTestUtils.TestAppWindowContainerController controllerTop =
- createAppWindowController(taskController);
- final WindowTestUtils.TestAppWindowContainerController controllerBottom =
- createAppWindowController(taskController);
-
- // Add a starting window.
- controllerTop.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false);
- waitUntilHandlersIdle();
-
- // Make the top one invisible, and try transfering the starting window from the top to the
- // bottom one.
- controllerTop.setVisibility(false, false);
- controllerBottom.mContainer.transferStartingWindowFromHiddenAboveTokenIfNeeded();
-
- // Assert that the bottom window now has the starting window.
- assertNoStartingWindow(controllerTop.getAppWindowToken(mDisplayContent));
- assertHasStartingWindow(controllerBottom.getAppWindowToken(mDisplayContent));
- }
-
- @Test
- public void testReparent() {
- final StackWindowController stackController =
- createStackControllerOnDisplay(mDisplayContent);
- final WindowTestUtils.TestTaskWindowContainerController taskController1 =
- new WindowTestUtils.TestTaskWindowContainerController(stackController);
- final WindowTestUtils.TestAppWindowContainerController appWindowController1 =
- createAppWindowController(taskController1);
- final WindowTestUtils.TestTaskWindowContainerController taskController2 =
- new WindowTestUtils.TestTaskWindowContainerController(stackController);
- final WindowTestUtils.TestAppWindowContainerController appWindowController2 =
- createAppWindowController(taskController2);
- final WindowTestUtils.TestTaskWindowContainerController taskController3 =
- new WindowTestUtils.TestTaskWindowContainerController(stackController);
-
- try {
- appWindowController1.reparent(taskController1, 0);
- fail("Should not be able to reparent to the same parent");
- } catch (IllegalArgumentException e) {
- // Expected
- }
-
- try {
- taskController3.setContainer(null);
- appWindowController1.reparent(taskController3, 0);
- fail("Should not be able to reparent to a task that doesn't have a container");
- } catch (IllegalArgumentException e) {
- // Expected
- }
-
- // Reparent the app window and ensure that it is moved
- appWindowController1.reparent(taskController2, 0);
- assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
- assertEquals(0, ((WindowTestUtils.TestAppWindowToken) appWindowController1.mContainer)
- .positionInParent());
- assertEquals(1, ((WindowTestUtils.TestAppWindowToken) appWindowController2.mContainer)
- .positionInParent());
- }
-
- private WindowTestUtils.TestAppWindowContainerController createAppWindowController() {
- return createAppWindowController(
- new WindowTestUtils.TestTaskWindowContainerController(this));
- }
-
- private WindowTestUtils.TestAppWindowContainerController createAppWindowController(
- WindowTestUtils.TestTaskWindowContainerController taskController) {
- return new WindowTestUtils.TestAppWindowContainerController(taskController);
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index 552390d..99abbf7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -18,6 +18,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.content.ActivityInfoProto.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -31,8 +32,11 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_UNSET;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -66,6 +70,8 @@
Task mTask;
WindowTestUtils.TestAppWindowToken mToken;
+ private final String mPackageName = getInstrumentation().getTargetContext().getPackageName();
+
@Before
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
@@ -251,7 +257,7 @@
"closingWindow");
closingWindow.mAnimatingExit = true;
closingWindow.mRemoveOnExit = true;
- closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+ closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
true /* performLayout */, false /* isVoiceInteraction */);
// We pretended that we were running an exit animation, but that should have been cleared up
@@ -261,6 +267,124 @@
}
@Test
+ public void testSetOrientation() {
+ // Assert orientation is unspecified to start.
+ assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mToken.getOrientation());
+
+ mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation());
+
+ mDisplayContent.removeAppToken(mToken.token);
+ // Assert orientation is unset to after container is removed.
+ assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
+
+ // Reset display frozen state
+ mWm.mDisplayFrozen = false;
+ }
+
+ @Test
+ public void testCreateRemoveStartingWindow() {
+ mToken.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+ assertHasStartingWindow(mToken);
+ mToken.removeStartingWindow();
+ waitUntilHandlersIdle();
+ assertNoStartingWindow(mToken);
+ }
+
+ @Test
+ public void testAddRemoveRace() {
+ // There was once a race condition between adding and removing starting windows
+ for (int i = 0; i < 1000; i++) {
+ final WindowTestUtils.TestAppWindowToken appToken = createIsolatedTestAppWindowToken();
+
+ appToken.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ appToken.removeStartingWindow();
+ waitUntilHandlersIdle();
+ assertNoStartingWindow(appToken);
+
+ appToken.getParent().getParent().removeImmediately();
+ }
+ }
+
+ @Test
+ public void testTransferStartingWindow() {
+ final WindowTestUtils.TestAppWindowToken token1 = createIsolatedTestAppWindowToken();
+ final WindowTestUtils.TestAppWindowToken token2 = createIsolatedTestAppWindowToken();
+ token1.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+ token2.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, token1.appToken.asBinder(),
+ true, true, false, true, false, false);
+ waitUntilHandlersIdle();
+ assertNoStartingWindow(token1);
+ assertHasStartingWindow(token2);
+ }
+
+ @Test
+ public void testTransferStartingWindowWhileCreating() {
+ final WindowTestUtils.TestAppWindowToken token1 = createIsolatedTestAppWindowToken();
+ final WindowTestUtils.TestAppWindowToken token2 = createIsolatedTestAppWindowToken();
+ ((TestWindowManagerPolicy) token1.mService.mPolicy).setRunnableWhenAddingSplashScreen(
+ () -> {
+ // Surprise, ...! Transfer window in the middle of the creation flow.
+ token2.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0,
+ token1.appToken.asBinder(), true, true, false,
+ true, false, false);
+ });
+ token1.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+ assertNoStartingWindow(token1);
+ assertHasStartingWindow(token2);
+ }
+
+ private WindowTestUtils.TestAppWindowToken createIsolatedTestAppWindowToken() {
+ final TaskStack taskStack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(taskStack, 0 /* userId */);
+ return createTestAppWindowTokenForGivenTask(task);
+ }
+
+ private WindowTestUtils.TestAppWindowToken createTestAppWindowTokenForGivenTask(Task task) {
+ final WindowTestUtils.TestAppWindowToken appToken =
+ WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+ task.addChild(appToken, 0);
+ waitUntilHandlersIdle();
+ return appToken;
+ }
+
+ @Test
+ public void testTryTransferStartingWindowFromHiddenAboveToken() {
+ // Add two tasks on top of each other.
+ final WindowTestUtils.TestAppWindowToken tokenTop = createIsolatedTestAppWindowToken();
+ final WindowTestUtils.TestAppWindowToken tokenBottom =
+ createTestAppWindowTokenForGivenTask(tokenTop.getTask());
+
+ // Add a starting window.
+ tokenTop.addStartingWindow(mPackageName,
+ android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+ false, false);
+ waitUntilHandlersIdle();
+
+ // Make the top one invisible, and try transferring the starting window from the top to the
+ // bottom one.
+ tokenTop.setVisibility(false, false);
+ tokenBottom.transferStartingWindowFromHiddenAboveTokenIfNeeded();
+
+ // Assert that the bottom window now has the starting window.
+ assertNoStartingWindow(tokenTop);
+ assertHasStartingWindow(tokenBottom);
+ }
+
+ @Test
public void testTransitionAnimationPositionAndBounds() {
final Rect stackBounds = new Rect(
0/* left */, 0 /* top */, 1000 /* right */, 1000 /* bottom */);
@@ -285,4 +409,19 @@
assertEquals(expectedY, outPosition.y);
assertEquals(expectedBounds, outBounds);
}
+
+ private void assertHasStartingWindow(AppWindowToken atoken) {
+ assertNotNull(atoken.startingSurface);
+ assertNotNull(atoken.startingData);
+ assertNotNull(atoken.startingWindow);
+ }
+
+ private void assertNoStartingWindow(AppWindowToken atoken) {
+ assertNull(atoken.startingSurface);
+ assertNull(atoken.startingWindow);
+ assertNull(atoken.startingData);
+ atoken.forAllWindows(windowState -> {
+ assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
+ }, true);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index 991981f..a6415d1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -145,7 +145,7 @@
}
@Test
- public void testUpdateDimsAppliesSize() {
+ public void testUpdateDimsAppliesCrop() {
mDimmer.dimAbove(mTransaction, 0.8f);
int width = 100;
@@ -153,7 +153,7 @@
Rect bounds = new Rect(0, 0, width, height);
mDimmer.updateDims(mTransaction, bounds);
- verify(mTransaction).setSize(getDimLayer(), width, height);
+ verify(mTransaction).setWindowCrop(getDimLayer(), width, height);
verify(mTransaction).show(getDimLayer());
}
@@ -242,13 +242,13 @@
SurfaceControl dimLayer = getDimLayer();
bounds.set(0, 0, 10, 10);
mDimmer.updateDims(mTransaction, bounds);
+ verify(mTransaction).setWindowCrop(dimLayer, bounds.width(), bounds.height());
verify(mTransaction, times(1)).show(dimLayer);
- verify(mTransaction).setSize(dimLayer, bounds.width(), bounds.height());
verify(mTransaction).setPosition(dimLayer, 0, 0);
bounds.set(10, 10, 30, 30);
mDimmer.updateDims(mTransaction, bounds);
- verify(mTransaction).setSize(dimLayer, bounds.width(), bounds.height());
+ verify(mTransaction).setWindowCrop(dimLayer, bounds.width(), bounds.height());
verify(mTransaction).setPosition(dimLayer, 10, 10);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index b823e70..7f390a5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -27,7 +27,12 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.WindowConfiguration;
import android.platform.test.annotations.Presubmit;
@@ -378,6 +383,33 @@
mSecondaryDisplay.getDisplayRotation().getUserRotation());
}
+ @Test
+ public void testNotFixedToUserRotationByDefault() {
+ mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_0);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ }
+
+ @Test
+ public void testSetFixedToUserRotation() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ }
+
private static void assertOverscan(DisplayContent display, int left, int top, int right,
int bottom) {
final DisplayInfo info = display.getDisplayInfo();
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index 55e766d..ad293d9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -171,7 +171,7 @@
try {
final SurfaceControl surface = new SurfaceControl.Builder(appSession)
.setName("drag surface")
- .setSize(100, 100)
+ .setBufferSize(100, 100)
.setFormat(PixelFormat.TRANSLUCENT)
.build();
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
new file mode 100644
index 0000000..241b987
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.wm;
+
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsSourceProviderTest extends WindowTestsBase {
+
+ private InsetsSourceProvider mProvider = new InsetsSourceProvider(
+ new InsetsSource(TYPE_TOP_BAR));
+
+ @Test
+ public void testPostLayout() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ topBar.mHasSurface = true;
+ mProvider.setWindow(topBar, null);
+ mProvider.onPostLayout();
+ assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame());
+ assertEquals(Insets.of(0, 100, 0, 0),
+ mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+ }
+
+ @Test
+ public void testPostLayout_invisible() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ mProvider.setWindow(topBar, null);
+ mProvider.onPostLayout();
+ assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+ }
+
+ @Test
+ public void testPostLayout_frameProvider() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ topBar.getFrameLw().set(0, 0, 500, 100);
+ mProvider.setWindow(topBar,
+ (displayFrames, windowState, rect) -> {
+ rect.set(10, 10, 20, 20);
+ });
+ mProvider.onPostLayout();
+ assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
new file mode 100644
index 0000000..7505db1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.wm;
+
+import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@Presubmit
+public class InsetsStateControllerTest extends WindowTestsBase {
+
+ @Test
+ public void testStripForDispatch_notOwn() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ topBar.setInsetProvider(
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+ assertNotNull(mDisplayContent.getInsetsStateController().getInsetsForDispatch(app)
+ .getSource(TYPE_TOP_BAR));
+ }
+
+ @Test
+ public void testStripForDispatch_own() {
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ topBar.setInsetProvider(
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR));
+ assertEquals(new InsetsState(),
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(topBar));
+ }
+
+ @Test
+ public void testStripForDispatch_navBar() {
+ final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ final WindowState ime = createWindow(null, TYPE_APPLICATION, "parentWindow");
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_TOP_BAR)
+ .setWindow(topBar, null);
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_NAVIGATION_BAR)
+ .setWindow(navBar, null);
+ mDisplayContent.getInsetsStateController().getSourceProvider(TYPE_IME)
+ .setWindow(ime, null);
+ assertEquals(new InsetsState(),
+ mDisplayContent.getInsetsStateController().getInsetsForDispatch(navBar));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 6833dc5..e638a6a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -225,11 +225,9 @@
mTransaction = transaction;
mParent = wm.makeSurfaceBuilder(mSession)
.setName("test surface parent")
- .setSize(3000, 3000)
.build();
mSurface = wm.makeSurfaceBuilder(mSession)
.setName("test surface")
- .setSize(1, 1)
.build();
mFinishedCallbackCalled = false;
mLeash = null;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index d2c0765..792e8a6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -48,7 +48,7 @@
public void testGetClosingApps_closing() {
final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
"closingWindow");
- closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+ closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
true /* performLayout */, false /* isVoiceInteraction */);
final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
closingApps.add(closingWindow.mAppToken);
@@ -64,9 +64,9 @@
"closingWindow");
final WindowState openingWindow = createAppWindow(closingWindow.getTask(),
FIRST_APPLICATION_WINDOW, "openingWindow");
- closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+ closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
true /* performLayout */, false /* isVoiceInteraction */);
- openingWindow.mAppToken.setVisibility(null, true /* visible */, TRANSIT_UNSET,
+ openingWindow.mAppToken.commitVisibility(null, true /* visible */, TRANSIT_UNSET,
true /* performLayout */, false /* isVoiceInteraction */);
final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
closingApps.add(closingWindow.mAppToken);
@@ -79,7 +79,7 @@
public void testGetClosingApps_skipClosingAppsSnapshotTasks() {
final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW,
"closingWindow");
- closingWindow.mAppToken.setVisibility(null, false /* visible */, TRANSIT_UNSET,
+ closingWindow.mAppToken.commitVisibility(null, false /* visible */, TRANSIT_UNSET,
true /* performLayout */, false /* isVoiceInteraction */);
final ArraySet<AppWindowToken> closingApps = new ArraySet<>();
closingApps.add(closingWindow.mAppToken);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 1af79e4..bbf508d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -17,8 +17,6 @@
package com.android.server.wm;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
@@ -37,6 +35,7 @@
@Presubmit
public class TaskWindowContainerControllerTests extends WindowTestsBase {
+ /* Comment out due to removal of AppWindowContainerController
@Test
public void testRemoveContainer() {
final WindowTestUtils.TestTaskWindowContainerController taskController =
@@ -49,7 +48,9 @@
assertNull(taskController.mContainer);
assertNull(appController.mContainer);
}
+ */
+ /* Comment out due to removal of AppWindowContainerController
@Test
public void testRemoveContainer_deferRemoval() {
final WindowTestUtils.TestTaskWindowContainerController taskController =
@@ -74,6 +75,7 @@
assertNull(appController.mContainer);
assertNull(app.getController());
}
+ */
@Test
public void testReparent() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index 99deeb9..432af0d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -24,6 +24,7 @@
import android.view.DisplayCutout;
import android.view.DragEvent;
import android.view.IWindow;
+import android.view.InsetsState;
import com.android.internal.os.IResultReceiver;
@@ -39,6 +40,9 @@
Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId,
DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException {
}
+ @Override
+ public void insetsChanged(InsetsState insetsState) throws RemoteException {
+ }
@Override
public void moved(int newX, int newY) throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 60c0459..2e47c35 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -18,7 +18,6 @@
import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -116,12 +115,11 @@
ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
- boolean launchTaskBehind, boolean alwaysFocusable,
- AppWindowContainerController controller) {
+ boolean launchTaskBehind, boolean alwaysFocusable, ActivityRecord activityRecord) {
super(service, token, activityComponent, voiceInteraction, dc,
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
orientation, rotationAnimationHint, configChanges, launchTaskBehind,
- alwaysFocusable, controller);
+ alwaysFocusable, activityRecord);
}
int getWindowsCount() {
@@ -275,45 +273,6 @@
}
}
- public static class TestAppWindowContainerController extends AppWindowContainerController {
-
- final IApplicationToken mToken;
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController) {
- this(taskController, new TestIApplicationToken());
- }
-
- TestAppWindowContainerController(TestTaskWindowContainerController taskController,
- IApplicationToken token) {
- super(taskController, token, new ComponentName("", "") /* activityComponent */,
- null /* listener */, 0 /* index */, SCREEN_ORIENTATION_UNSPECIFIED,
- true /* fullscreen */, true /* showForAllUsers */, 0 /* configChanges */,
- false /* voiceInteraction */, false /* launchTaskBehind */,
- false /* alwaysFocusable */, 0 /* targetSdkVersion */,
- 0 /* rotationAnimationHint */, 0 /* inputDispatchingTimeoutNanos */,
- taskController.mService);
- mToken = token;
- }
-
- @Override
- AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
- ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
- long inputDispatchingTimeoutNanos,
- boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
- int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
- boolean alwaysFocusable, AppWindowContainerController controller) {
- return new TestAppWindowToken(service, token, activityComponent, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
- orientation,
- rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
- controller);
- }
-
- AppWindowToken getAppWindowToken(DisplayContent dc) {
- return (AppWindowToken) dc.getWindowToken(mToken.asBinder());
- }
- }
-
public static class TestIApplicationToken implements IApplicationToken {
private final Binder mBinder = new Binder();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index fcd29e1..d950360 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3711,4 +3711,23 @@
verify(mAssistants).notifyAssistantSuggestedReplySent(
eq(r.sbn), eq(reply), eq(generatedByAssistant));
}
+
+ @Test
+ public void testOnNotificationActionClick() {
+ final int actionIndex = 2;
+ final Notification.Action action =
+ new Notification.Action.Builder(null, "text", null).build();
+ final boolean generatedByAssistant = false;
+
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(r);
+
+ NotificationVisibility notificationVisibility =
+ NotificationVisibility.obtain(r.getKey(), 1, 2, true);
+ mService.mNotificationDelegate.onNotificationActionClick(
+ 10, 10, r.getKey(), actionIndex, action, notificationVisibility,
+ generatedByAssistant);
+ verify(mAssistants).notifyAssistantActionClicked(
+ eq(r.sbn), eq(actionIndex), eq(action), eq(generatedByAssistant));
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 38d8e39..6c7ede3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -41,6 +41,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
@@ -1097,6 +1098,25 @@
assertFalse(Objects.equals(defaultRuleName, ruleAfterUpdating.name)); // update name
}
+ @Test
+ public void testAddAutomaticZenRule() {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+
+ assertTrue(id != null);
+ ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
+ assertTrue(ruleInConfig != null);
+ assertEquals(zenRule.isEnabled(), ruleInConfig.enabled);
+ assertEquals(zenRule.isModified(), ruleInConfig.modified);
+ assertEquals(zenRule.getConditionId(), ruleInConfig.conditionId);
+ assertEquals(NotificationManager.zenModeFromInterruptionFilter(
+ zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode);
+ assertEquals(zenRule.getName(), ruleInConfig.name);
+ }
+
private void setupZenConfig() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index f128b4e2..67acec6 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -37,6 +37,8 @@
<application android:debuggable="true"
android:testOnly="true">
+ <uses-library android:name="android.test.mock" android:required="true" />
+
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityA" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityB" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index cb2a8ec..5bf3d2d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -62,8 +62,9 @@
@Test
public void testLastFocusedStackIsUpdatedWhenMovingStack() {
// Create a stack at bottom.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- final ActivityStack stack = new StackBuilder(mSupervisor).setOnTop(!ON_TOP).build();
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack stack =
+ new StackBuilder(mRootActivityContainer).setOnTop(!ON_TOP).build();
final ActivityStack prevFocusedStack = display.getFocusedStack();
stack.moveToFront("moveStackToFront");
@@ -83,7 +84,7 @@
@Test
public void testFullscreenStackCanBeFocusedWhenFocusablePinnedStackExists() {
// Create a pinned stack and move to front.
- final ActivityStack pinnedStack = mSupervisor.getDefaultDisplay().createStack(
+ final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
final TaskRecord pinnedTask = new TaskBuilder(mService.mStackSupervisor)
.setStack(pinnedStack).build();
@@ -96,7 +97,7 @@
// Create a fullscreen stack and move to front.
final ActivityStack fullscreenStack = createFullscreenStackWithSimpleActivityAt(
- mSupervisor.getDefaultDisplay());
+ mRootActivityContainer.getDefaultDisplay());
fullscreenStack.moveToFront("moveFullscreenStackToFront");
// The focused stack should be the fullscreen stack.
@@ -138,7 +139,7 @@
final ActivityDisplay display = spy(createNewActivityDisplay());
doReturn(false).when(display).shouldDestroyContentOnRemove();
doReturn(true).when(display).supportsSystemDecorations();
- mSupervisor.addChild(display, ActivityDisplay.POSITION_TOP);
+ mRootActivityContainer.addChild(display, ActivityDisplay.POSITION_TOP);
// Put home stack on the display.
final ActivityStack homeStack = display.createStack(
@@ -175,14 +176,14 @@
*/
@Test
public void testTopRunningActivity() {
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
final KeyguardController keyguard = mSupervisor.getKeyguardController();
- final ActivityStack stack = new StackBuilder(mSupervisor).build();
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
final ActivityRecord activity = stack.getTopActivity();
// Create empty stack on top.
final ActivityStack emptyStack =
- new StackBuilder(mSupervisor).setCreateActivity(false).build();
+ new StackBuilder(mRootActivityContainer).setCreateActivity(false).build();
// Make sure the top running activity is not affected when keyguard is not locked.
assertTopRunningActivity(activity, display);
@@ -225,7 +226,7 @@
*/
@Test
public void testAlwaysOnTopStackLocation() {
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index c7f0521..0e30037 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -74,7 +74,7 @@
// Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
// This seems to be the easiest way to create an ActivityRecord.
- mStack = mSupervisor.getDefaultDisplay().createStack(
+ mStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 170bd33..b6f1817 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -29,10 +29,9 @@
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static junit.framework.TestCase.assertNotNull;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -65,7 +64,7 @@
@Before
public void setUp() throws Exception {
setupActivityTaskManagerService();
- mStack = new StackBuilder(mSupervisor).build();
+ mStack = new StackBuilder(mRootActivityContainer).build();
mTask = mStack.getChildAt(0);
mActivity = mTask.getTopActivity();
}
@@ -86,7 +85,7 @@
public void testStackCleanupOnTaskRemoval() {
mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING);
// Stack should be gone on task removal.
- assertNull(mService.mStackSupervisor.getStack(mStack.mStackId));
+ assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId));
}
@Test
@@ -116,7 +115,7 @@
assertFalse(pauseFound.value);
// Clear focused stack
- final ActivityDisplay display = mActivity.mStackSupervisor.getDefaultDisplay();
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
when(display.getFocusedStack()).thenReturn(null);
// In the unfocused stack, the activity should move to paused.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 8a6d587..78a67d2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -38,8 +38,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStackSupervisor
- .MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static com.google.common.truth.Truth.assertThat;
@@ -83,78 +82,11 @@
@Before
public void setUp() throws Exception {
setupActivityTaskManagerService();
- mFullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
/**
- * This test ensures that we do not try to restore a task based off an invalid task id. We
- * should expect {@code null} to be returned in this case.
- */
- @Test
- public void testRestoringInvalidTask() {
- ((TestActivityDisplay) mSupervisor.getDefaultDisplay()).removeAllTasks();
- TaskRecord task = mSupervisor.anyTaskForIdLocked(0 /*taskId*/,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
- assertNull(task);
- }
-
- /**
- * This test ensures that an existing task in the pinned stack is moved to the fullscreen
- * activity stack when a new task is added.
- */
- @Test
- public void testReplacingTaskInPinnedStack() {
- final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(mFullscreenStack).build();
- final TaskRecord firstTask = firstActivity.getTask();
-
- final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(mFullscreenStack).build();
- final TaskRecord secondTask = secondActivity.getTask();
-
- mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
-
- // Ensure full screen stack has both tasks.
- ensureStackPlacement(mFullscreenStack, firstTask, secondTask);
-
- // Move first activity to pinned stack.
- final Rect sourceBounds = new Rect();
- mSupervisor.moveActivityToPinnedStackLocked(firstActivity, sourceBounds,
- 0f /*aspectRatio*/, "initialMove");
-
- final ActivityDisplay display = mFullscreenStack.getDisplay();
- ActivityStack pinnedStack = display.getPinnedStack();
- // Ensure a task has moved over.
- ensureStackPlacement(pinnedStack, firstTask);
- ensureStackPlacement(mFullscreenStack, secondTask);
-
- // Move second activity to pinned stack.
- mSupervisor.moveActivityToPinnedStackLocked(secondActivity, sourceBounds,
- 0f /*aspectRatio*/, "secondMove");
-
- // Need to get stacks again as a new instance might have been created.
- pinnedStack = display.getPinnedStack();
- mFullscreenStack = display.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- // Ensure stacks have swapped tasks.
- ensureStackPlacement(pinnedStack, secondTask);
- ensureStackPlacement(mFullscreenStack, firstTask);
- }
-
- private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) {
- final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
- assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
-
- if (tasks == null) {
- return;
- }
-
- for (TaskRecord task : tasks) {
- assertTrue(stackTasks.contains(task));
- }
- }
-
- /**
* Ensures that an activity is removed from the stopping activities list once it is resumed.
*/
@Test
@@ -179,7 +111,7 @@
// #notifyAll will be called on the ActivityManagerService. we must hold the object lock
// when this happens.
- synchronized (mSupervisor.mService.mGlobalLock) {
+ synchronized (mService.mGlobalLock) {
final WaitResult taskToFrontWait = new WaitResult();
mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait);
mSupervisor.reportWaitingActivityLaunchedIfNeeded(firstActivity, START_TASK_TO_FRONT);
@@ -198,334 +130,4 @@
assertEquals(deliverToTopWait.who, firstActivity.realActivity);
}
}
-
- @Test
- public void testApplySleepTokensLocked() {
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- final KeyguardController keyguard = mSupervisor.getKeyguardController();
- final ActivityStack stack = mock(ActivityStack.class);
- display.addChild(stack, 0 /* position */);
-
- // Make sure we wake and resume in the case the display is turning on and the keyguard is
- // not showing.
- verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
- false /* displayShouldSleep */, true /* isFocusedStack */,
- false /* keyguardShowing */, true /* expectWakeFromSleep */,
- true /* expectResumeTopActivity */);
-
- // Make sure we wake and don't resume when the display is turning on and the keyguard is
- // showing.
- verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
- false /* displayShouldSleep */, true /* isFocusedStack */,
- true /* keyguardShowing */, true /* expectWakeFromSleep */,
- false /* expectResumeTopActivity */);
-
- // Make sure we wake and don't resume when the display is turning on and the keyguard is
- // not showing as unfocused.
- verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
- false /* displayShouldSleep */, false /* isFocusedStack */,
- false /* keyguardShowing */, true /* expectWakeFromSleep */,
- false /* expectResumeTopActivity */);
-
- // Should not do anything if the display state hasn't changed.
- verifySleepTokenBehavior(display, keyguard, stack, false /*displaySleeping*/,
- false /* displayShouldSleep */, true /* isFocusedStack */,
- false /* keyguardShowing */, false /* expectWakeFromSleep */,
- false /* expectResumeTopActivity */);
- }
-
- private void verifySleepTokenBehavior(ActivityDisplay display, KeyguardController keyguard,
- ActivityStack stack, boolean displaySleeping, boolean displayShouldSleep,
- boolean isFocusedStack, boolean keyguardShowing, boolean expectWakeFromSleep,
- boolean expectResumeTopActivity) {
- reset(stack);
-
- doReturn(displayShouldSleep).when(display).shouldSleep();
- doReturn(displaySleeping).when(display).isSleeping();
- doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt());
-
- doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay();
- doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack();
- mSupervisor.applySleepTokensLocked(true);
- verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked();
- verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
- null /* target */, null /* targetOptions */);
- }
-
- /**
- * Verifies that removal of activity with task and stack is done correctly.
- */
- @Test
- public void testRemovingStackOnAppCrash() {
- final ActivityDisplay defaultDisplay = mService.mStackSupervisor.getDefaultDisplay();
- final int originalStackCount = defaultDisplay.getChildCount();
- final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(stack).build();
-
- assertEquals(originalStackCount + 1, defaultDisplay.getChildCount());
-
- // Let's pretend that the app has crashed.
- firstActivity.app.setThread(null);
- mService.mStackSupervisor.finishTopCrashedActivitiesLocked(firstActivity.app, "test");
-
- // Verify that the stack was removed.
- assertEquals(originalStackCount, defaultDisplay.getChildCount());
- }
-
- @Test
- public void testFocusability() {
- final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(stack).build();
-
- // Under split screen primary we should be focusable when not minimized
- mService.mStackSupervisor.setDockedStackMinimized(false);
- assertTrue(stack.isFocusable());
- assertTrue(activity.isFocusable());
-
- // Under split screen primary we should not be focusable when minimized
- mService.mStackSupervisor.setDockedStackMinimized(true);
- assertFalse(stack.isFocusable());
- assertFalse(activity.isFocusable());
-
- final ActivityStack pinnedStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true)
- .setStack(pinnedStack).build();
-
- // We should not be focusable when in pinned mode
- assertFalse(pinnedStack.isFocusable());
- assertFalse(pinnedActivity.isFocusable());
-
- // Add flag forcing focusability.
- pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE;
-
- // We should not be focusable when in pinned mode
- assertTrue(pinnedStack.isFocusable());
- assertTrue(pinnedActivity.isFocusable());
-
- // Without the overridding activity, stack should not be focusable.
- pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability",
- REMOVE_TASK_MODE_DESTROYING);
- assertFalse(pinnedStack.isFocusable());
- }
-
- /**
- * Verify that split-screen primary stack will be chosen if activity is launched that targets
- * split-screen secondary, but a matching existing instance is found on top of split-screen
- * primary stack.
- */
- @Test
- public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() {
- // Create primary split-screen stack with a task and an activity.
- final ActivityStack primaryStack = mService.mStackSupervisor.getDefaultDisplay()
- .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
- true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
- final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build();
-
- // Find a launch stack for the top activity in split-screen primary, while requesting
- // split-screen secondary.
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
- final ActivityStack result = mSupervisor.getLaunchStack(r, options, task, true /* onTop */);
-
- // Assert that the primary stack is returned.
- assertEquals(primaryStack, result);
- }
-
- /**
- * Verify split-screen primary stack & task can resized by
- * {@link android.app.IActivityTaskManager#resizeDockedStack} as expect.
- */
- @Test
- public void testResizeDockedStackForSplitScreenPrimary() {
- final Rect taskSize = new Rect(0, 0, 600, 600);
- final Rect stackSize = new Rect(0, 0, 300, 300);
-
- // Create primary split-screen stack with a task.
- final ActivityStack primaryStack = mService.mStackSupervisor.getDefaultDisplay()
- .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
- true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
-
- // Resize dock stack.
- mService.resizeDockedStack(stackSize, taskSize, null, null, null);
-
- // Verify dock stack & its task bounds if is equal as resized result.
- assertEquals(primaryStack.getBounds(), stackSize);
- assertEquals(task.getBounds(), taskSize);
- }
-
- /**
- * Verify that home stack would be moved to front when the top activity is Recents.
- */
- @Test
- public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
- // Create stack/task on default display.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- final TestActivityStack targetStack = new StackBuilder(mSupervisor).setOnTop(false).build();
- final TaskRecord targetTask = targetStack.getChildAt(0);
-
- // Create Recents on top of the display.
- final ActivityStack stack =
- new StackBuilder(mSupervisor).setActivityType(ACTIVITY_TYPE_RECENTS).build();
-
- final String reason = "findTaskToMoveToFront";
- mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
- false);
-
- verify(display).moveHomeStackToFront(contains(reason));
- }
-
- /**
- * Verify that home stack won't be moved to front if the top activity on other display is
- * Recents.
- */
- @Test
- public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
- // Create stack/task on default display.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
-
- // Create Recents on secondary display.
- final TestActivityDisplay secondDisplay = addNewActivityDisplayAt(
- ActivityDisplay.POSITION_TOP);
- final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_RECENTS, true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
- new ActivityBuilder(mService).setTask(task).build();
-
- final String reason = "findTaskToMoveToFront";
- mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
- false);
-
- verify(display, never()).moveHomeStackToFront(contains(reason));
- }
-
- /**
- * Verify if a stack is not at the topmost position, it should be able to resume its activity if
- * the stack is the top focused.
- */
- @Test
- public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
- // Create a stack at bottom.
- final ActivityDisplay display = mSupervisor.getDefaultDisplay();
- final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD, false /* onTop */));
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
- final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
- display.positionChildAtBottom(targetStack);
-
- // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
- // is the current top focused stack.
- assertFalse(targetStack.isTopStackOnDisplay());
- doReturn(targetStack).when(mSupervisor).getTopDisplayFocusedStack();
-
- // Use the stack as target to resume.
- mSupervisor.resumeFocusedStacksTopActivitiesLocked(
- targetStack, activity, null /* targetOptions */);
-
- // Verify the target stack should resume its activity.
- verify(targetStack, times(1)).resumeTopActivityUncheckedLocked(
- eq(activity), eq(null /* targetOptions */));
- }
-
- /**
- * Tests home activities that targeted sdk before Q cannot start on secondary display.
- */
- @Test
- public void testStartHomeTargetSdkBeforeQ() throws Exception {
- final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
- mSupervisor.addChild(secondDisplay, POSITION_TOP);
- doReturn(true).when(secondDisplay).supportsSystemDecorations();
-
- final ActivityInfo info = new ActivityInfo();
- info.launchMode = LAUNCH_MULTIPLE;
- info.applicationInfo = new ApplicationInfo();
- info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
- assertTrue(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
- false /* allowInstrumenting */));
-
- info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
- assertFalse(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
- false /* allowInstrumenting */));
- }
-
- /**
- * Tests that home activities can be started on the displays that supports system decorations.
- */
- @Test
- public void testStartHomeOnAllDisplays() {
- // Create secondary displays.
- final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
- mSupervisor.addChild(secondDisplay, POSITION_TOP);
- doReturn(true).when(secondDisplay).supportsSystemDecorations();
-
- // Create mock tasks and other necessary mocks.
- TaskBuilder taskBuilder = new TaskBuilder(mService.mStackSupervisor).setCreateStack(false);
- final TaskRecord.TaskRecordFactory factory = mock(TaskRecord.TaskRecordFactory.class);
- TaskRecord.setTaskRecordFactory(factory);
- doAnswer(i -> taskBuilder.build()).when(factory)
- .create(any(), anyInt(), any(), any(), any(), any());
- doReturn(true).when(mService.mStackSupervisor)
- .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
- doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt(), anyBoolean());
-
- mSupervisor.startHomeOnAllDisplays(0, "testStartHome");
-
- assertTrue(mSupervisor.getDefaultDisplay().getTopStack().isActivityTypeHome());
- assertNotNull(secondDisplay.getTopStack());
- assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
- }
-
- /**
- * Tests that home activities won't be started before booting when display added.
- */
- @Test
- public void testNotStartHomeBeforeBoot() {
- final int displayId = 1;
- final boolean isBooting = mService.mAmInternal.isBooting();
- final boolean isBooted = mService.mAmInternal.isBooted();
- try {
- mService.mAmInternal.setBooting(false);
- mService.mAmInternal.setBooted(false);
- mSupervisor.onDisplayAdded(displayId);
- verify(mSupervisor, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
- } finally {
- mService.mAmInternal.setBooting(isBooting);
- mService.mAmInternal.setBooted(isBooted);
- }
- }
-
- /**
- * Tests whether home can be started if being instrumented.
- */
- @Test
- public void testCanStartHomeWhenInstrumented() {
- final ActivityInfo info = new ActivityInfo();
- info.applicationInfo = new ApplicationInfo();
- final WindowProcessController app = mock(WindowProcessController.class);
- doReturn(app).when(mService).getProcessController(any(), anyInt());
-
- // Can not start home if we don't want to start home while home is being instrumented.
- doReturn(true).when(app).isInstrumenting();
- assertFalse(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
- false /* allowInstrumenting*/));
-
- // Can start home for other cases.
- assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
- true /* allowInstrumenting*/));
-
- doReturn(false).when(app).isInstrumenting();
- assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
- false /* allowInstrumenting*/));
- assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
- true /* allowInstrumenting*/));
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 2fe45b8..0da0b24 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -74,7 +74,7 @@
@Before
public void setUp() throws Exception {
setupActivityTaskManagerService();
- mDefaultDisplay = mSupervisor.getDefaultDisplay();
+ mDefaultDisplay = mRootActivityContainer.getDefaultDisplay();
mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD,
true /* onTop */));
mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
@@ -112,7 +112,7 @@
r.setState(RESUMED, "testResumedActivityFromTaskReparenting");
assertEquals(r, mStack.getResumedActivity());
- final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask.reparent(destStack, true /* toTop */, TaskRecord.REPARENT_KEEP_STACK_AT_FRONT,
@@ -130,7 +130,7 @@
r.setState(RESUMED, "testResumedActivityFromActivityReparenting");
assertEquals(r, mStack.getResumedActivity());
- final ActivityStack destStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ final ActivityStack destStack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final TaskRecord destTask = new TaskBuilder(mSupervisor).setStack(destStack).build();
@@ -239,8 +239,8 @@
.setUid(UserHandle.PER_USER_RANGE * 2).build();
taskOverlay.mTaskOverlay = true;
- final ActivityStackSupervisor.FindTaskResult result =
- new ActivityStackSupervisor.FindTaskResult();
+ final RootActivityContainer.FindTaskResult result =
+ new RootActivityContainer.FindTaskResult();
mStack.findTaskLocked(r, result);
assertEquals(r, task.getTopActivity(false /* includeOverlays */));
@@ -700,7 +700,7 @@
// should be destroyed immediately with updating configuration to restore original state.
final ActivityRecord activity1 = finishCurrentActivity(stack1);
assertEquals(DESTROYING, activity1.getState());
- verify(mSupervisor).ensureVisibilityAndConfig(eq(null) /* starting */,
+ verify(mRootActivityContainer).ensureVisibilityAndConfig(eq(null) /* starting */,
eq(display.mDisplayId), anyBoolean(), anyBoolean());
}
@@ -778,7 +778,7 @@
final ActivityDisplay display = mock(ActivityDisplay.class);
final KeyguardController keyguardController = mSupervisor.getKeyguardController();
- doReturn(display).when(mSupervisor).getActivityDisplay(anyInt());
+ doReturn(display).when(mRootActivityContainer).getActivityDisplay(anyInt());
doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
doReturn(displaySleeping).when(display).isSleeping();
doReturn(focusedStack).when(mStack).isFocusedStackOnDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
index 9d93c85..2ba2fdb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java
@@ -74,7 +74,7 @@
final ActivityRecord activity = new ActivityBuilder(mService).build();
final ActivityRecord source = new ActivityBuilder(mService).build();
final int startFlags = random.nextInt();
- final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ final ActivityStack stack = mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final WindowProcessController wpc = new WindowProcessController(mService,
mService.mContext.getApplicationInfo(), "name", 12345,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 27fa20b..350114c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -90,6 +90,8 @@
@Mock
private ActivityTaskManagerService mService;
@Mock
+ private RootActivityContainer mRootActivityContainer;
+ @Mock
private ActivityStackSupervisor mSupervisor;
@Mock
private DevicePolicyManagerInternal mDevicePolicyManager;
@@ -111,7 +113,8 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mService.mAmInternal = mAmInternal;
- mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
+ mInterceptor = new ActivityStartInterceptor(
+ mService, mSupervisor, mRootActivityContainer, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 50aa541..d78fbcd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.START_ABORTED;
import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
@@ -69,6 +70,7 @@
import android.content.pm.PackageManagerInternal;
import android.graphics.Rect;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.service.voice.IVoiceInteractionSession;
@@ -110,6 +112,7 @@
private static final int FAKE_CALLING_UID = 666;
private static final int FAKE_REAL_CALLING_UID = 667;
private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude";
+ private static final int UNIMPORTANT_UID = 12345;
@Before
public void setUp() throws Exception {
@@ -125,7 +128,7 @@
public void testUpdateLaunchBounds() {
// When in a non-resizeable stack, the task bounds should be updated.
final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
- .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack(
+ .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.build();
final Rect bounds = new Rect(10, 10, 100, 100);
@@ -136,7 +139,7 @@
// When in a resizeable stack, the stack bounds should be updated as well.
final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor)
- .setStack(mService.mStackSupervisor.getDefaultDisplay().createStack(
+ .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */))
.build();
assertThat((Object) task2.getStack()).isInstanceOf(PinnedActivityStack.class);
@@ -314,7 +317,7 @@
* Creates a {@link ActivityStarter} with default parameters and necessary mocks.
*
* @param launchFlags The intent flags to launch activity.
- * @param mockGetLaunchStack Whether to mock {@link ActivityStackSupervisor#getLaunchStack} for
+ * @param mockGetLaunchStack Whether to mock {@link RootActivityContainer#getLaunchStack} for
* always launching to the testing stack. Set to false when allowing
* the activity can be launched to any stack that is decided by real
* implementation.
@@ -323,14 +326,14 @@
private ActivityStarter prepareStarter(@Intent.Flags int launchFlags,
boolean mockGetLaunchStack) {
// always allow test to start activity.
- doReturn(true).when(mService.mStackSupervisor).checkStartAnyActivityPermission(
+ doReturn(true).when(mSupervisor).checkStartAnyActivityPermission(
any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
anyBoolean(), anyBoolean(), any(), any(), any());
// instrument the stack and task used.
- final ActivityStack stack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TaskRecord task = new TaskBuilder(mService.mStackSupervisor)
+ final TaskRecord task = new TaskBuilder(mSupervisor)
.setCreateStack(false)
.build();
@@ -343,9 +346,9 @@
if (mockGetLaunchStack) {
// Direct starter to use spy stack.
- doReturn(stack).when(mService.mStackSupervisor)
+ doReturn(stack).when(mRootActivityContainer)
.getLaunchStack(any(), any(), any(), anyBoolean());
- doReturn(stack).when(mService.mStackSupervisor)
+ doReturn(stack).when(mRootActivityContainer)
.getLaunchStack(any(), any(), any(), anyBoolean(), any());
}
@@ -441,7 +444,7 @@
final ActivityStack focusStack = focusActivity.getStack();
focusStack.moveToFront("testSplitScreenDeliverToTop");
- doReturn(reusableActivity).when(mService.mStackSupervisor).findTaskLocked(any(), anyInt());
+ doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
final int result = starter.setReason("testSplitScreenDeliverToTop").execute();
@@ -473,7 +476,7 @@
// Enter split-screen. Primary stack should have focus.
focusActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- doReturn(reusableActivity).when(mService.mStackSupervisor).findTaskLocked(any(), anyInt());
+ doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
final int result = starter.setReason("testSplitScreenMoveToFront").execute();
@@ -486,7 +489,7 @@
*/
@Test
public void testTaskModeViolation() {
- final ActivityDisplay display = mService.mStackSupervisor.getDefaultDisplay();
+ final ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
((TestActivityDisplay) display).removeAllTasks();
assertNoTasks(display);
@@ -551,6 +554,85 @@
}
/**
+ * This test ensures that unsupported usecases aren't aborted when background starts are
+ * allowed.
+ */
+ @Test
+ public void testBackgroundActivityStartsAllowed_noStartsAborted() {
+ doReturn(true).when(mService).isBackgroundActivityStartsEnabled();
+
+ runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted",
+ false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ }
+
+ /**
+ * This test ensures that unsupported usecases are aborted when background starts are
+ * disallowed.
+ */
+ @Test
+ public void testBackgroundActivityStartsDisallowed_unsupportedStartsAborted() {
+ doReturn(false).when(mService).isBackgroundActivityStartsEnabled();
+
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_unsupportedUsecase_aborted",
+ true, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ }
+
+ /**
+ * This test ensures that supported usecases aren't aborted when background starts are
+ * disallowed.
+ * The scenarios each have only one condidion that makes them supported.
+ */
+ @Test
+ public void testBackgroundActivityStartsDisallowed_supportedStartsNotAborted() {
+ doReturn(false).when(mService).isBackgroundActivityStartsEnabled();
+
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted",
+ false, Process.ROOT_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted",
+ false, Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_hasVisibleWindow_notAborted",
+ false, UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_processStateTop_notAborted",
+ false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_hasForegroundActivities_notAborted",
+ false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, true, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_callerIsRecents_notAborted",
+ false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, true);
+ }
+
+ private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
+ int testCallingUid, boolean hasVisibleWindow, int procState,
+ boolean hasForegroundActivities, boolean callerIsRecents) {
+ // window visibility
+ doReturn(hasVisibleWindow).when(mService.mWindowManager).isAnyWindowVisibleForUid(
+ testCallingUid);
+ // process importance
+ doReturn(procState).when(mService).getUidStateLocked(testCallingUid);
+ // foreground activities
+ final IApplicationThread caller = mock(IApplicationThread.class);
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.uid = testCallingUid;
+ final WindowProcessController callerApp =
+ new WindowProcessController(mService, ai, null, testCallingUid, -1, null, null);
+ callerApp.setHasForegroundActivities(hasForegroundActivities);
+ doReturn(callerApp).when(mService).getProcessController(caller);
+ // caller is recents
+ RecentTasks recentTasks = mock(RecentTasks.class);
+ mService.mStackSupervisor.setRecentTasks(recentTasks);
+ doReturn(callerIsRecents).when(recentTasks).isCallerRecents(testCallingUid);
+
+ final ActivityOptions options = spy(ActivityOptions.makeBasic());
+ ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK).setCaller(caller)
+ .setCallingUid(testCallingUid).setActivityOptions(new SafeActivityOptions(options));
+
+ final int result = starter.setReason("testBackgroundActivityStarts_" + name).execute();
+
+ assertEquals(ActivityStarter.getExternalResult(
+ shouldHaveAborted ? START_ABORTED : START_SUCCESS), result);
+ verify(options, times(shouldHaveAborted ? 1 : 0)).abort();
+ }
+
+ /**
* This test ensures that when starting an existing single task activity on secondary display
* which is not the top focused display, it should deliver new intent to the activity and not
* create a new stack.
@@ -562,7 +644,7 @@
// Create a secondary display at bottom.
final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay());
- mSupervisor.addChild(secondaryDisplay, POSITION_BOTTOM);
+ mRootActivityContainer.addChild(secondaryDisplay, POSITION_BOTTOM);
final ActivityStack stack = secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -600,7 +682,7 @@
// Create a secondary display with an activity.
final TestActivityDisplay secondaryDisplay = spy(createNewActivityDisplay());
- mSupervisor.addChild(secondaryDisplay, POSITION_TOP);
+ mRootActivityContainer.addChild(secondaryDisplay, POSITION_TOP);
final ActivityRecord singleTaskActivity = createSingleTaskActivityOn(
secondaryDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index c2ab3ac..ead9731 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -94,6 +94,7 @@
final TestInjector mTestInjector = new TestInjector();
ActivityTaskManagerService mService;
+ RootActivityContainer mRootActivityContainer;
ActivityStackSupervisor mSupervisor;
// Default package name
@@ -120,6 +121,7 @@
ActivityTaskManagerService createActivityTaskManagerService() {
mService = new TestActivityTaskManagerService(mContext);
mSupervisor = mService.mStackSupervisor;
+ mRootActivityContainer = mService.mRootActivityContainer;
return mService;
}
@@ -139,7 +141,7 @@
/** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
TestActivityDisplay addNewActivityDisplayAt(int position) {
final TestActivityDisplay display = createNewActivityDisplay();
- mSupervisor.addChild(display, position);
+ mRootActivityContainer.addChild(display, position);
return display;
}
@@ -231,7 +233,9 @@
aInfo /*aInfo*/, new Configuration(), null /* resultTo */, null /* resultWho */,
0 /* reqCode */, false /*componentSpecified*/, false /* rootVoiceInteraction */,
mService.mStackSupervisor, null /* options */, null /* sourceRecord */);
- activity.mWindowContainerController = mock(AppWindowContainerController.class);
+ spyOn(activity);
+ activity.mAppWindowToken = mock(AppWindowToken.class);
+ doNothing().when(activity).removeWindowContainer();
if (mTaskRecord != null) {
mTaskRecord.addActivityToTop(activity);
@@ -317,7 +321,7 @@
TaskRecord build() {
if (mStack == null && mCreateStack) {
- mStack = mSupervisor.getDefaultDisplay().createStack(
+ mStack = mSupervisor.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
@@ -375,6 +379,8 @@
// We keep the reference in order to prevent creating it twice.
ActivityStackSupervisor mTestStackSupervisor;
+ ActivityDisplay mDefaultDisplay;
+
TestActivityTaskManagerService(Context context) {
super(context);
spyOn(this);
@@ -390,18 +396,11 @@
final TestActivityManagerService am =
new TestActivityManagerService(mTestInjector, this);
- // Put a home stack on the default display, so that we'll always have something
- // focusable.
- final TestActivityStackSupervisor supervisor =
- (TestActivityStackSupervisor) mStackSupervisor;
- supervisor.mDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
- final TaskRecord task = new TaskBuilder(mStackSupervisor)
- .setStack(supervisor.getDefaultDisplay().getHomeStack()).build();
- new ActivityBuilder(this).setTask(task).build();
-
spyOn(getLifecycleManager());
spyOn(getLockTaskController());
doReturn(mock(IPackageManager.class)).when(this).getPackageManager();
+ // allow background activity starts by default
+ doReturn(true).when(this).isBackgroundActivityStartsEnabled();
}
void setActivityManagerService(IntentFirewall intentFirewall,
@@ -409,9 +408,38 @@
WindowManagerService wm) {
mAmInternal = amInternal;
setActivityManagerService(intentFirewall, intentController);
+ initRootActivityContainerMocks(wm);
setWindowManager(wm);
}
+ void initRootActivityContainerMocks(WindowManagerService wm) {
+ spyOn(mRootActivityContainer);
+ mRootActivityContainer.setWindowContainer(mock(RootWindowContainer.class));
+ mRootActivityContainer.mWindowManager = wm;
+ mRootActivityContainer.mDisplayManager =
+ (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+ doNothing().when(mRootActivityContainer).setWindowManager(any());
+ // Invoked during {@link ActivityStack} creation.
+ doNothing().when(mRootActivityContainer).updateUIDsPresentOnDisplay();
+ // Always keep things awake.
+ doReturn(true).when(mRootActivityContainer).hasAwakeDisplay();
+ // Called when moving activity to pinned stack.
+ doNothing().when(mRootActivityContainer).ensureActivitiesVisible(any(), anyInt(),
+ anyBoolean());
+
+ // Create a default display and put a home stack on it so that we'll always have
+ // something focusable.
+ mDefaultDisplay = TestActivityDisplay.create(mStackSupervisor, DEFAULT_DISPLAY);
+ spyOn(mDefaultDisplay);
+ mRootActivityContainer.addChild(mDefaultDisplay, ActivityDisplay.POSITION_TOP);
+ mDefaultDisplay.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+ final TaskRecord task = new TaskBuilder(mStackSupervisor)
+ .setStack(mDefaultDisplay.getHomeStack()).build();
+ new ActivityBuilder(this).setTask(task).build();
+
+ doReturn(mDefaultDisplay).when(mRootActivityContainer).getDefaultDisplay();
+ }
+
@Override
int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
return userId;
@@ -508,25 +536,14 @@
* setup not available in the test environment. Also specifies an injector for
*/
protected class TestActivityStackSupervisor extends ActivityStackSupervisor {
- private ActivityDisplay mDisplay;
private KeyguardController mKeyguardController;
TestActivityStackSupervisor(ActivityTaskManagerService service, Looper looper) {
super(service, looper);
spyOn(this);
- mDisplayManager =
- (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
mWindowManager = prepareMockWindowManager();
mKeyguardController = mock(KeyguardController.class);
- setWindowContainerController(mock(RootWindowContainerController.class));
- // Invoked during {@link ActivityStack} creation.
- doNothing().when(this).updateUIDsPresentOnDisplay();
- // Always keep things awake.
- doReturn(true).when(this).hasAwakeDisplay();
- // Called when moving activity to pinned stack.
- doNothing().when(this).ensureActivitiesVisibleLocked(any(), anyInt(),
- anyBoolean());
// Do not schedule idle timeouts
doNothing().when(this).scheduleIdleTimeoutLocked(any());
// unit test version does not handle launch wake lock
@@ -537,24 +554,11 @@
}
@Override
- public void initialize() {
- super.initialize();
- mDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY);
- spyOn(mDisplay);
- addChild(mDisplay, ActivityDisplay.POSITION_TOP);
- }
-
- @Override
public KeyguardController getKeyguardController() {
return mKeyguardController;
}
@Override
- ActivityDisplay getDefaultDisplay() {
- return mDisplay;
- }
-
- @Override
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
}
@@ -571,7 +575,7 @@
DisplayInfo info) {
if (displayId == DEFAULT_DISPLAY) {
return new TestActivityDisplay(supervisor,
- supervisor.mDisplayManager.getDisplay(displayId));
+ supervisor.mRootActivityContainer.mDisplayManager.getDisplay(displayId));
}
final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
info, DEFAULT_DISPLAY_ADJUSTMENTS);
@@ -579,7 +583,7 @@
}
TestActivityDisplay(ActivityStackSupervisor supervisor, Display display) {
- super(supervisor, display);
+ super(supervisor.mService.mRootActivityContainer, display);
// Normally this comes from display-properties as exposed by WM. Without that, just
// hard-code to FULLSCREEN for tests.
setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -590,7 +594,7 @@
@Override
<T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
int stackId, boolean onTop) {
- return new StackBuilder(mSupervisor).setDisplay(this)
+ return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this)
.setWindowingMode(windowingMode).setActivityType(activityType)
.setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build();
}
@@ -732,8 +736,8 @@
}
}
- protected static class StackBuilder {
- private final ActivityStackSupervisor mSupervisor;
+ static class StackBuilder {
+ private final RootActivityContainer mRootActivityContainer;
private ActivityDisplay mDisplay;
private int mStackId = -1;
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
@@ -741,9 +745,9 @@
private boolean mOnTop = true;
private boolean mCreateActivity = true;
- StackBuilder(ActivityStackSupervisor supervisor) {
- mSupervisor = supervisor;
- mDisplay = mSupervisor.getDefaultDisplay();
+ StackBuilder(RootActivityContainer root) {
+ mRootActivityContainer = root;
+ mDisplay = mRootActivityContainer.getDefaultDisplay();
}
StackBuilder setWindowingMode(int windowingMode) {
@@ -780,7 +784,8 @@
<T extends ActivityStack> T build() {
final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
if (mWindowingMode == WINDOWING_MODE_PINNED) {
- return (T) new PinnedActivityStack(mDisplay, stackId, mSupervisor, mOnTop) {
+ return (T) new PinnedActivityStack(mDisplay, stackId,
+ mRootActivityContainer.mStackSupervisor, mOnTop) {
@Override
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
return new Rect(50, 50, 100, 100);
@@ -796,7 +801,8 @@
}
};
} else {
- return (T) new TestActivityStack(mDisplay, stackId, mSupervisor, mWindowingMode,
+ return (T) new TestActivityStack(mDisplay, stackId,
+ mRootActivityContainer.mStackSupervisor, mWindowingMode,
mActivityType, mOnTop, mCreateActivity);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
new file mode 100644
index 0000000..e988994
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.PowerManagerInternal;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.view.Surface;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class for {@link DisplayRotation}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayRotationTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
+public class DisplayRotationTests {
+ private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50;
+
+ private StatusBarManagerInternal mPreviousStatusBarManagerInternal;
+
+ private WindowManagerService mMockWm;
+ private DisplayContent mMockDisplayContent;
+ private DisplayPolicy mMockDisplayPolicy;
+ private Context mMockContext;
+ private Resources mMockRes;
+ private SensorManager mMockSensorManager;
+ private Sensor mFakeSensor;
+ private DisplayWindowSettings mMockDisplayWindowSettings;
+ private ContentResolver mMockResolver;
+ private FakeSettingsProvider mFakeSettingsProvider;
+ private StatusBarManagerInternal mMockStatusBarManagerInternal;
+
+ // Fields below are callbacks captured from test target.
+ private ContentObserver mShowRotationSuggestionsObserver;
+ private ContentObserver mAccelerometerRotationObserver;
+ private ContentObserver mUserRotationObserver;
+ private SensorEventListener mOrientationSensorListener;
+
+ private DisplayRotationBuilder mBuilder;
+
+ private DisplayRotation mTarget;
+
+ @Before
+ public void setUp() {
+ FakeSettingsProvider.clearSettingsProvider();
+
+ mMockWm = mock(WindowManagerService.class);
+ mMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
+
+ mPreviousStatusBarManagerInternal = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class);
+ LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
+
+ mBuilder = new DisplayRotationBuilder();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ if (mPreviousStatusBarManagerInternal != null) {
+ LocalServices.addService(StatusBarManagerInternal.class,
+ mPreviousStatusBarManagerInternal);
+ mPreviousStatusBarManagerInternal = null;
+ }
+ }
+
+ // ================================
+ // Display Settings Related Tests
+ // ================================
+ @Test
+ public void testLocksUserRotation_LockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ assertEquals(0, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ assertEquals(Surface.ROTATION_180, Settings.System.getInt(mMockResolver,
+ Settings.System.USER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(mMockDisplayContent,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_180);
+ }
+
+ @Test
+ public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ assertEquals(1, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(same(mMockDisplayContent),
+ eq(WindowManagerPolicy.USER_ROTATION_FREE), anyInt());
+ }
+
+ @Test
+ public void testPersistsFixedToUserRotation() throws Exception {
+ mBuilder.build();
+
+ mTarget.setFixedToUserRotation(true);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(false);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ }
+
+ // ========================================
+ // Tests for User Rotation based Rotation
+ // ========================================
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_NoAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_CompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsSidesays_UserRotationLocked_IncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_90);
+ assertTrue("Rotation should be sideways, but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ // =================================
+ // Tests for Sensor based Rotation
+ // =================================
+ private void verifyOrientationListenerRegistration(int numOfInvocation) {
+ final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(
+ SensorEventListener.class);
+ verify(mMockSensorManager, times(numOfInvocation)).registerListener(
+ listenerCaptor.capture(),
+ same(mFakeSensor),
+ anyInt(),
+ any());
+ if (numOfInvocation > 0) {
+ mOrientationSensorListener = listenerCaptor.getValue();
+ }
+ }
+
+ @Test
+ public void testNotEnablesSensor_AutoRotationNotSupported() throws Exception {
+ mBuilder.setSupportAutoRotation(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ScreenNotOn() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(false);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_NotAwake() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(false);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_KeyguardNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(false);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_WindowManagerNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(false);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_FixedUserRotation() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.setFixedToUserRotation(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ private void enableOrientationSensor() {
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(1);
+ }
+
+ private SensorEvent createSensorEvent(int rotation) throws Exception {
+ final Constructor<SensorEvent> constructor =
+ SensorEvent.class.getDeclaredConstructor(int.class);
+ constructor.setAccessible(true);
+ final SensorEvent event = constructor.newInstance(1);
+ event.sensor = mFakeSensor;
+ event.values[0] = rotation;
+ event.timestamp = SystemClock.elapsedRealtimeNanos();
+ return event;
+ }
+
+ @Test
+ public void testReturnsSensorRotation_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ private boolean waitForUiHandler() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ UiThread.getHandler().post(latch::countDown);
+ return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void testUpdatesRotationWhenSensorUpdates_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockWm).updateRotation(false, false);
+ }
+
+ @Test
+ public void testNotifiesChoiceWhenSensorUpdates_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);
+ }
+
+ @Test
+ public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ final int rotation = mTarget.rotationForOrientation(SCREEN_ORIENTATION_LANDSCAPE,
+ Surface.ROTATION_0);
+ assertTrue("Rotation should be sideways but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ @Test
+ public void testReturnsUserRotation_SensorEnabled_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ // =================================
+ // Tests for Policy based Rotation
+ // =================================
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsLidOpenRotation_LidOpen() throws Exception {
+ mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getLidState()).thenReturn(
+ WindowManagerPolicy.WindowManagerFuncs.LID_OPEN);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testReturnsCarDockRotation_CarDockedMode() throws Exception {
+ mBuilder.setCarDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_CAR);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsDeskDockRotation_DeskDockedMode() throws Exception {
+ mBuilder.setDeskDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ mTarget.setFixedToUserRotation(true);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90);
+ assertEquals(Surface.ROTATION_180, rotation);
+ }
+
+ @Test
+ public void testReturnsUserRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ /**
+ * Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
+ * according to given parameters.
+ */
+ private void configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv) {
+ final int width;
+ final int height;
+ switch (displayOrientation) {
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ width = 1920;
+ height = 1080;
+ break;
+ case SCREEN_ORIENTATION_PORTRAIT:
+ width = 1080;
+ height = 1920;
+ break;
+ default:
+ throw new IllegalArgumentException("displayOrientation needs to be either landscape"
+ + " or portrait, but we got "
+ + ActivityInfo.screenOrientationToString(displayOrientation));
+ }
+
+ final PackageManager mockPackageManager = mock(PackageManager.class);
+ when(mMockContext.getPackageManager()).thenReturn(mockPackageManager);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ .thenReturn(isCar);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ .thenReturn(isTv);
+
+ final int shortSizeDp = (isCar || isTv) ? 540 : 720;
+ final int longSizeDp = 960;
+ mTarget.configure(width, height, shortSizeDp, longSizeDp);
+ }
+
+ private void freezeRotation(int rotation) {
+ mTarget.freezeRotation(rotation);
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private void thawRotation() {
+ mTarget.thawRotation();
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private class DisplayRotationBuilder {
+ private boolean mIsDefaultDisplay = true;
+ private boolean mSupportAutoRotation = true;
+
+ private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+ private int mCarDockRotation;
+ private int mDeskDockRotation;
+ private int mUndockedHdmiRotation;
+
+ private DisplayRotationBuilder setIsDefaultDisplay(boolean isDefaultDisplay) {
+ mIsDefaultDisplay = isDefaultDisplay;
+ return this;
+ }
+
+ private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) {
+ mSupportAutoRotation = supportAutoRotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setLidOpenRotation(int rotation) {
+ mLidOpenRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setCarDockRotation(int rotation) {
+ mCarDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setDeskDockRotation(int rotation) {
+ mDeskDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setUndockedHdmiRotation(int rotation) {
+ mUndockedHdmiRotation = rotation;
+ return this;
+ }
+
+ private void captureObservers() {
+ ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(
+ ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.Secure.getUriFor(Settings.Secure.SHOW_ROTATION_SUGGESTIONS)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mShowRotationSuggestionsObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mAccelerometerRotationObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.USER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mUserRotationObserver = captor.getValue();
+ }
+ }
+
+ private Sensor createSensor(int type) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+
+ setSensorType(sensor, type);
+ setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+ setSensorField(sensor, "mVendor", "Mock Vendor");
+ setSensorField(sensor, "mVersion", 1);
+ setSensorField(sensor, "mHandle", -1);
+ setSensorField(sensor, "mMaxRange", 10);
+ setSensorField(sensor, "mResolution", 1);
+ setSensorField(sensor, "mPower", 1);
+ setSensorField(sensor, "mMinDelay", 1000);
+ setSensorField(sensor, "mMaxDelay", 1000000000);
+ setSensorField(sensor, "mFlags", 0);
+ setSensorField(sensor, "mId", -1);
+
+ return sensor;
+ }
+
+ private void setSensorType(Sensor sensor, int type) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ }
+
+ private void setSensorField(Sensor sensor, String fieldName, Object value)
+ throws Exception {
+ Field field = Sensor.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(sensor, value);
+ }
+
+ private int convertRotationToDegrees(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return 0;
+ case Surface.ROTATION_90:
+ return 90;
+ case Surface.ROTATION_180:
+ return 180;
+ case Surface.ROTATION_270:
+ return 270;
+ default:
+ return -1;
+ }
+ }
+
+ private void build() throws Exception {
+ mMockContext = mock(Context.class);
+
+ mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
+ mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
+
+ mMockDisplayPolicy = mock(DisplayPolicy.class);
+
+ mMockRes = mock(Resources.class);
+ when(mMockContext.getResources()).thenReturn((mMockRes));
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation))
+ .thenReturn(mSupportAutoRotation);
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation))
+ .thenReturn(convertRotationToDegrees(mLidOpenRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_carDockRotation))
+ .thenReturn(convertRotationToDegrees(mCarDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_deskDockRotation))
+ .thenReturn(convertRotationToDegrees(mDeskDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
+ .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+
+ mMockSensorManager = mock(SensorManager.class);
+ when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
+ .thenReturn(mMockSensorManager);
+ mFakeSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION);
+ when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn(
+ Collections.singletonList(mFakeSensor));
+
+ mMockResolver = mock(ContentResolver.class);
+ when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
+ mFakeSettingsProvider = new FakeSettingsProvider();
+ when(mMockResolver.acquireProvider(Settings.AUTHORITY))
+ .thenReturn(mFakeSettingsProvider.getIContentProvider());
+
+ mMockDisplayWindowSettings = mock(DisplayWindowSettings.class);
+ mTarget = new DisplayRotation(mMockWm, mMockDisplayContent, mMockDisplayPolicy,
+ mMockDisplayWindowSettings, mMockContext, new Object());
+
+ captureObservers();
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index dc22bc1..f3a125b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -110,8 +110,9 @@
final DisplayInfo info = new DisplayInfo();
info.uniqueId = mDisplayUniqueId;
mTestDisplay = createNewActivityDisplay(info);
- mSupervisor.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
- when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(mTestDisplay);
+ mRootActivityContainer.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
+ when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId)))
+ .thenReturn(mTestDisplay);
ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
ACTIVITY_TYPE_STANDARD, /* onTop */ true);
@@ -184,7 +185,7 @@
public void testReturnsEmptyDisplayIfDisplayIsNotFound() {
mTarget.saveTask(mTestTask);
- when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(null);
+ when(mRootActivityContainer.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(null);
mTarget.getLaunchParams(mTestTask, null, mResult);
@@ -271,6 +272,51 @@
}
@Test
+ public void testClearsRecordInMemory() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ mTarget.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsWriteQueueItem() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsFile() {
+ mTarget.saveTask(mTestTask);
+ mPersisterQueue.flush();
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+
+ @Test
public void testClearsRecordInMemoryOnPackageUninstalled() {
mTarget.saveTask(mTestTask);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 33e6063..6259fa6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -104,6 +104,7 @@
new DexmakerShareClassLoaderRule();
@Mock private ActivityStackSupervisor mSupervisor;
+ @Mock private RootActivityContainer mRootActivityContainer;
@Mock private IDevicePolicyManager mDevicePolicyManager;
@Mock private IStatusBarService mStatusBarService;
@Mock private WindowManagerService mWindowManager;
@@ -129,6 +130,7 @@
}
mSupervisor.mRecentTasks = mRecentTasks;
+ mSupervisor.mRootActivityContainer = mRootActivityContainer;
mLockTaskController = new LockTaskController(mContext, mSupervisor,
new ImmediatelyExecuteHandler());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 8596c77..3c7b4b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -113,9 +113,10 @@
mTestService = new MyTestActivityTaskManagerService(mContext);
mRecentTasks = (TestRecentTasks) mTestService.getRecentTasks();
mRecentTasks.loadParametersFromResources(mContext.getResources());
- mHomeStack = mTestService.mStackSupervisor.getDefaultDisplay().getOrCreateStack(
+ mRunningTasks = (TestRunningTasks) mTestService.mStackSupervisor.mRunningTasks;
+ mHomeStack = mTestService.mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
- mStack = mTestService.mStackSupervisor.getDefaultDisplay().createStack(
+ mStack = mTestService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mCallbacksRecorder = new CallbacksRecorder();
mRecentTasks.registerCallback(mCallbacksRecorder);
@@ -872,6 +873,15 @@
}
return mTestStackSupervisor;
}
+
+ @Override
+ void initRootActivityContainerMocks(WindowManagerService wm) {
+ super.initRootActivityContainerMocks(wm);
+ mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
+ mOtherDisplay = TestActivityDisplay.create(mTestStackSupervisor, DEFAULT_DISPLAY + 1);
+ mRootActivityContainer.addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
+ mRootActivityContainer.addChild(mDisplay, ActivityDisplay.POSITION_TOP);
+ }
}
private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
@@ -880,15 +890,6 @@
}
@Override
- public void initialize() {
- super.initialize();
- mDisplay = getActivityDisplay(DEFAULT_DISPLAY);
- mOtherDisplay = TestActivityDisplay.create(this, DEFAULT_DISPLAY + 1);
- addChild(mOtherDisplay, ActivityDisplay.POSITION_TOP);
- addChild(mDisplay, ActivityDisplay.POSITION_TOP);
- }
-
- @Override
RunningTasks createRunningTasks() {
mRunningTasks = new TestRunningTasks();
return mRunningTasks;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 070f073..0ff67d7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -67,9 +67,9 @@
@Test
public void testCancelAnimationOnStackOrderChange() {
ActivityStack fullscreenStack =
- mService.mStackSupervisor.getDefaultDisplay().createStack(
+ mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- ActivityStack recentsStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
+ ActivityStack recentsStack = mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
ActivityRecord recentsActivity = new ActivityBuilder(mService)
.setComponent(mRecentsComponent)
@@ -77,7 +77,7 @@
.setStack(recentsStack)
.build();
ActivityStack fullscreenStack2 =
- mService.mStackSupervisor.getDefaultDisplay().createStack(
+ mService.mRootActivityContainer.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
ActivityRecord fsActivity = new ActivityBuilder(mService)
.setComponent(new ComponentName(mContext.getPackageName(), "App1"))
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
new file mode 100644
index 0000000..631de99d
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2018 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
+ */
+
+package com.android.server.wm;
+
+import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
+import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
+import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
+import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.contains;
+import static org.mockito.ArgumentMatchers.eq;
+
+import android.app.ActivityOptions;
+import android.app.WaitResult;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.graphics.Rect;
+import android.os.Build;
+import android.platform.test.annotations.Presubmit;
+import androidx.test.filters.MediumTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for the {@link ActivityStackSupervisor} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:ActivityStackSupervisorTests
+ */
+@MediumTest
+@Presubmit
+public class RootActivityContainerTests extends ActivityTestsBase {
+ private ActivityStack mFullscreenStack;
+
+ @Before
+ public void setUp() throws Exception {
+ setupActivityTaskManagerService();
+ mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ }
+
+ /**
+ * This test ensures that we do not try to restore a task based off an invalid task id. We
+ * should expect {@code null} to be returned in this case.
+ */
+ @Test
+ public void testRestoringInvalidTask() {
+ ((TestActivityDisplay) mRootActivityContainer.getDefaultDisplay()).removeAllTasks();
+ TaskRecord task = mRootActivityContainer.anyTaskForId(0 /*taskId*/,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null, false /* onTop */);
+ assertNull(task);
+ }
+
+ /**
+ * This test ensures that an existing task in the pinned stack is moved to the fullscreen
+ * activity stack when a new task is added.
+ */
+ @Test
+ public void testReplacingTaskInPinnedStack() {
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final TaskRecord firstTask = firstActivity.getTask();
+
+ final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(mFullscreenStack).build();
+ final TaskRecord secondTask = secondActivity.getTask();
+
+ mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
+
+ // Ensure full screen stack has both tasks.
+ ensureStackPlacement(mFullscreenStack, firstTask, secondTask);
+
+ // Move first activity to pinned stack.
+ final Rect sourceBounds = new Rect();
+ mRootActivityContainer.moveActivityToPinnedStack(firstActivity, sourceBounds,
+ 0f /*aspectRatio*/, "initialMove");
+
+ final ActivityDisplay display = mFullscreenStack.getDisplay();
+ ActivityStack pinnedStack = display.getPinnedStack();
+ // Ensure a task has moved over.
+ ensureStackPlacement(pinnedStack, firstTask);
+ ensureStackPlacement(mFullscreenStack, secondTask);
+
+ // Move second activity to pinned stack.
+ mRootActivityContainer.moveActivityToPinnedStack(secondActivity, sourceBounds,
+ 0f /*aspectRatio*/, "secondMove");
+
+ // Need to get stacks again as a new instance might have been created.
+ pinnedStack = display.getPinnedStack();
+ mFullscreenStack = display.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ // Ensure stacks have swapped tasks.
+ ensureStackPlacement(pinnedStack, secondTask);
+ ensureStackPlacement(mFullscreenStack, firstTask);
+ }
+
+ private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) {
+ final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
+ assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
+
+ if (tasks == null) {
+ return;
+ }
+
+ for (TaskRecord task : tasks) {
+ assertTrue(stackTasks.contains(task));
+ }
+ }
+
+ @Test
+ public void testApplySleepTokens() {
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final KeyguardController keyguard = mSupervisor.getKeyguardController();
+ final ActivityStack stack = mock(ActivityStack.class);
+ display.addChild(stack, 0 /* position */);
+
+ // Make sure we wake and resume in the case the display is turning on and the keyguard is
+ // not showing.
+ verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
+ false /* displayShouldSleep */, true /* isFocusedStack */,
+ false /* keyguardShowing */, true /* expectWakeFromSleep */,
+ true /* expectResumeTopActivity */);
+
+ // Make sure we wake and don't resume when the display is turning on and the keyguard is
+ // showing.
+ verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
+ false /* displayShouldSleep */, true /* isFocusedStack */,
+ true /* keyguardShowing */, true /* expectWakeFromSleep */,
+ false /* expectResumeTopActivity */);
+
+ // Make sure we wake and don't resume when the display is turning on and the keyguard is
+ // not showing as unfocused.
+ verifySleepTokenBehavior(display, keyguard, stack, true /*displaySleeping*/,
+ false /* displayShouldSleep */, false /* isFocusedStack */,
+ false /* keyguardShowing */, true /* expectWakeFromSleep */,
+ false /* expectResumeTopActivity */);
+
+ // Should not do anything if the display state hasn't changed.
+ verifySleepTokenBehavior(display, keyguard, stack, false /*displaySleeping*/,
+ false /* displayShouldSleep */, true /* isFocusedStack */,
+ false /* keyguardShowing */, false /* expectWakeFromSleep */,
+ false /* expectResumeTopActivity */);
+ }
+
+ private void verifySleepTokenBehavior(ActivityDisplay display, KeyguardController keyguard,
+ ActivityStack stack, boolean displaySleeping, boolean displayShouldSleep,
+ boolean isFocusedStack, boolean keyguardShowing, boolean expectWakeFromSleep,
+ boolean expectResumeTopActivity) {
+ reset(stack);
+
+ doReturn(displayShouldSleep).when(display).shouldSleep();
+ doReturn(displaySleeping).when(display).isSleeping();
+ doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt());
+
+ doReturn(isFocusedStack).when(stack).isFocusedStackOnDisplay();
+ doReturn(isFocusedStack ? stack : null).when(display).getFocusedStack();
+ mRootActivityContainer.applySleepTokens(true);
+ verify(stack, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleepingLocked();
+ verify(stack, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked(
+ null /* target */, null /* targetOptions */);
+ }
+
+ /**
+ * Verifies that removal of activity with task and stack is done correctly.
+ */
+ @Test
+ public void testRemovingStackOnAppCrash() {
+ final ActivityDisplay defaultDisplay = mRootActivityContainer.getDefaultDisplay();
+ final int originalStackCount = defaultDisplay.getChildCount();
+ final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(stack).build();
+
+ assertEquals(originalStackCount + 1, defaultDisplay.getChildCount());
+
+ // Let's pretend that the app has crashed.
+ firstActivity.app.setThread(null);
+ mRootActivityContainer.finishTopCrashedActivities(firstActivity.app, "test");
+
+ // Verify that the stack was removed.
+ assertEquals(originalStackCount, defaultDisplay.getChildCount());
+ }
+
+ @Test
+ public void testFocusability() {
+ final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().createStack(
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(stack).build();
+
+ // Under split screen primary we should be focusable when not minimized
+ mRootActivityContainer.setDockedStackMinimized(false);
+ assertTrue(stack.isFocusable());
+ assertTrue(activity.isFocusable());
+
+ // Under split screen primary we should not be focusable when minimized
+ mRootActivityContainer.setDockedStackMinimized(true);
+ assertFalse(stack.isFocusable());
+ assertFalse(activity.isFocusable());
+
+ final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack(
+ WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ final ActivityRecord pinnedActivity = new ActivityBuilder(mService).setCreateTask(true)
+ .setStack(pinnedStack).build();
+
+ // We should not be focusable when in pinned mode
+ assertFalse(pinnedStack.isFocusable());
+ assertFalse(pinnedActivity.isFocusable());
+
+ // Add flag forcing focusability.
+ pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE;
+
+ // We should not be focusable when in pinned mode
+ assertTrue(pinnedStack.isFocusable());
+ assertTrue(pinnedActivity.isFocusable());
+
+ // Without the overridding activity, stack should not be focusable.
+ pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability",
+ REMOVE_TASK_MODE_DESTROYING);
+ assertFalse(pinnedStack.isFocusable());
+ }
+
+ /**
+ * Verify that split-screen primary stack will be chosen if activity is launched that targets
+ * split-screen secondary, but a matching existing instance is found on top of split-screen
+ * primary stack.
+ */
+ @Test
+ public void testSplitScreenPrimaryChosenWhenTopActivityLaunchedToSecondary() {
+ // Create primary split-screen stack with a task and an activity.
+ final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay()
+ .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
+ final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build();
+
+ // Find a launch stack for the top activity in split-screen primary, while requesting
+ // split-screen secondary.
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
+ final ActivityStack result =
+ mRootActivityContainer.getLaunchStack(r, options, task, true /* onTop */);
+
+ // Assert that the primary stack is returned.
+ assertEquals(primaryStack, result);
+ }
+
+ /**
+ * Verify split-screen primary stack & task can resized by
+ * {@link android.app.IActivityTaskManager#resizeDockedStack} as expect.
+ */
+ @Test
+ public void testResizeDockedStackForSplitScreenPrimary() {
+ final Rect taskSize = new Rect(0, 0, 600, 600);
+ final Rect stackSize = new Rect(0, 0, 300, 300);
+
+ // Create primary split-screen stack with a task.
+ final ActivityStack primaryStack = mRootActivityContainer.getDefaultDisplay()
+ .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(primaryStack).build();
+
+ // Resize dock stack.
+ mService.resizeDockedStack(stackSize, taskSize, null, null, null);
+
+ // Verify dock stack & its task bounds if is equal as resized result.
+ assertEquals(primaryStack.getBounds(), stackSize);
+ assertEquals(task.getBounds(), taskSize);
+ }
+
+ /**
+ * Verify that home stack would be moved to front when the top activity is Recents.
+ */
+ @Test
+ public void testFindTaskToMoveToFrontWhenRecentsOnTop() {
+ // Create stack/task on default display.
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final TestActivityStack targetStack =
+ new StackBuilder(mRootActivityContainer).setOnTop(false).build();
+ final TaskRecord targetTask = targetStack.getChildAt(0);
+
+ // Create Recents on top of the display.
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer).setActivityType(
+ ACTIVITY_TYPE_RECENTS).build();
+
+ final String reason = "findTaskToMoveToFront";
+ mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
+ false);
+
+ verify(display).moveHomeStackToFront(contains(reason));
+ }
+
+ /**
+ * Verify that home stack won't be moved to front if the top activity on other display is
+ * Recents.
+ */
+ @Test
+ public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
+ // Create stack/task on default display.
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, false /* onTop */);
+ final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
+
+ // Create Recents on secondary display.
+ final TestActivityDisplay secondDisplay = addNewActivityDisplayAt(
+ ActivityDisplay.POSITION_TOP);
+ final ActivityStack stack = secondDisplay.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_RECENTS, true /* onTop */);
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ new ActivityBuilder(mService).setTask(task).build();
+
+ final String reason = "findTaskToMoveToFront";
+ mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
+ false);
+
+ verify(display, never()).moveHomeStackToFront(contains(reason));
+ }
+
+ /**
+ * Verify if a stack is not at the topmost position, it should be able to resume its activity if
+ * the stack is the top focused.
+ */
+ @Test
+ public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
+ // Create a stack at bottom.
+ final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
+ final ActivityStack targetStack = spy(display.createStack(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, false /* onTop */));
+ final TaskRecord task = new TaskBuilder(mSupervisor).setStack(targetStack).build();
+ final ActivityRecord activity = new ActivityBuilder(mService).setTask(task).build();
+ display.positionChildAtBottom(targetStack);
+
+ // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
+ // is the current top focused stack.
+ assertFalse(targetStack.isTopStackOnDisplay());
+ doReturn(targetStack).when(mRootActivityContainer).getTopDisplayFocusedStack();
+
+ // Use the stack as target to resume.
+ mRootActivityContainer.resumeFocusedStacksTopActivities(
+ targetStack, activity, null /* targetOptions */);
+
+ // Verify the target stack should resume its activity.
+ verify(targetStack, times(1)).resumeTopActivityUncheckedLocked(
+ eq(activity), eq(null /* targetOptions */));
+ }
+
+ /**
+ * Tests home activities that targeted sdk before Q cannot start on secondary display.
+ */
+ @Test
+ public void testStartHomeTargetSdkBeforeQ() throws Exception {
+ final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+ mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
+ doReturn(true).when(secondDisplay).supportsSystemDecorations();
+
+ final ActivityInfo info = new ActivityInfo();
+ info.launchMode = LAUNCH_MULTIPLE;
+ info.applicationInfo = new ApplicationInfo();
+ info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+ false /* allowInstrumenting */));
+
+ info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+ assertFalse(mRootActivityContainer.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+ false /* allowInstrumenting */));
+ }
+
+ /**
+ * Tests that home activities can be started on the displays that supports system decorations.
+ */
+ @Test
+ public void testStartHomeOnAllDisplays() {
+ // Create secondary displays.
+ final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+ mRootActivityContainer.addChild(secondDisplay, POSITION_TOP);
+ doReturn(true).when(secondDisplay).supportsSystemDecorations();
+
+ // Create mock tasks and other necessary mocks.
+ TaskBuilder taskBuilder = new TaskBuilder(mService.mStackSupervisor).setCreateStack(false);
+ final TaskRecord.TaskRecordFactory factory = mock(TaskRecord.TaskRecordFactory.class);
+ TaskRecord.setTaskRecordFactory(factory);
+ doAnswer(i -> taskBuilder.build()).when(factory)
+ .create(any(), anyInt(), any(), any(), any(), any());
+ doReturn(true).when(mRootActivityContainer)
+ .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
+ doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ any(), anyInt(), anyBoolean());
+
+ mRootActivityContainer.startHomeOnAllDisplays(0, "testStartHome");
+
+ assertTrue(mRootActivityContainer.getDefaultDisplay().getTopStack().isActivityTypeHome());
+ assertNotNull(secondDisplay.getTopStack());
+ assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
+ }
+
+ /**
+ * Tests that home activities won't be started before booting when display added.
+ */
+ @Test
+ public void testNotStartHomeBeforeBoot() {
+ final int displayId = 1;
+ final boolean isBooting = mService.mAmInternal.isBooting();
+ final boolean isBooted = mService.mAmInternal.isBooted();
+ try {
+ mService.mAmInternal.setBooting(false);
+ mService.mAmInternal.setBooted(false);
+ mRootActivityContainer.onDisplayAdded(displayId);
+ verify(mRootActivityContainer, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
+ } finally {
+ mService.mAmInternal.setBooting(isBooting);
+ mService.mAmInternal.setBooted(isBooted);
+ }
+ }
+
+ /**
+ * Tests whether home can be started if being instrumented.
+ */
+ @Test
+ public void testCanStartHomeWhenInstrumented() {
+ final ActivityInfo info = new ActivityInfo();
+ info.applicationInfo = new ApplicationInfo();
+ final WindowProcessController app = mock(WindowProcessController.class);
+ doReturn(app).when(mService).getProcessController(any(), anyInt());
+
+ // Can not start home if we don't want to start home while home is being instrumented.
+ doReturn(true).when(app).isInstrumenting();
+ assertFalse(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ false /* allowInstrumenting*/));
+
+ // Can start home for other cases.
+ assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ true /* allowInstrumenting*/));
+
+ doReturn(false).when(app).isInstrumenting();
+ assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ false /* allowInstrumenting*/));
+ assertTrue(mRootActivityContainer.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+ true /* allowInstrumenting*/));
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
index 0e1624e..a8b6dc3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java
@@ -63,7 +63,7 @@
final int numStacks = 2;
for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
final ActivityStack stack =
- new StackBuilder(mSupervisor).setCreateActivity(false).build();
+ new StackBuilder(mRootActivityContainer).setCreateActivity(false).build();
display.addChild(stack, POSITION_BOTTOM);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 6638eeb..bd8cd1f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -888,10 +888,10 @@
@Test
public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() {
- final Configuration overrideConfig = mSupervisor.getOverrideConfiguration();
+ final Configuration overrideConfig = mRootActivityContainer.getOverrideConfiguration();
// Egyptian Arabic is a RTL language.
overrideConfig.setLayoutDirection(new Locale("ar", "EG"));
- mSupervisor.onOverrideConfigurationChanged(overrideConfig);
+ mRootActivityContainer.onOverrideConfigurationChanged(overrideConfig);
final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
WINDOWING_MODE_FREEFORM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index e56edab..3c87721 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -65,7 +65,7 @@
final DisplayRotation displayRotation = new DisplayRotation(
mock(WindowManagerService.class), displayContent, displayPolicy,
- context, new Object());
+ mock(DisplayWindowSettings.class), context, new Object());
displayRotation.mPortraitRotation = Surface.ROTATION_0;
displayRotation.mLandscapeRotation = Surface.ROTATION_90;
displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c338581..45cfe1e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -147,7 +147,8 @@
public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
/**
- * A content {@link Uri} used to receive updates on advanced calling user setting.
+ * A content {@link Uri} used to receive updates on advanced calling user setting
+ * @see ImsMmTelManager#isAdvancedCallingSettingEnabled().
* <p>
* Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
* subscription advanced calling enabled
@@ -568,14 +569,6 @@
public static final String IS_OPPORTUNISTIC = "is_opportunistic";
/**
- * TelephonyProvider column name for subId of parent subscription of an opportunistic
- * subscription.
- * if the parent sub id is valid, then is_opportunistic should always to true.
- * @hide
- */
- public static final String PARENT_SUB_ID = "parent_sub_id";
-
- /**
* TelephonyProvider column name for group ID. Subscriptions with same group ID
* are considered bundled together, and should behave as a single subscription at
* certain scenarios.
diff --git a/tests/TouchLatency/.gitignore b/tests/TouchLatency/.gitignore
index bd79078..7f4121a 100644
--- a/tests/TouchLatency/.gitignore
+++ b/tests/TouchLatency/.gitignore
@@ -3,4 +3,5 @@
/.idea
.DS_Store
/build
+/gen
.iml
diff --git a/tests/TouchLatency/app/build.gradle b/tests/TouchLatency/app/build.gradle
index 2337110..2594322 100644
--- a/tests/TouchLatency/app/build.gradle
+++ b/tests/TouchLatency/app/build.gradle
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 21
- buildToolsVersion "21.1.2"
+ compileSdkVersion 28
+ buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.prefabulated.touchlatency"
minSdkVersion 21
- targetSdkVersion 21
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
}
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index b4b5ca7..360c22f 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -19,11 +19,9 @@
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
-import android.os.CountDownTimer;
+import android.graphics.Paint.Align;
import android.os.Bundle;
-import android.text.method.Touch;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Menu;
@@ -31,15 +29,17 @@
import android.view.MotionEvent;
import android.view.View;
import android.os.Trace;
-
-import java.util.ArrayList;
-import java.util.Collections;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
class TouchLatencyView extends View implements View.OnTouchListener {
private static final String LOG_TAG = "TouchLatency";
private static final int BACKGROUND_COLOR = 0xFF400080;
private static final int INNER_RADIUS = 70;
- private static final int BALL_RADIUS = 100;
+ private static final int BALL_DIAMETER = 200;
+ private static final int SEC_TO_NANOS = 1000000000;
+ private static final float FPS_UPDATE_THRESHOLD = 20;
+ private static final long BALL_VELOCITY = 420;
public TouchLatencyView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -58,13 +58,17 @@
mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRedPaint.setColor(0xFFFF0000);
mRedPaint.setStyle(Paint.Style.FILL);
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setColor(0xFFFFFFFF);
+ mTextPaint.setTextSize(100);
+ mTextPaint.setTextAlign(Align.RIGHT);
mTouching = false;
- mBallX = 100.0f;
- mBallY = 100.0f;
- mVelocityX = 7.0f;
- mVelocityY = 7.0f;
+ mLastDrawNano = 0;
+ mFps = 0;
+ mLastFpsUpdate = 0;
+ mFrameCount = 0;
Trace.endSection();
}
@@ -113,43 +117,70 @@
}
}
+ private Paint getBallColor() {
+ if (mFps > 75)
+ return mGreenPaint;
+ else if (mFps > 45)
+ return mYellowPaint;
+ else
+ return mRedPaint;
+ }
+
private void drawBall(Canvas canvas) {
Trace.beginSection("TouchLatencyView drawBall");
int width = canvas.getWidth();
int height = canvas.getHeight();
+ float fps = 0f;
- // Update position
- mBallX += mVelocityX;
- mBallY += mVelocityY;
+ long t = System.nanoTime();
+ long tDiff = t - mLastDrawNano;
+ mLastDrawNano = t;
+ mFrameCount++;
- // Clamp and change velocity if necessary
- float left = mBallX - BALL_RADIUS;
- if (left < 0) {
- left = 0;
- mVelocityX *= -1;
+ if (tDiff < SEC_TO_NANOS) {
+ fps = 1f * SEC_TO_NANOS / tDiff;
}
- float top = mBallY - BALL_RADIUS;
- if (top < 0) {
- top = 0;
- mVelocityY *= -1;
+ long fDiff = t - mLastFpsUpdate;
+ if (Math.abs(mFps - fps) > FPS_UPDATE_THRESHOLD) {
+ mFps = fps;
+ mLastFpsUpdate = t;
+ mFrameCount = 0;
+ } else if (fDiff > SEC_TO_NANOS) {
+ mFps = 1f * mFrameCount * SEC_TO_NANOS / fDiff;
+ mLastFpsUpdate = t;
+ mFrameCount = 0;
}
- float right = mBallX + BALL_RADIUS;
- if (right > width) {
- right = width;
- mVelocityX *= -1;
- }
+ final long pos = t * BALL_VELOCITY / SEC_TO_NANOS;
+ final long xMax = width - BALL_DIAMETER;
+ final long yMax = height - BALL_DIAMETER;
+ long xOffset = pos % xMax;
+ long yOffset = pos % yMax;
- float bottom = mBallY + BALL_RADIUS;
- if (bottom > height) {
- bottom = height;
- mVelocityY *= -1;
+ float left, right, top, bottom;
+
+ if (((pos / xMax) & 1) == 0) {
+ left = xMax - xOffset;
+ } else {
+ left = xOffset;
}
+ right = left + BALL_DIAMETER;
+
+ if (((pos / yMax) & 1) == 0) {
+ top = yMax - yOffset;
+ } else {
+ top = yOffset;
+ }
+ bottom = top + BALL_DIAMETER;
// Draw the ball
canvas.drawColor(BACKGROUND_COLOR);
- canvas.drawOval(left, top, right, bottom, mYellowPaint);
+ canvas.drawOval(left, top, right, bottom, getBallColor());
+ DecimalFormat df = new DecimalFormat("fps: #.##");
+ df.setRoundingMode(RoundingMode.HALF_UP);
+ canvas.drawText(df.format(mFps), width, 100, mTextPaint);
+
invalidate();
Trace.endSection();
}
@@ -176,15 +207,15 @@
Trace.endSection();
}
- private Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint;
+ private final Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint, mTextPaint;
private int mMode;
private boolean mTouching;
private float mTouchX, mTouchY;
private float mLastDrawnX, mLastDrawnY;
- private float mBallX, mBallY;
- private float mVelocityX, mVelocityY;
+ private long mLastDrawNano, mLastFpsUpdate, mFrameCount;
+ private float mFps;
}
public class TouchLatencyActivity extends Activity {
diff --git a/tests/TouchLatency/build.gradle b/tests/TouchLatency/build.gradle
index d3ff69d..03abe82 100644
--- a/tests/TouchLatency/build.gradle
+++ b/tests/TouchLatency/build.gradle
@@ -3,9 +3,10 @@
buildscript {
repositories {
jcenter()
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.1.0'
+ classpath 'com.android.tools.build:gradle:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -15,5 +16,6 @@
allprojects {
repositories {
jcenter()
+ google()
}
}
diff --git a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
index 0c71e76..111992a 100644
--- a/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
+++ b/tests/TouchLatency/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Apr 10 15:27:10 PDT 2013
+#Tue Nov 27 13:37:59 PST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
index ae3914e..d5987a5 100644
--- a/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
+++ b/tests/WindowManagerStressTest/src/test/windowmanagerstresstest/MainActivity.java
@@ -26,6 +26,7 @@
import android.view.Display;
import android.view.DisplayCutout;
import android.view.IWindowSession;
+import android.view.InsetsState;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
@@ -105,7 +106,7 @@
window.mSeq, mLayoutParams, -1, -1, View.VISIBLE, 0, -1, mTmpRect,
mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect, mTmpRect,
new DisplayCutout.ParcelableWrapper(), new MergedConfiguration(),
- new Surface());
+ new Surface(), new InsetsState());
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -131,8 +132,9 @@
final IWindowSession session = WindowManagerGlobal.getWindowSession();
final Rect tmpRect = new Rect();
try {
- final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq, layoutParams,
- View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect);
+ final int res = session.addToDisplayWithoutInputChannel(window, window.mSeq,
+ layoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, tmpRect, tmpRect,
+ new InsetsState());
} catch (RemoteException e) {
e.printStackTrace();
}
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 91cd1cb..cb8fef9 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -1285,10 +1285,19 @@
if clazz.fullname == "android.os.UserManager": return
for m in clazz.methods:
- if m.name.endswith("AsUser") or m.name.endswith("ForUser"): continue
if re.match("on[A-Z]+", m.name): continue
- if "android.os.UserHandle" in m.args:
- warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' or 'queryFooForUser'")
+
+ has_arg = "android.os.UserHandle" in m.args
+ has_name = m.name.endswith("AsUser") or m.name.endswith("ForUser")
+
+ if clazz.fullname.endswith("Manager") and has_arg:
+ warn(clazz, m, None, "When a method overload is needed to target a specific "
+ "UserHandle, callers should be directed to use "
+ "Context.createPackageContextAsUser() and re-obtain the relevant "
+ "Manager, and no new API should be added")
+ elif has_arg and not has_name:
+ warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' "
+ "or 'queryFooForUser'")
def verify_params(clazz):
diff --git a/tools/hiddenapi/exclude.sh b/tools/hiddenapi/exclude.sh
new file mode 100755
index 0000000..2291e5a
--- /dev/null
+++ b/tools/hiddenapi/exclude.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+set -e
+# Make sure that entries are not added for packages that are already fully handled using
+# annotations.
+LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
+# Each team should add a <team>_PACKAGES and <team>_EMAIL with the list of packages and
+# the team email to use in the event of this detecting an entry in a <team> package. Also
+# add <team> to the TEAMS list.
+LIBCORE_PACKAGES="\
+ android.icu \
+ android.system \
+ com.android.bouncycastle \
+ com.android.conscrypt \
+ com.android.okhttp \
+ com.sun \
+ dalvik \
+ java \
+ javax \
+ libcore \
+ org.apache.harmony \
+ org.json \
+ org.w3c.dom \
+ org.xml.sax \
+ sun \
+ "
+LIBCORE_EMAIL=libcore-team@android.com
+
+# List of teams.
+TEAMS=LIBCORE
+
+# Generate the list of packages and convert to a regular expression.
+PACKAGES=$(for t in $TEAMS; do echo $(eval echo \${${t}_PACKAGES}); done)
+RE=$(echo ${PACKAGES} | sed "s/ /|/g")
+git show --name-only --pretty=format: $1 | grep "config/hiddenapi-.*txt" | while read file; do
+ ENTRIES=$(grep -E "^L(${RE})/" <(git show $1:$file))
+ if [[ -n "${ENTRIES}" ]]; then
+ echo -e "\e[1m\e[31m$file $1 contains the following entries\e[0m"
+ echo -e "\e[1m\e[31mfor packages that are handled using UnsupportedAppUsage. Please remove\e[0m"
+ echo -e "\e[1m\e[31mthese entries and add annotations instead.\e[0m"
+ # Partition the entries by team and provide contact details to aid in fixing the issue.
+ for t in ${TEAMS}
+ do
+ PACKAGES=$(eval echo \${${t}_PACKAGES})
+ RE=$(echo ${PACKAGES} | sed "s/ /|/g")
+ TEAM_ENTRIES=$(grep -E "^L(${RE})/" <(echo "${ENTRIES}"))
+ if [[ -n "${TEAM_ENTRIES}" ]]; then
+ EMAIL=$(eval echo \${${t}_EMAIL})
+ echo -e "\e[33mContact ${EMAIL} or compat- for help with the following:\e[0m"
+ for i in ${ENTRIES}
+ do
+ echo -e "\e[33m ${i}\e[0m"
+ done
+ fi
+ done
+ exit 1
+ fi
+done
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index f58a006..d0efbcf 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -16,6 +16,7 @@
package android.net.wifi.p2p;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -25,6 +26,7 @@
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.net.NetworkInfo;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo;
import android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceResponse;
@@ -49,6 +51,8 @@
import dalvik.system.CloseGuard;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -158,6 +162,14 @@
*/
public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
+ /** @hide */
+ @IntDef({
+ WIFI_P2P_STATE_DISABLED,
+ WIFI_P2P_STATE_ENABLED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiP2pState {
+ }
+
/**
* Wi-Fi p2p is disabled.
*
@@ -250,6 +262,14 @@
*/
public static final String EXTRA_DISCOVERY_STATE = "discoveryState";
+ /** @hide */
+ @IntDef({
+ WIFI_P2P_DISCOVERY_STOPPED,
+ WIFI_P2P_DISCOVERY_STARTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiP2pDiscoveryState {
+ }
+
/**
* p2p discovery has stopped
*
@@ -502,6 +522,21 @@
/** @hide */
public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED = BASE + 89;
+ /** @hide */
+ public static final int REQUEST_P2P_STATE = BASE + 90;
+ /** @hide */
+ public static final int RESPONSE_P2P_STATE = BASE + 91;
+
+ /** @hide */
+ public static final int REQUEST_DISCOVERY_STATE = BASE + 92;
+ /** @hide */
+ public static final int RESPONSE_DISCOVERY_STATE = BASE + 93;
+
+ /** @hide */
+ public static final int REQUEST_NETWORK_INFO = BASE + 94;
+ /** @hide */
+ public static final int RESPONSE_NETWORK_INFO = BASE + 95;
+
/**
* Create a new WifiP2pManager instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -690,6 +725,43 @@
public void onHandoverMessageAvailable(String handoverMessage);
}
+ /** Interface for callback invocation when p2p state is available
+ * in response to {@link #requestP2pState}.
+ */
+ public interface P2pStateListener {
+ /**
+ * The requested p2p state is available.
+ * @param state Wi-Fi p2p state
+ * @see #WIFI_P2P_STATE_DISABLED
+ * @see #WIFI_P2P_STATE_ENABLED
+ */
+ void onP2pStateAvailable(@WifiP2pState int state);
+ }
+
+ /** Interface for callback invocation when p2p state is available
+ * in response to {@link #requestDiscoveryState}.
+ */
+ public interface DiscoveryStateListener {
+ /**
+ * The requested p2p discovery state is available.
+ * @param state Wi-Fi p2p discovery state
+ * @see #WIFI_P2P_DISCOVERY_STARTED
+ * @see #WIFI_P2P_DISCOVERY_STOPPED
+ */
+ void onDiscoveryStateAvailable(@WifiP2pDiscoveryState int state);
+ }
+
+ /** Interface for callback invocation when {@link android.net.NetworkInfo} is available
+ * in response to {@link #requestNetworkInfo}.
+ */
+ public interface NetworkInfoListener {
+ /**
+ * The requested {@link android.net.NetworkInfo} is available
+ * @param networkInfo Wi-Fi p2p {@link android.net.NetworkInfo}
+ */
+ void onNetworkInfoAvailable(NetworkInfo networkInfo);
+ }
+
/**
* Interface for callback invocation when ongoing peer info is available
* @hide
@@ -889,6 +961,24 @@
.onOngoingPeerAvailable(peerConfig);
}
break;
+ case RESPONSE_P2P_STATE:
+ if (listener != null) {
+ ((P2pStateListener) listener)
+ .onP2pStateAvailable(message.arg1);
+ }
+ break;
+ case RESPONSE_DISCOVERY_STATE:
+ if (listener != null) {
+ ((DiscoveryStateListener) listener)
+ .onDiscoveryStateAvailable(message.arg1);
+ }
+ break;
+ case RESPONSE_NETWORK_INFO:
+ if (listener != null) {
+ ((NetworkInfoListener) listener)
+ .onNetworkInfoAvailable((NetworkInfo) message.obj);
+ }
+ break;
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -1616,4 +1706,68 @@
c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
c.putListener(listener), config);
}
+
+ /**
+ * Request p2p enabled state.
+ *
+ * <p> This state indicates whether Wi-Fi p2p is enabled or disabled.
+ * The valid value is one of {@link #WIFI_P2P_STATE_DISABLED} or
+ * {@link #WIFI_P2P_STATE_ENABLED}. The state is returned using the
+ * {@link P2pStateListener} listener.
+ *
+ * <p> This state is also included in the {@link #WIFI_P2P_STATE_CHANGED_ACTION}
+ * broadcast event with extra {@link #EXTRA_WIFI_STATE}.
+ *
+ * @param c is the channel created at {@link #initialize}.
+ * @param listener for callback when p2p state is available..
+ */
+ public void requestP2pState(@NonNull Channel c,
+ @NonNull P2pStateListener listener) {
+ checkChannel(c);
+ if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
+ c.mAsyncChannel.sendMessage(REQUEST_P2P_STATE, 0, c.putListener(listener));
+ }
+
+ /**
+ * Request p2p discovery state.
+ *
+ * <p> This state indicates whether p2p discovery has started or stopped.
+ * The valid value is one of {@link #WIFI_P2P_DISCOVERY_STARTED} or
+ * {@link #WIFI_P2P_DISCOVERY_STOPPED}. The state is returned using the
+ * {@link DiscoveryStateListener} listener.
+ *
+ * <p> This state is also included in the {@link #WIFI_P2P_DISCOVERY_CHANGED_ACTION}
+ * broadcast event with extra {@link #EXTRA_DISCOVERY_STATE}.
+ *
+ * @param c is the channel created at {@link #initialize}.
+ * @param listener for callback when discovery state is available..
+ */
+ public void requestDiscoveryState(@NonNull Channel c,
+ @NonNull DiscoveryStateListener listener) {
+ checkChannel(c);
+ if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
+ c.mAsyncChannel.sendMessage(REQUEST_DISCOVERY_STATE, 0, c.putListener(listener));
+ }
+
+ /**
+ * Request network info.
+ *
+ * <p> This method provides the network info in the form of a {@link android.net.NetworkInfo}.
+ * {@link android.net.NetworkInfo#isAvailable()} indicates the p2p availability and
+ * {@link android.net.NetworkInfo#getDetailedState()} reports the current fine-grained state
+ * of the network. This {@link android.net.NetworkInfo} is returned using the
+ * {@link NetworkInfoListener} listener.
+ *
+ * <p> This information is also included in the {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION}
+ * broadcast event with extra {@link #EXTRA_NETWORK_INFO}.
+ *
+ * @param c is the channel created at {@link #initialize}.
+ * @param listener for callback when network info is available..
+ */
+ public void requestNetworkInfo(@NonNull Channel c,
+ @NonNull NetworkInfoListener listener) {
+ checkChannel(c);
+ if (listener == null) throw new IllegalArgumentException("This listener cannot be null.");
+ c.mAsyncChannel.sendMessage(REQUEST_NETWORK_INFO, 0, c.putListener(listener));
+ }
}