Merge "Check for null in addition to instanceof Face"
diff --git a/Android.bp b/Android.bp
index 092f548..abeeb43 100644
--- a/Android.bp
+++ b/Android.bp
@@ -570,7 +570,6 @@
"telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
"telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
- "telephony/java/com/android/internal/telephony/IRcs.aidl",
"telephony/java/com/android/internal/telephony/ISms.aidl",
"telephony/java/com/android/internal/telephony/ISub.aidl",
"telephony/java/com/android/internal/telephony/IAns.aidl",
@@ -601,6 +600,7 @@
"telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+ "telephony/java/com/android/internal/telephony/rcs/IRcs.aidl",
"wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl",
"wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl",
"wifi/java/android/net/wifi/ISoftApCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 533c70f..28863b8 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -740,6 +740,7 @@
field public static final int immersive = 16843456; // 0x10102c0
field public static final int importantForAccessibility = 16843690; // 0x10103aa
field public static final int importantForAutofill = 16844120; // 0x1010558
+ field public static final int importantForContentCapture = 16844182; // 0x1010596
field public static final int inAnimation = 16843127; // 0x1010177
field public static final int includeFontPadding = 16843103; // 0x101015f
field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -7580,6 +7581,8 @@
method public java.lang.String getShortcutId();
method public long getTimeStamp();
field public static final int CONFIGURATION_CHANGE = 5; // 0x5
+ field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
+ field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
field public static final int KEYGUARD_HIDDEN = 18; // 0x12
field public static final int KEYGUARD_SHOWN = 17; // 0x11
field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
@@ -7597,9 +7600,11 @@
method public void add(android.app.usage.UsageStats);
method public int describeContents();
method public long getFirstTimeStamp();
+ method public long getLastTimeForegroundServiceUsed();
method public long getLastTimeStamp();
method public long getLastTimeUsed();
method public java.lang.String getPackageName();
+ method public long getTotalTimeForegroundServiceUsed();
method public long getTotalTimeInForeground();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.usage.UsageStats> CREATOR;
@@ -16628,6 +16633,8 @@
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
+ field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5; // 0x5
+ field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6; // 0x6
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1; // 0x1
@@ -20712,6 +20719,51 @@
enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_STANDARD;
}
+ public abstract class Transliterator {
+ method public static final android.icu.text.Transliterator createFromRules(java.lang.String, java.lang.String, int);
+ method public void filteredTransliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, boolean);
+ method public final void finishTransliteration(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+ method public static final java.util.Enumeration<java.lang.String> getAvailableIDs();
+ method public static final java.util.Enumeration<java.lang.String> getAvailableSources();
+ method public static final java.util.Enumeration<java.lang.String> getAvailableTargets(java.lang.String);
+ method public static final java.util.Enumeration<java.lang.String> getAvailableVariants(java.lang.String, java.lang.String);
+ method public static final java.lang.String getDisplayName(java.lang.String);
+ method public static java.lang.String getDisplayName(java.lang.String, java.util.Locale);
+ method public static java.lang.String getDisplayName(java.lang.String, android.icu.util.ULocale);
+ method public android.icu.text.Transliterator[] getElements();
+ method public final android.icu.text.UnicodeFilter getFilter();
+ method public final java.lang.String getID();
+ method public static final android.icu.text.Transliterator getInstance(java.lang.String);
+ method public static android.icu.text.Transliterator getInstance(java.lang.String, int);
+ method public final android.icu.text.Transliterator getInverse();
+ method public final int getMaximumContextLength();
+ method public final android.icu.text.UnicodeSet getSourceSet();
+ method public android.icu.text.UnicodeSet getTargetSet();
+ method public void setFilter(android.icu.text.UnicodeFilter);
+ method public java.lang.String toRules(boolean);
+ method public final int transliterate(android.icu.text.Replaceable, int, int);
+ method public final void transliterate(android.icu.text.Replaceable);
+ method public final java.lang.String transliterate(java.lang.String);
+ method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, java.lang.String);
+ method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, int);
+ method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+ field public static final int FORWARD = 0; // 0x0
+ field public static final int REVERSE = 1; // 0x1
+ }
+
+ public static class Transliterator.Position {
+ ctor public Transliterator.Position();
+ ctor public Transliterator.Position(int, int, int);
+ ctor public Transliterator.Position(int, int, int, int);
+ ctor public Transliterator.Position(android.icu.text.Transliterator.Position);
+ method public void set(android.icu.text.Transliterator.Position);
+ method public final void validate(int);
+ field public int contextLimit;
+ field public int contextStart;
+ field public int limit;
+ field public int start;
+ }
+
public abstract class UCharacterIterator implements java.lang.Cloneable {
ctor protected UCharacterIterator();
method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -24208,6 +24260,8 @@
method public static int getMaxSecurityLevel();
method public int getMaxSessionCount();
method public android.os.PersistableBundle getMetrics();
+ method public java.util.List<byte[]> getOfflineLicenseKeySetIds();
+ method public int getOfflineLicenseState(byte[]);
method public int getOpenSessionCount();
method public byte[] getPropertyByteArray(java.lang.String);
method public java.lang.String getPropertyString(java.lang.String);
@@ -24228,6 +24282,7 @@
method public void releaseSecureStops(byte[]);
method public void removeAllSecureStops();
method public void removeKeys(byte[]);
+ method public void removeOfflineLicense(byte[]);
method public void removeSecureStop(byte[]);
method public void restoreKeys(byte[], byte[]);
method public void setOnEventListener(android.media.MediaDrm.OnEventListener);
@@ -24250,6 +24305,9 @@
field public static final int KEY_TYPE_OFFLINE = 2; // 0x2
field public static final int KEY_TYPE_RELEASE = 3; // 0x3
field public static final int KEY_TYPE_STREAMING = 1; // 0x1
+ field public static final int OFFLINE_LICENSE_INACTIVE = 2; // 0x2
+ field public static final int OFFLINE_LICENSE_STATE_UNKNOWN = 0; // 0x0
+ field public static final int OFFLINE_LICENSE_USABLE = 1; // 0x1
field public static final java.lang.String PROPERTY_ALGORITHMS = "algorithms";
field public static final java.lang.String PROPERTY_DESCRIPTION = "description";
field public static final java.lang.String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
@@ -42083,7 +42141,7 @@
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000
field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000
- field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
+ field public static final deprecated int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000
field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
field public static final int CAPABILITY_HOLD = 1; // 0x1
field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80
@@ -42503,6 +42561,7 @@
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
method public android.telecom.PhoneAccountHandle getSimCallManager();
+ method public java.lang.String getSystemDialerPackage();
method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
method public boolean handleMmi(java.lang.String);
method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
@@ -48785,6 +48844,7 @@
method public int getId();
method public int getImportantForAccessibility();
method public int getImportantForAutofill();
+ method public int getImportantForContentCapture();
method public boolean getKeepScreenOn();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
method public int getLabelFor();
@@ -48918,6 +48978,7 @@
method public boolean isHovered();
method public boolean isImportantForAccessibility();
method public final boolean isImportantForAutofill();
+ method public final boolean isImportantForContentCapture();
method public boolean isInEditMode();
method public boolean isInLayout();
method public boolean isInTouchMode();
@@ -48992,6 +49053,7 @@
method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
method public void onProvideAutofillStructure(android.view.ViewStructure, int);
method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+ method public boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
method public void onProvideStructure(android.view.ViewStructure);
method public void onProvideVirtualStructure(android.view.ViewStructure);
method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -49110,6 +49172,7 @@
method public void setId(int);
method public void setImportantForAccessibility(int);
method public void setImportantForAutofill(int);
+ method public void setImportantForContentCapture(int);
method public void setKeepScreenOn(boolean);
method public void setKeyboardNavigationCluster(boolean);
method public void setLabelFor(int);
@@ -49280,6 +49343,11 @@
field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
+ field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
+ field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
+ field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
+ field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
+ field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
field public static final int INVISIBLE = 4; // 0x4
field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -51734,6 +51802,10 @@
method public void disableContentCapture();
method public android.content.ComponentName getIntelligenceServiceComponentName();
method public boolean isContentCaptureEnabled();
+ method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+ method public void notifyViewAppeared(android.view.ViewStructure);
+ method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+ method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
field public static final int FLAG_USER_INPUT = 1; // 0x1
}
@@ -52047,6 +52119,7 @@
public final class TextLinks implements android.os.Parcelable {
method public int apply(android.text.Spannable, int, java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.view.textclassifier.TextLinks.TextLinkSpan>);
method public int describeContents();
+ method public android.os.Bundle getExtras();
method public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
method public void writeToParcel(android.os.Parcel, int);
field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
@@ -52063,12 +52136,14 @@
method public android.view.textclassifier.TextLinks.Builder addLink(int, int, java.util.Map<java.lang.String, java.lang.Float>);
method public android.view.textclassifier.TextLinks build();
method public android.view.textclassifier.TextLinks.Builder clearTextLinks();
+ method public android.view.textclassifier.TextLinks.Builder setExtras(android.os.Bundle);
}
public static final class TextLinks.Request implements android.os.Parcelable {
method public int describeContents();
method public android.os.LocaleList getDefaultLocales();
method public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
+ method public android.os.Bundle getExtras();
method public java.lang.CharSequence getText();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Request> CREATOR;
@@ -52079,6 +52154,7 @@
method public android.view.textclassifier.TextLinks.Request build();
method public android.view.textclassifier.TextLinks.Request.Builder setDefaultLocales(android.os.LocaleList);
method public android.view.textclassifier.TextLinks.Request.Builder setEntityConfig(android.view.textclassifier.TextClassifier.EntityConfig);
+ method public android.view.textclassifier.TextLinks.Request.Builder setExtras(android.os.Bundle);
}
public static final class TextLinks.TextLink implements android.os.Parcelable {
@@ -52103,6 +52179,7 @@
method public float getConfidenceScore(java.lang.String);
method public java.lang.String getEntity(int);
method public int getEntityCount();
+ method public android.os.Bundle getExtras();
method public java.lang.String getId();
method public int getSelectionEndIndex();
method public int getSelectionStartIndex();
@@ -52114,6 +52191,7 @@
ctor public TextSelection.Builder(int, int);
method public android.view.textclassifier.TextSelection build();
method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float);
+ method public android.view.textclassifier.TextSelection.Builder setExtras(android.os.Bundle);
method public android.view.textclassifier.TextSelection.Builder setId(java.lang.String);
}
@@ -52121,6 +52199,7 @@
method public int describeContents();
method public android.os.LocaleList getDefaultLocales();
method public int getEndIndex();
+ method public android.os.Bundle getExtras();
method public int getStartIndex();
method public java.lang.CharSequence getText();
method public void writeToParcel(android.os.Parcel, int);
@@ -52131,6 +52210,7 @@
ctor public TextSelection.Request.Builder(java.lang.CharSequence, int, int);
method public android.view.textclassifier.TextSelection.Request build();
method public android.view.textclassifier.TextSelection.Request.Builder setDefaultLocales(android.os.LocaleList);
+ method public android.view.textclassifier.TextSelection.Request.Builder setExtras(android.os.Bundle);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index e0c58b4..5c4efcd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4109,8 +4109,12 @@
}
public final class PowerManager {
+ method public int getPowerSaveMode();
+ method public boolean setDynamicPowerSavings(boolean, int);
method public boolean setPowerSaveMode(boolean);
method public void userActivity(long, int, int);
+ field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+ field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
@@ -5427,15 +5431,21 @@
method public int getAllPhoneAccountsCount();
method public int getCallState();
method public android.telecom.PhoneAccountHandle getConnectionManager();
+ method public int getCurrentTtyMode();
method public deprecated android.content.ComponentName getDefaultPhoneApp();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
method public boolean isInEmergencyCall();
method public boolean isRinging();
method public boolean isTtySupported();
+ method public boolean setDefaultDialer(java.lang.String);
field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
field public static final java.lang.String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+ field public static final int TTY_MODE_FULL = 1; // 0x1
+ field public static final int TTY_MODE_HCO = 2; // 0x2
+ field public static final int TTY_MODE_OFF = 0; // 0x0
+ field public static final int TTY_MODE_VCO = 3; // 0x3
}
}
@@ -6999,8 +7009,8 @@
field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
- field public static final int TYPE_VIEW_ADDED = 5; // 0x5
- field public static final int TYPE_VIEW_REMOVED = 6; // 0x6
+ field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
+ field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 8b8c542..5531014 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -25,6 +25,10 @@
package android.app {
+ public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ method public void onMovedToDisplay(int, android.content.res.Configuration);
+ }
+
public class ActivityManager {
method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
@@ -710,6 +714,7 @@
public class Environment {
method public static java.io.File buildPath(java.io.File, java.lang.String...);
+ method public static java.io.File getProductDirectory();
method public static java.io.File getStorageDirectory();
}
@@ -739,7 +744,11 @@
}
public final class PowerManager {
+ method public int getPowerSaveMode();
+ method public boolean setDynamicPowerSavings(boolean, int);
method public boolean setPowerSaveMode(boolean);
+ field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+ field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
}
public class Process {
@@ -976,6 +985,9 @@
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final java.lang.String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
+ field public static final java.lang.String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+ field public static final java.lang.String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
+ field public static final java.lang.String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
field public static final java.lang.String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
field public static final java.lang.String LOW_POWER_MODE = "low_power";
@@ -1591,6 +1603,7 @@
public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
method public static java.lang.String actionToString(int);
+ method public final void setDisplayId(int);
field public static final int LAST_KEYCODE = 288; // 0x120
}
@@ -1637,9 +1650,9 @@
}
public abstract interface WindowManager implements android.view.ViewManager {
- method public abstract void setShouldShowIme(int, boolean);
- method public abstract void setShouldShowWithInsecureKeyguard(int, boolean);
- method public abstract void setShouldShowSystemDecors(int, boolean);
+ method public default void setShouldShowIme(int, boolean);
+ method public default void setShouldShowSystemDecors(int, boolean);
+ method public default void setShouldShowWithInsecureKeyguard(int, boolean);
}
public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 33c274e..00c49e3 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -138,7 +138,8 @@
std::stringstream stream;
for (auto iter = interesting_apks.cbegin(); iter != interesting_apks.cend(); ++iter) {
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, *iter);
- if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), out_error) &&
+ std::stringstream dev_null;
+ if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), dev_null) &&
!Create(std::vector<std::string>({
"--target-apk-path",
target_apk_path,
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index c6d717a..783c8c4 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -127,6 +127,8 @@
filterType = VolumeInfo.TYPE_PRIVATE;
} else if ("emulated".equals(filter)) {
filterType = VolumeInfo.TYPE_EMULATED;
+ } else if ("stub".equals(filter)) {
+ filterType = VolumeInfo.TYPE_STUB;
} else {
filterType = -1;
}
@@ -314,7 +316,7 @@
private static int showUsage() {
System.err.println("usage: sm list-disks [adoptable]");
- System.err.println(" sm list-volumes [public|private|emulated|all]");
+ System.err.println(" sm list-volumes [public|private|emulated|stub|all]");
System.err.println(" sm has-adoptable");
System.err.println(" sm get-primary-storage-uuid");
System.err.println(" sm set-force-adoptable [on|off|default]");
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index a3cd8a3..0114ff4 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -72,6 +72,7 @@
"src/external/StatsPuller.cpp",
"src/external/StatsCompanionServicePuller.cpp",
"src/external/SubsystemSleepStatePuller.cpp",
+ "src/external/PowerStatsPuller.cpp",
"src/external/ResourceHealthManagerPuller.cpp",
"src/external/ResourceThermalManagerPuller.cpp",
"src/external/StatsPullerManager.cpp",
@@ -134,6 +135,7 @@
"android.hardware.health@2.0",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
+ "android.hardware.power.stats@1.0",
"android.hardware.thermal@1.0",
"libpackagelistparser",
"libsysutils",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5620184..21e7203 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -190,6 +190,7 @@
ProcessCpuTime process_cpu_time = 10035;
NativeProcessMemoryState native_process_memory_state = 10036;
CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
+ OnDevicePowerMeasurement on_device_power_measurement = 10038;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -2262,6 +2263,27 @@
}
/**
+ * Pulls on-device power measurement information.
+ * Data defined by hardware/interfaces/power/stats/1.0/types.hal.
+ * Pulled from:
+ * frameworks/base/cmds/statsd/src/external/PowerStatsPuller.cpp
+ */
+message OnDevicePowerMeasurement {
+ // Name of the subsystem (to which the rail belongs).
+ optional string subsystem_name = 1;
+
+ // Rail name. The rail lies within the subsystem.
+ optional string rail_name = 2;
+
+ // Time (in ms since boot) at which the rail energy value was measured.
+ // This may differ slightly from the time that statsd logs this information.
+ optional uint64 measurement_timestamp_millis = 3;
+
+ // Accumulated energy used via the rail since device boot in uWs.
+ optional uint64 energy_microwatt_secs = 4;
+}
+
+/**
* Pulls Cpu time per frequency.
* Pulls the time the cpu spend on the frequency index. Frequency index
* starts from highest to lowest. The value should be monotonically
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
new file mode 100644
index 0000000..71e5fa0
--- /dev/null
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "Log.h"
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+#include <vector>
+
+#include "PowerStatsPuller.h"
+#include "stats_log_util.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHal = nullptr;
+std::mutex gPowerStatsHalMutex;
+bool gPowerStatsExist = true; // Initialized to ensure making a first attempt.
+std::vector<RailInfo> gRailInfo;
+
+bool getPowerStatsHal() {
+ if (gPowerStatsHal == nullptr && gPowerStatsExist) {
+ gPowerStatsHal = android::hardware::power::stats::V1_0::IPowerStats::getService();
+ if (gPowerStatsHal == nullptr) {
+ ALOGW("Couldn't load power.stats HAL service");
+ gPowerStatsExist = false;
+ }
+ }
+ return gPowerStatsHal != nullptr;
+}
+
+PowerStatsPuller::PowerStatsPuller() : StatsPuller(android::util::ON_DEVICE_POWER_MEASUREMENT) {
+}
+
+bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ if (!getPowerStatsHal()) {
+ ALOGE("power.stats Hal not loaded");
+ return false;
+ }
+
+ int64_t wallClockTimestampNs = getWallClockNs();
+ int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
+ data->clear();
+
+ // Pull getRailInfo if necessary
+ if (gRailInfo.empty()) {
+ bool resultSuccess = true;
+ Return<void> ret = gPowerStatsHal->getRailInfo(
+ [&resultSuccess](const hidl_vec<RailInfo> &list, Status status) {
+ resultSuccess = (status == Status::SUCCESS || status == Status::NOT_SUPPORTED);
+ if (status != Status::SUCCESS) return;
+
+ gRailInfo.reserve(list.size());
+ for (size_t i = 0; i < list.size(); ++i) {
+ gRailInfo.push_back(list[i]);
+ }
+ });
+ if (!resultSuccess || !ret.isOk()) {
+ ALOGE("power.stats getRailInfo() failed. Description: %s", ret.description().c_str());
+ gPowerStatsHal = nullptr;
+ return false;
+ }
+ // If SUCCESS but empty, or if NOT_SUPPORTED, then never try again.
+ if (gRailInfo.empty()) {
+ ALOGE("power.stats has no rail information");
+ gPowerStatsExist = false; // No rail info, so never try again.
+ return false;
+ }
+ }
+
+ // Pull getEnergyData and write the data out
+ const hidl_vec<uint32_t> desiredRailIndices; // Empty vector indicates we want all.
+ bool resultSuccess = true;
+ Return<void> ret = gPowerStatsHal->getEnergyData(desiredRailIndices,
+ [&data, wallClockTimestampNs, elapsedTimestampNs, &resultSuccess]
+ (hidl_vec<EnergyData> energyDataList, Status status) {
+ resultSuccess = (status == Status::SUCCESS);
+ if (!resultSuccess) return;
+
+ for (size_t i = 0; i < energyDataList.size(); i++) {
+ const EnergyData& energyData = energyDataList[i];
+
+ if (energyData.index >= gRailInfo.size()) {
+ ALOGE("power.stats getEnergyData() returned an invalid rail index %u.",
+ energyData.index);
+ resultSuccess = false;
+ return;
+ }
+ const RailInfo& rail = gRailInfo[energyData.index];
+
+ auto ptr = make_shared<LogEvent>(android::util::ON_DEVICE_POWER_MEASUREMENT,
+ wallClockTimestampNs, elapsedTimestampNs);
+ ptr->write(rail.subsysName);
+ ptr->write(rail.railName);
+ ptr->write(energyData.timestamp);
+ ptr->write(energyData.energy);
+ ptr->init();
+ data->push_back(ptr);
+
+ VLOG("power.stat: %s.%s: %llu, %llu",
+ rail.subsysName.c_str(),
+ rail.railName.c_str(),
+ (unsigned long long)energyData.timestamp,
+ (unsigned long long)energyData.energy);
+ }
+ });
+ if (!resultSuccess || !ret.isOk()) {
+ ALOGE("power.stats getEnergyData() failed. Description: %s", ret.description().c_str());
+ gPowerStatsHal = nullptr;
+ return false;
+ }
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/cmds/statsd/src/external/PowerStatsPuller.h
similarity index 63%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to cmds/statsd/src/external/PowerStatsPuller.h
index ede8695..dd5ff8f 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/cmds/statsd/src/external/PowerStatsPuller.h
@@ -14,8 +14,23 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+#pragma once
-interface IRcs {
- void deleteThread(int threadId);
-}
\ No newline at end of file
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads hal for power.stats
+ */
+class PowerStatsPuller : public StatsPuller {
+public:
+ PowerStatsPuller();
+ bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9633980..8378ae1 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -26,6 +26,7 @@
#include "../logd/LogEvent.h"
#include "../stats_log_util.h"
#include "../statscompanion_util.h"
+#include "PowerStatsPuller.h"
#include "ResourceHealthManagerPuller.h"
#include "ResourceThermalManagerPuller.h"
#include "StatsCompanionServicePuller.h"
@@ -86,6 +87,9 @@
// subsystem_sleep_state
{android::util::SUBSYSTEM_SLEEP_STATE,
{{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+ // on_device_power_measurement
+ {android::util::ON_DEVICE_POWER_MEASUREMENT,
+ {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
// cpu_time_per_freq
{android::util::CPU_TIME_PER_FREQ,
{{3},
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index 5c46a29..aa789c7 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -274,6 +274,7 @@
optional bool use_diff = 12;
enum ValueDirection {
+ UNKNOWN = 0;
INCREASING = 1;
DECREASING = 2;
ANY = 3;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 0997566..851e35b 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -441,6 +441,8 @@
Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
+Landroid/inputmethodservice/IInputMethodSessionWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
+Landroid/inputmethodservice/IInputMethodWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
Landroid/location/ICountryListener$Stub;-><init>()V
Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -4210,170 +4212,6 @@
Lcom/android/okhttp/Response;->message:Ljava/lang/String;
Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
-Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;-><init>()V
-Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;->add(Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>(Ljava/io/InputStream;)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/ASN1InputStream;->readObject()Lcom/android/org/bouncycastle/asn1/ASN1Primitive;
-Lcom/android/org/bouncycastle/asn1/ASN1Integer;-><init>(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/asn1/DERBitString;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/DEREncodableVector;-><init>()V
-Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(J)V
-Lcom/android/org/bouncycastle/asn1/DERInteger;-><init>(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/asn1/DERNull;->INSTANCE:Lcom/android/org/bouncycastle/asn1/DERNull;
-Lcom/android/org/bouncycastle/asn1/DERObjectIdentifier;-><init>(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/asn1/DEROctetString;-><init>([B)V
-Lcom/android/org/bouncycastle/asn1/DEROutputStream;-><init>(Ljava/io/OutputStream;)V
-Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>()V
-Lcom/android/org/bouncycastle/asn1/DERSequence;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
-Lcom/android/org/bouncycastle/asn1/DERSet;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1EncodableVector;)V
-Lcom/android/org/bouncycastle/asn1/pkcs/PKCSObjectIdentifiers;->sha256WithRSAEncryption:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;)V
-Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;Lcom/android/org/bouncycastle/asn1/ASN1Encodable;)V
-Lcom/android/org/bouncycastle/asn1/x509/Certificate;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/Certificate;
-Lcom/android/org/bouncycastle/asn1/x509/DigestInfo;-><init>(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;[B)V
-Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;->getInstance(Ljava/lang/Object;)Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;
-Lcom/android/org/bouncycastle/asn1/x509/Time;-><init>(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;-><init>()V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->generateTBSCertificate()Lcom/android/org/bouncycastle/asn1/x509/TBSCertificate;
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setEndDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setIssuer(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSerialNumber(Lcom/android/org/bouncycastle/asn1/ASN1Integer;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSignature(Lcom/android/org/bouncycastle/asn1/x509/AlgorithmIdentifier;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setStartDate(Lcom/android/org/bouncycastle/asn1/x509/Time;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubject(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/asn1/x509/V3TBSCertificateGenerator;->setSubjectPublicKeyInfo(Lcom/android/org/bouncycastle/asn1/x509/SubjectPublicKeyInfo;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Lcom/android/org/bouncycastle/asn1/ASN1Sequence;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;-><init>(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->CN:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getOIDs()Ljava/util/Vector;
-Lcom/android/org/bouncycastle/asn1/x509/X509Name;->getValues()Ljava/util/Vector;
-Lcom/android/org/bouncycastle/asn1/x9/X9ObjectIdentifiers;->ecdsa_with_SHA256:Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;
-Lcom/android/org/bouncycastle/jce/provider/BouncyCastleProvider;-><init>()V
-Lcom/android/org/bouncycastle/jce/provider/X509CertificateObject;-><init>(Lcom/android/org/bouncycastle/asn1/x509/Certificate;)V
-Lcom/android/org/bouncycastle/jce/X509Principal;-><init>([B)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;-><init>()V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->generate(Ljava/security/PrivateKey;)Ljava/security/cert/X509Certificate;
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setIssuerDN(Ljavax/security/auth/x500/X500Principal;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotAfter(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setNotBefore(Ljava/util/Date;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setPublicKey(Ljava/security/PublicKey;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSerialNumber(Ljava/math/BigInteger;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSignatureAlgorithm(Ljava/lang/String;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Lcom/android/org/bouncycastle/asn1/x509/X509Name;)V
-Lcom/android/org/bouncycastle/x509/X509V3CertificateGenerator;->setSubjectDN(Ljavax/security/auth/x500/X500Principal;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setApplicationProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/ClientSessionContext;->getSession(Ljava/lang/String;I)Lcom/android/org/conscrypt/NativeSslSession;
-Lcom/android/org/conscrypt/ClientSessionContext;->setPersistentCache(Lcom/android/org/conscrypt/SSLClientSessionCache;)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/FileClientSessionCache$Impl;->getSessionData(Ljava/lang/String;I)[B
-Lcom/android/org/conscrypt/FileClientSessionCache;->usingDirectory(Ljava/io/File;)Lcom/android/org/conscrypt/SSLClientSessionCache;
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_pack_X509([J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_seq_unpack_X509_bio(J)[J
-Lcom/android/org/conscrypt/NativeCrypto;->ASN1_TIME_to_Calendar(JLjava/util/Calendar;)V
-Lcom/android/org/conscrypt/NativeCrypto;->BIO_free_all(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_InputStream(Lcom/android/org/conscrypt/OpenSSLBIOInputStream;Z)J
-Lcom/android/org/conscrypt/NativeCrypto;->create_BIO_OutputStream(Ljava/io/OutputStream;)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_PKCS7_bio(JI)[J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_SSL_SESSION([B)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509([B)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_bio(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->d2i_X509_CRL_bio(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_clear_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EC_GROUP_new_by_curve_name(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EC_POINT_clear_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_CTX_new()J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_CIPHER_iv_length(J)I
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_cipherbyname(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_get_digestbyname(Ljava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_create()J
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_CTX_destroy(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_MD_size(J)I
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->EVP_PKEY_new_RSA([B[B[B[B[B[B[B[B)J
-Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_ext_oids(JI)[Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->get_X509_REVOKED_revocationDate(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_PKCS7([J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_SSL_SESSION(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->i2d_X509_REVOKED(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_PKCS7(JI)[J
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->PEM_read_bio_X509_CRL(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->RAND_bytes([B)V
-Lcom/android/org/conscrypt/NativeCrypto;->RSA_generate_key_ex(I[B)J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_CTX_new()J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_cipher(J)Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_free(J)V
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_time(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_get_version(J)Ljava/lang/String;
-Lcom/android/org/conscrypt/NativeCrypto;->SSL_SESSION_session_id(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_dup(J)J
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext(JLjava/lang/String;)J
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_ext_oid(JLjava/lang/String;)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_get_serialNumber(J)[B
-Lcom/android/org/conscrypt/NativeCrypto;->X509_REVOKED_print(JJ)V
-Lcom/android/org/conscrypt/NativeCrypto;->X509_supported_extension(J)I
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;-><init>(Ljava/io/InputStream;Z)V
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->getBioContext()J
-Lcom/android/org/conscrypt/OpenSSLBIOInputStream;->release()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl$TLSv12;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLContextImpl;->engineGetClientSessionContext()Lcom/android/org/conscrypt/ClientSessionContext;
-Lcom/android/org/conscrypt/OpenSSLContextImpl;->getPreferred()Lcom/android/org/conscrypt/OpenSSLContextImpl;
-Lcom/android/org/conscrypt/OpenSSLKey;-><init>(J)V
-Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
-Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
-Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
-Lcom/android/org/conscrypt/OpenSSLKeyHolder;->getOpenSSLKey()Lcom/android/org/conscrypt/OpenSSLKey;
-Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLSocketFactoryImpl;->sslParameters:Lcom/android/org/conscrypt/SSLParametersImpl;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->fromX509PemInputStream(Ljava/io/InputStream;)Lcom/android/org/conscrypt/OpenSSLX509Certificate;
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
-Lcom/android/org/conscrypt/SSLParametersImpl;->getDefault()Lcom/android/org/conscrypt/SSLParametersImpl;
-Lcom/android/org/conscrypt/SSLParametersImpl;->getDefaultX509TrustManager()Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/SSLParametersImpl;->getX509TrustManager()Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/SSLParametersImpl;->setEnabledProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/SSLParametersImpl;->x509TrustManager:Ljavax/net/ssl/X509TrustManager;
-Lcom/android/org/conscrypt/TrustedCertificateStore;-><init>()V
-Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
-Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
-Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
-Lcom/android/org/conscrypt/X509PublicKey;-><init>(Ljava/lang/String;[B)V
Lcom/android/server/net/BaseNetworkObserver;-><init>()V
Lcom/android/server/net/NetlinkTracker;-><init>(Ljava/lang/String;Lcom/android/server/net/NetlinkTracker$Callback;)V
Lcom/android/server/net/NetlinkTracker;->clearLinkProperties()V
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fade574..553acc8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
import android.annotation.RequiresPermission;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.VoiceInteractor.Request;
import android.app.admin.DevicePolicyManager;
@@ -2346,6 +2347,7 @@
* @see View#onMovedToDisplay(int, Configuration)
* @hide
*/
+ @TestApi
public void onMovedToDisplay(int displayId, Configuration config) {
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 45d68fa..0e5b976 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -161,13 +161,6 @@
public abstract List<ProcessMemoryState> getMemoryStateForProcesses();
/**
- * Returns a list that contains the memory stats for monitored native processes.
- *
- * The list of the monitored processes is defined in MemoryStatUtil class.
- */
- public abstract List<ProcessMemoryState> getMemoryStateForNativeProcesses();
-
- /**
* Checks to see if the calling pid is allowed to handle the user. Returns adjusted user id as
* needed.
*/
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ac16442..015bc6c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1009,7 +1009,7 @@
* from its event processing, though it may <em>not</em> have completely
* finished reacting from the event -- for example, if it needs to update
* its display as a result, it may still be in the process of doing that.
- *
+ *
* @param event The event to send to the current focus.
*/
public void sendKeySync(KeyEvent event) {
@@ -1017,14 +1017,7 @@
long downTime = event.getDownTime();
long eventTime = event.getEventTime();
- int action = event.getAction();
- int code = event.getKeyCode();
- int repeatCount = event.getRepeatCount();
- int metaState = event.getMetaState();
- int deviceId = event.getDeviceId();
- int scancode = event.getScanCode();
int source = event.getSource();
- int flags = event.getFlags();
if (source == InputDevice.SOURCE_UNKNOWN) {
source = InputDevice.SOURCE_KEYBOARD;
}
@@ -1034,12 +1027,14 @@
if (downTime == 0) {
downTime = eventTime;
}
- KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
- deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
+ KeyEvent newEvent = new KeyEvent(event);
+ newEvent.setTime(downTime, eventTime);
+ newEvent.setSource(source);
+ newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
InputManager.getInstance().injectInputEvent(newEvent,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
-
+
/**
* Sends an up and down key event sync to the currently focused window.
*
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 5850540..0123551 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -153,6 +153,7 @@
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
+import android.telephony.rcs.RcsManager;
import android.util.ArrayMap;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -547,6 +548,14 @@
return new SubscriptionManager(ctx.getOuterContext());
}});
+ registerService(Context.TELEPHONY_RCS_SERVICE, RcsManager.class,
+ new CachedServiceFetcher<RcsManager>() {
+ @Override
+ public RcsManager createService(ContextImpl ctx) {
+ return new RcsManager();
+ }
+ });
+
registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
new CachedServiceFetcher<CarrierConfigManager>() {
@Override
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 308b39e..3a5975a 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -50,12 +50,20 @@
public static final int NONE = 0;
/**
- * An event type denoting that a component moved to the foreground.
+ * An event type denoting that an {@link android.app.Activity} moved to the foreground.
+ * This event has a package name and class name associated with it and can be retrieved
+ * using {@link #getPackageName()} and {@link #getClassName()}.
+ * If a package has multiple activities, this event is reported for each activity that moves
+ * to foreground.
*/
public static final int MOVE_TO_FOREGROUND = 1;
/**
- * An event type denoting that a component moved to the background.
+ * An event type denoting that an {@link android.app.Activity} moved to the background.
+ * This event has a package name and class name associated with it and can be retrieved
+ * using {@link #getPackageName()} and {@link #getClassName()}.
+ * If a package has multiple activities, this event is reported for each activity that moves
+ * to background.
*/
public static final int MOVE_TO_BACKGROUND = 2;
@@ -166,10 +174,43 @@
public static final int KEYGUARD_HIDDEN = 18;
/**
+ * An event type denoting start of a foreground service.
+ * This event has a package name and class name associated with it and can be retrieved
+ * using {@link #getPackageName()} and {@link #getClassName()}.
+ * If a package has multiple foreground services, this event is reported for each service
+ * that is started.
+ */
+ public static final int FOREGROUND_SERVICE_START = 19;
+
+ /**
+ * An event type denoting stop of a foreground service.
+ * This event has a package name and class name associated with it and can be retrieved
+ * using {@link #getPackageName()} and {@link #getClassName()}.
+ * If a package has multiple foreground services, this event is reported for each service
+ * that is stopped.
+ */
+ public static final int FOREGROUND_SERVICE_STOP = 20;
+
+ /**
+ * An event type denoting that a foreground service is at started state at beginning of a
+ * time interval.
+ * This is effectively treated as a {@link #FOREGROUND_SERVICE_START}.
+ * {@hide}
+ */
+ public static final int CONTINUING_FOREGROUND_SERVICE = 21;
+
+ /**
+ * An event type denoting that a foreground service is at started state when the stats
+ * rolled-over at the end of a time interval.
+ * {@hide}
+ */
+ public static final int ROLLOVER_FOREGROUND_SERVICE = 22;
+
+ /**
* Keep in sync with the greatest event type value.
* @hide
*/
- public static final int MAX_EVENT_TYPE = 18;
+ public static final int MAX_EVENT_TYPE = 22;
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0659a23..73426e4 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -16,6 +16,15 @@
package android.app.usage;
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
+
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
@@ -48,19 +57,32 @@
public long mEndTimeStamp;
/**
- * Last time used by the user with an explicit action (notification, activity launch).
+ * Last time used by the user with an explicit action (notification, activity launch)
* {@hide}
*/
@UnsupportedAppUsage
public long mLastTimeUsed;
/**
+ * Total time this package's activity is in foreground.
* {@hide}
*/
@UnsupportedAppUsage
public long mTotalTimeInForeground;
/**
+ * Last time foreground service is started.
+ * {@hide}
+ */
+ public long mLastTimeForegroundServiceUsed;
+
+ /**
+ * Total time this package's foreground service is started.
+ * {@hide}
+ */
+ public long mTotalTimeForegroundServiceUsed;
+
+ /**
* {@hide}
*/
@UnsupportedAppUsage
@@ -71,16 +93,36 @@
*/
public int mAppLaunchCount;
- /**
+ /** Last activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
* {@hide}
+ * @deprecated use {@link #mLastForegroundActivityEventMap} instead.
*/
@UnsupportedAppUsage
+ @Deprecated
public int mLastEvent;
/**
+ * If an activity is in foreground, it has one entry in this map.
+ * When activity moves to background, it is removed from this map.
+ * Key is activity class name.
+ * Value is last time this activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
+ * {@hide}
+ */
+ public ArrayMap<String, Integer> mLastForegroundActivityEventMap = new ArrayMap<>();
+
+ /**
+ * If a foreground service is started, it has one entry in this map.
+ * When a foreground service is stopped, it is removed from this map.
+ * Key is foreground service class name.
+ * Value is last foreground service FOREGROUND_SERVICE_START ot FOREGROUND_SERVICE_STOP event.
+ * {@hide}
+ */
+ public ArrayMap<String, Integer> mLastForegroundServiceEventMap = new ArrayMap<>();
+
+ /**
* {@hide}
*/
- public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;
+ public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts = new ArrayMap<>();
/**
* {@hide}
@@ -93,10 +135,14 @@
mBeginTimeStamp = stats.mBeginTimeStamp;
mEndTimeStamp = stats.mEndTimeStamp;
mLastTimeUsed = stats.mLastTimeUsed;
+ mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
mTotalTimeInForeground = stats.mTotalTimeInForeground;
+ mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
mLaunchCount = stats.mLaunchCount;
mAppLaunchCount = stats.mAppLaunchCount;
mLastEvent = stats.mLastEvent;
+ mLastForegroundActivityEventMap = stats.mLastForegroundActivityEventMap;
+ mLastForegroundServiceEventMap = stats.mLastForegroundServiceEventMap;
mChooserCounts = stats.mChooserCounts;
}
@@ -136,7 +182,7 @@
}
/**
- * Get the last time this package was used, measured in milliseconds since the epoch.
+ * Get the last time this package's activity was used, measured in milliseconds since the epoch.
* <p/>
* See {@link System#currentTimeMillis()}.
*/
@@ -152,6 +198,23 @@
}
/**
+ * Get the last time this package's foreground service was used, measured in milliseconds since
+ * the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeForegroundServiceUsed() {
+ return mLastTimeForegroundServiceUsed;
+ }
+
+ /**
+ * Get the total time this package's foreground services are started, measured in milliseconds.
+ */
+ public long getTotalTimeForegroundServiceUsed() {
+ return mTotalTimeForegroundServiceUsed;
+ }
+
+ /**
* Returns the number of times the app was launched as an activity from outside of the app.
* Excludes intra-app activity transitions.
* @hide
@@ -161,6 +224,19 @@
return mAppLaunchCount;
}
+ private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
+ final int size = right.size();
+ for (int i = 0; i < size; i++) {
+ final String className = right.keyAt(i);
+ final Integer event = right.valueAt(i);
+ if (left.containsKey(className)) {
+ left.put(className, Math.max(left.get(className), event));
+ } else {
+ left.put(className, event);
+ }
+ }
+ }
+
/**
* Add the statistics from the right {@link UsageStats} to the left. The package name for
* both {@link UsageStats} objects must be the same.
@@ -179,12 +255,16 @@
if (right.mBeginTimeStamp > mBeginTimeStamp) {
// Even though incoming UsageStat begins after this one, its last time used fields
// may somehow be empty or chronologically preceding the older UsageStat.
- mLastEvent = Math.max(mLastEvent, right.mLastEvent);
+ mergeEventMap(mLastForegroundActivityEventMap, right.mLastForegroundActivityEventMap);
+ mergeEventMap(mLastForegroundServiceEventMap, right.mLastForegroundServiceEventMap);
mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
+ mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
+ right.mLastTimeForegroundServiceUsed);
}
mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
mTotalTimeInForeground += right.mTotalTimeInForeground;
+ mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
mLaunchCount += right.mLaunchCount;
mAppLaunchCount += right.mAppLaunchCount;
if (mChooserCounts == null) {
@@ -209,6 +289,161 @@
}
}
+ /**
+ * Tell if an event indicate activity is in foreground or not.
+ * @param event the activity event.
+ * @return true if activity is in foreground, false otherwise.
+ * @hide
+ */
+ private boolean isActivityInForeground(int event) {
+ return event == MOVE_TO_FOREGROUND
+ || event == CONTINUE_PREVIOUS_DAY;
+ }
+
+ /**
+ * Tell if an event indicate foreground sevice is started or not.
+ * @param event the foreground service event.
+ * @return true if foreground service is started, false if stopped.
+ * @hide
+ */
+ private boolean isForegroundServiceStarted(int event) {
+ return event == FOREGROUND_SERVICE_START
+ || event == CONTINUING_FOREGROUND_SERVICE;
+ }
+
+ /**
+ * If any activity in foreground or any foreground service is started, the app is considered in
+ * use.
+ * @return true if in use, false otherwise.
+ * @hide
+ */
+ private boolean isAppInUse() {
+ return !mLastForegroundActivityEventMap.isEmpty()
+ || !mLastForegroundServiceEventMap.isEmpty();
+ }
+
+ /**
+ * Update by an event of an activity.
+ * @param className className of the activity.
+ * @param timeStamp timeStamp of the event.
+ * @param eventType type of the event.
+ * @hide
+ */
+ private void updateForegroundActivity(String className, long timeStamp, int eventType) {
+ if (eventType != MOVE_TO_BACKGROUND
+ && eventType != MOVE_TO_FOREGROUND
+ && eventType != END_OF_DAY) {
+ return;
+ }
+
+ final Integer lastEvent = mLastForegroundActivityEventMap.get(className);
+ if (lastEvent != null) {
+ if (isActivityInForeground(lastEvent)) {
+ if (timeStamp > mLastTimeUsed) {
+ mTotalTimeInForeground += timeStamp - mLastTimeUsed;
+ mLastTimeUsed = timeStamp;
+ }
+ }
+ if (eventType == MOVE_TO_BACKGROUND) {
+ mLastForegroundActivityEventMap.remove(className);
+ } else {
+ mLastForegroundActivityEventMap.put(className, eventType);
+ }
+ } else if (eventType == MOVE_TO_FOREGROUND) {
+ if (!isAppInUse()) {
+ mLastTimeUsed = timeStamp;
+ }
+ mLastForegroundActivityEventMap.put(className, eventType);
+ }
+ }
+
+ /**
+ * Update by an event of an foreground service.
+ * @param className className of the foreground service.
+ * @param timeStamp timeStamp of the event.
+ * @param eventType type of the event.
+ * @hide
+ */
+ private void updateForegroundService(String className, long timeStamp, int eventType) {
+ if (eventType != FOREGROUND_SERVICE_STOP
+ && eventType != FOREGROUND_SERVICE_START
+ && eventType != ROLLOVER_FOREGROUND_SERVICE) {
+ return;
+ }
+ final Integer lastEvent = mLastForegroundServiceEventMap.get(className);
+ if (lastEvent != null) {
+ if (isForegroundServiceStarted(lastEvent)) {
+ if (timeStamp > mLastTimeForegroundServiceUsed) {
+ mTotalTimeForegroundServiceUsed +=
+ timeStamp - mLastTimeForegroundServiceUsed;
+ mLastTimeForegroundServiceUsed = timeStamp;
+ }
+ }
+ if (eventType == FOREGROUND_SERVICE_STOP) {
+ mLastForegroundServiceEventMap.remove(className);
+ } else {
+ mLastForegroundServiceEventMap.put(className, eventType);
+ }
+ } else if (eventType == FOREGROUND_SERVICE_START) {
+ if (!isAppInUse()) {
+ mLastTimeForegroundServiceUsed = timeStamp;
+ }
+ mLastForegroundServiceEventMap.put(className, eventType);
+ }
+ }
+
+ /**
+ * Update the UsageStats by a activity or foreground service event.
+ * @param className class name of a activity or foreground service, could be null to mark
+ * END_OF_DAY or rollover.
+ * @param timeStamp Epoch timestamp in milliseconds.
+ * @param eventType event type as in {@link UsageEvents.Event}
+ * @hide
+ */
+ public void update(String className, long timeStamp, int eventType) {
+ switch(eventType) {
+ case MOVE_TO_BACKGROUND:
+ case MOVE_TO_FOREGROUND:
+ updateForegroundActivity(className, timeStamp, eventType);
+ break;
+ case END_OF_DAY:
+ // END_OF_DAY means updating all activities.
+ final int size = mLastForegroundActivityEventMap.size();
+ for (int i = 0; i < size; i++) {
+ final String name = mLastForegroundActivityEventMap.keyAt(i);
+ updateForegroundActivity(name, timeStamp, eventType);
+ }
+ break;
+ case CONTINUE_PREVIOUS_DAY:
+ mLastTimeUsed = timeStamp;
+ mLastForegroundActivityEventMap.put(className, eventType);
+ break;
+ case FOREGROUND_SERVICE_STOP:
+ case FOREGROUND_SERVICE_START:
+ updateForegroundService(className, timeStamp, eventType);
+ break;
+ case ROLLOVER_FOREGROUND_SERVICE:
+ // ROLLOVER_FOREGROUND_SERVICE means updating all foreground services.
+ final int size2 = mLastForegroundServiceEventMap.size();
+ for (int i = 0; i < size2; i++) {
+ final String name = mLastForegroundServiceEventMap.keyAt(i);
+ updateForegroundService(name, timeStamp, eventType);
+ }
+ break;
+ case CONTINUING_FOREGROUND_SERVICE:
+ mLastTimeForegroundServiceUsed = timeStamp;
+ mLastForegroundServiceEventMap.put(className, eventType);
+ break;
+ default:
+ break;
+ }
+ mEndTimeStamp = timeStamp;
+
+ if (eventType == MOVE_TO_FOREGROUND) {
+ mLaunchCount += 1;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -220,7 +455,9 @@
dest.writeLong(mBeginTimeStamp);
dest.writeLong(mEndTimeStamp);
dest.writeLong(mLastTimeUsed);
+ dest.writeLong(mLastTimeForegroundServiceUsed);
dest.writeLong(mTotalTimeInForeground);
+ dest.writeLong(mTotalTimeForegroundServiceUsed);
dest.writeInt(mLaunchCount);
dest.writeInt(mAppLaunchCount);
dest.writeInt(mLastEvent);
@@ -239,6 +476,22 @@
}
}
dest.writeBundle(allCounts);
+
+ final Bundle foregroundActivityEventBundle = new Bundle();
+ final int foregroundEventSize = mLastForegroundActivityEventMap.size();
+ for (int i = 0; i < foregroundEventSize; i++) {
+ foregroundActivityEventBundle.putInt(mLastForegroundActivityEventMap.keyAt(i),
+ mLastForegroundActivityEventMap.valueAt(i));
+ }
+ dest.writeBundle(foregroundActivityEventBundle);
+
+ final Bundle foregroundServiceEventBundle = new Bundle();
+ final int foregroundServiceEventSize = mLastForegroundServiceEventMap.size();
+ for (int i = 0; i < foregroundServiceEventSize; i++) {
+ foregroundServiceEventBundle.putInt(mLastForegroundServiceEventMap.keyAt(i),
+ mLastForegroundServiceEventMap.valueAt(i));
+ }
+ dest.writeBundle(foregroundServiceEventBundle);
}
public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -249,7 +502,9 @@
stats.mBeginTimeStamp = in.readLong();
stats.mEndTimeStamp = in.readLong();
stats.mLastTimeUsed = in.readLong();
+ stats.mLastTimeForegroundServiceUsed = in.readLong();
stats.mTotalTimeInForeground = in.readLong();
+ stats.mTotalTimeForegroundServiceUsed = in.readLong();
stats.mLaunchCount = in.readInt();
stats.mAppLaunchCount = in.readInt();
stats.mLastEvent = in.readInt();
@@ -272,9 +527,20 @@
}
}
}
+ readBundleToEventMap(stats.mLastForegroundActivityEventMap, in.readBundle());
+ readBundleToEventMap(stats.mLastForegroundServiceEventMap, in.readBundle());
return stats;
}
+ private void readBundleToEventMap(ArrayMap<String, Integer> eventMap, Bundle bundle) {
+ if (bundle != null) {
+ for (String className : bundle.keySet()) {
+ final int event = bundle.getInt(className);
+ eventMap.put(className, event);
+ }
+ }
+ }
+
@Override
public UsageStats[] newArray(int size) {
return new UsageStats[size];
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 6d7400e..5514851 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -192,7 +192,10 @@
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
/** @hide */
public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
-
+ /** @hide */
+ public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000E;
+ /** @hide */
+ public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP = 0x000F;
/** @hide */
public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2aa32c4..9f8ae0b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4367,6 +4367,13 @@
public static final String APP_BINDING_SERVICE = "app_binding";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.telephony.rcs.RcsManager}.
+ * @hide
+ */
+ public static final String TELEPHONY_RCS_SERVICE = "ircs";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6b5c659..48240db 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -27,7 +27,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1171,11 +1170,11 @@
* system apps.
* @hide
*/
- public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+ public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0;
/**
* No API enforcement, but enable the detection logic and warnings. Observed behaviour is the
- * same as {@link #HIDDEN_API_ENFORCEMENT_NONE} but you may see warnings in the log when APIs
- * are accessed.
+ * same as {@link #HIDDEN_API_ENFORCEMENT_DISABLED} but you may see warnings in the log when
+ * APIs are accessed.
* @hide
* */
public static final int HIDDEN_API_ENFORCEMENT_JUST_WARN = 1;
@@ -1183,14 +1182,10 @@
* Dark grey list enforcement. Enforces the dark grey and black lists
* @hide
*/
- public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
- /**
- * Blacklist enforcement only.
- * @hide
- */
- public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+ public static final int HIDDEN_API_ENFORCEMENT_ENABLED = 2;
- private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+ private static final int HIDDEN_API_ENFORCEMENT_MIN = HIDDEN_API_ENFORCEMENT_DEFAULT;
+ private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_ENABLED;
/**
* Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
@@ -1199,17 +1194,16 @@
*/
@IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
HIDDEN_API_ENFORCEMENT_DEFAULT,
- HIDDEN_API_ENFORCEMENT_NONE,
+ HIDDEN_API_ENFORCEMENT_DISABLED,
HIDDEN_API_ENFORCEMENT_JUST_WARN,
- HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
- HIDDEN_API_ENFORCEMENT_BLACK,
+ HIDDEN_API_ENFORCEMENT_ENABLED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface HiddenApiEnforcementPolicy {}
/** @hide */
public static boolean isValidHiddenApiEnforcementPolicy(int policy) {
- return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+ return policy >= HIDDEN_API_ENFORCEMENT_MIN && policy <= HIDDEN_API_ENFORCEMENT_MAX;
}
private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -1749,16 +1743,12 @@
*/
public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
if (isAllowedToUseHiddenApis()) {
- return HIDDEN_API_ENFORCEMENT_NONE;
+ return HIDDEN_API_ENFORCEMENT_DISABLED;
}
if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
return mHiddenApiPolicy;
}
- if (targetSdkVersion < Build.VERSION_CODES.P) {
- return HIDDEN_API_ENFORCEMENT_BLACK;
- } else {
- return HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
- }
+ return HIDDEN_API_ENFORCEMENT_ENABLED;
}
/**
@@ -1777,23 +1767,15 @@
* This will have no effect if this app is not subject to hidden API enforcement, i.e. if it
* is on the package whitelist.
*
- * @param policyPreP configured policy for pre-P apps, or {@link
- * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
- * @param policyP configured policy for apps targeting P or later, or {@link
- * #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+ * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT}
+ * if nothing configured.
* @hide
*/
- public void maybeUpdateHiddenApiEnforcementPolicy(
- @HiddenApiEnforcementPolicy int policyPreP, @HiddenApiEnforcementPolicy int policyP) {
+ public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
if (isPackageWhitelistedForHiddenApis()) {
return;
}
- if (targetSdkVersion < Build.VERSION_CODES.P) {
- setHiddenApiEnforcementPolicy(policyPreP);
- } else if (targetSdkVersion >= Build.VERSION_CODES.P) {
- setHiddenApiEnforcementPolicy(policyP);
- }
-
+ setHiddenApiEnforcementPolicy(policy);
}
/**
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 444ca87..7148b12 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -28,8 +28,8 @@
import android.hardware.camera2.utils.TypeReference;
import android.util.Rational;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -2668,7 +2668,8 @@
/**
* <p>The arrangement of color filters on sensor;
* represents the colors in the top-left 2x2 section of
- * the sensor, in reading order.</p>
+ * the sensor, in reading order, for a Bayer camera, or the
+ * light spectrum it captures for MONOCHROME camera.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB RGGB}</li>
@@ -2676,6 +2677,8 @@
* <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG GBRG}</li>
* <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR BGGR}</li>
* <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB RGB}</li>
+ * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO MONO}</li>
+ * <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR NIR}</li>
* </ul></p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Full capability</b> -
@@ -2688,6 +2691,8 @@
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB
+ * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
+ * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR
*/
@PublicKey
public static final Key<Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT =
@@ -2919,6 +2924,8 @@
* <p>Some devices may choose to provide a second set of calibration
* information for improved quality, including
* {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT DAYLIGHT}</li>
@@ -2981,6 +2988,8 @@
* <p>If this key is present, then {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM2 android.sensor.colorTransform2},
* {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2 android.sensor.calibrationTransform2}, and
* {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX2 android.sensor.forwardMatrix2} will also be present.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Range of valid values:</b><br>
* Any value listed in {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3006,6 +3015,8 @@
* colorspace) into this camera device's native sensor color
* space under the first reference illuminant
* ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3029,6 +3040,8 @@
* ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2}).</p>
* <p>This matrix will only be present if the second reference
* illuminant is present.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3053,6 +3066,8 @@
* and the CIE XYZ colorspace when calculating this transform will
* match the standard white point for the first reference illuminant
* (i.e. no chromatic adaptation will be applied by this transform).</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3079,6 +3094,8 @@
* (i.e. no chromatic adaptation will be applied by this transform).</p>
* <p>This matrix will only be present if the second reference
* illuminant is present.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3101,6 +3118,8 @@
* this matrix is chosen so that the standard white point for this reference
* illuminant in the reference sensor colorspace is mapped to D50 in the
* CIE XYZ colorspace.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3125,6 +3144,8 @@
* CIE XYZ colorspace.</p>
* <p>This matrix will only be present if the second reference
* illuminant is present.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
* <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
*
@@ -3153,6 +3174,7 @@
* level values. For raw capture in particular, it is recommended to use
* pixels from {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} to calculate black
* level values for each frame.</p>
+ * <p>For a MONOCHROME camera device, all of the 2x2 channels must have the same values.</p>
* <p><b>Range of valid values:</b><br>
* >= 0 for each.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ac00f14..dc6cffc 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -357,7 +357,7 @@
* </p>
*
* <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
- * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME})
+ * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
* supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
* streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level
* and capabilities.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ffc2264..402472a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -880,11 +880,15 @@
/**
* <p>The camera device is a monochrome camera that doesn't contain a color filter array,
- * and the pixel values on U and V planes are all 128.</p>
+ * and for YUV_420_888 stream, the pixel values on U and V planes are all 128.</p>
* <p>A MONOCHROME camera must support the guaranteed stream combinations required for
* its device level and capabilities. Additionally, if the monochrome camera device
* supports Y8 format, all mandatory stream combination requirements related to {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888} apply
- * to {@link android.graphics.ImageFormat#Y8 Y8} as well.</p>
+ * to {@link android.graphics.ImageFormat#Y8 Y8} as well. There are no
+ * mandatory stream combination requirements with regard to
+ * {@link android.graphics.ImageFormat#Y8 Y8} for Bayer camera devices.</p>
+ * <p>Starting from Android Q, the SENSOR_INFO_COLOR_FILTER_ARRANGEMENT of a MONOCHROME
+ * camera will be either MONO or NIR.</p>
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12;
@@ -937,6 +941,23 @@
*/
public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
+ /**
+ * <p>Sensor doesn't have any Bayer color filter.
+ * Such sensor captures visible light in monochrome. The exact weighting and
+ * wavelengths captured is not specified, but generally only includes the visible
+ * frequencies. This value implies a MONOCHROME camera.</p>
+ * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ */
+ public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5;
+
+ /**
+ * <p>Sensor has a near infrared filter capturing light with wavelength between
+ * roughly 750nm and 1400nm, and the same filter covers the whole sensor array. This
+ * value implies a MONOCHROME camera.</p>
+ * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ */
+ public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6;
+
//
// Enumeration values for CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 2744e91..8ebaf2f 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -24,8 +24,8 @@
import android.hardware.camera2.impl.SyntheticKey;
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.utils.HashCodeHelpers;
-import android.hardware.camera2.utils.TypeReference;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.camera2.utils.TypeReference;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
@@ -2947,8 +2947,8 @@
* of points can be less than max (that is, the request doesn't have to
* always provide a curve with number of points equivalent to
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
- * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
- * are ignored.</p>
+ * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+ * control points.</p>
* <p>A few examples, and their corresponding graphical mappings; these
* only specify the red channel and the precision is limited to 4
* digits, for conciseness.</p>
@@ -3011,8 +3011,8 @@
* of points can be less than max (that is, the request doesn't have to
* always provide a curve with number of points equivalent to
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
- * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
- * are ignored.</p>
+ * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+ * control points.</p>
* <p>A few examples, and their corresponding graphical mappings; these
* only specify the red channel and the precision is limited to 4
* digits, for conciseness.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 2b67f3e..3d70c51 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3417,6 +3417,8 @@
* used to interpolate between the provided color transforms when
* processing raw sensor data.</p>
* <p>The order of the values is R, G, B; where R is in the lowest index.</p>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*/
@PublicKey
@@ -3442,6 +3444,8 @@
* that channel.</p>
* <p>A more detailed description of the noise model can be found in the
* Adobe DNG specification for the NoiseProfile tag.</p>
+ * <p>For a MONOCHROME camera, there is only one color channel. So the noise model coefficients
+ * will only contain one S and one O.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3482,6 +3486,8 @@
* <li>R > 1.20 will require strong software correction to produce
* a usuable image (>20% divergence).</li>
* </ul>
+ * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+ * the camera device has RAW capability.</p>
* <p><b>Range of valid values:</b><br></p>
* <p>>= 0</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3592,6 +3598,7 @@
* layout key (see {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT android.sensor.info.colorFilterArrangement}), i.e. the
* nth value given corresponds to the black level offset for the nth
* color channel listed in the CFA.</p>
+ * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values.</p>
* <p>This key will be available if {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} is available or the
* camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
* <p><b>Range of valid values:</b><br>
@@ -3852,6 +3859,17 @@
* <p>As a visualization only, inverting the full-color map to recover an
* image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
* <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+ * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+ * shading map for such a camera is defined as:</p>
+ * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+ * android.statistics.lensShadingMap =
+ * [ 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.1, 1.1, 1.1, 1.1, 1.3, 1.3, 1.3, 1.3,
+ * 1.2, 1.2, 1.2, 1.2, 1.1, 1.1, 1.1, 1.1,
+ * 1.0, 1.0, 1.0, 1.0, 1.2, 1.2, 1.2, 1.2,
+ * 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.3 ]
+ * </code></pre>
* <p><b>Range of valid values:</b><br>
* Each gain factor is >= 1</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3894,13 +3912,13 @@
* (x,y) ϵ (0 ... N-1, 0 ... M-1) is the value of the shading map at
* pixel ( ((W-1)/(N-1)) * x, ((H-1)/(M-1)) * y) for the four color channels.
* The map is assumed to be bilinearly interpolated between the sample points.</p>
- * <p>The channel order is [R, Geven, Godd, B], where Geven is the green
- * channel for the even rows of a Bayer pattern, and Godd is the odd rows.
+ * <p>For a Bayer camera, the channel order is [R, Geven, Godd, B], where Geven is
+ * the green channel for the even rows of a Bayer pattern, and Godd is the odd rows.
* The shading map is stored in a fully interleaved format, and its size
* is provided in the camera static metadata by android.lens.info.shadingMapSize.</p>
* <p>The shading map will generally have on the order of 30-40 rows and columns,
* and will be smaller than 64x64.</p>
- * <p>As an example, given a very small map defined as:</p>
+ * <p>As an example, given a very small map for a Bayer camera defined as:</p>
* <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
* android.statistics.lensShadingMap =
* [ 1.3, 1.2, 1.15, 1.2, 1.2, 1.2, 1.15, 1.2,
@@ -3920,6 +3938,17 @@
* image of a gray wall (using bicubic interpolation for visual quality)
* as captured by the sensor gives:</p>
* <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+ * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+ * shading map for such a camera is defined as:</p>
+ * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+ * android.statistics.lensShadingMap =
+ * [ 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.1, 1.1, 1.1, 1.1, 1.3, 1.3, 1.3, 1.3,
+ * 1.2, 1.2, 1.2, 1.2, 1.1, 1.1, 1.1, 1.1,
+ * 1.0, 1.0, 1.0, 1.0, 1.2, 1.2, 1.2, 1.2,
+ * 1.3, 1.3, 1.3, 1.3, 1.2, 1.2, 1.2, 1.2,
+ * 1.2, 1.2, 1.2, 1.2, 1.3, 1.3, 1.3, 1.3 ]
+ * </code></pre>
* <p>Note that the RAW image data might be subject to lens shading
* correction not reported on this map. Query
* {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} to see if RAW image data has subject
@@ -4250,8 +4279,8 @@
* of points can be less than max (that is, the request doesn't have to
* always provide a curve with number of points equivalent to
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
- * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
- * are ignored.</p>
+ * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+ * control points.</p>
* <p>A few examples, and their corresponding graphical mappings; these
* only specify the red channel and the precision is limited to 4
* digits, for conciseness.</p>
@@ -4314,8 +4343,8 @@
* of points can be less than max (that is, the request doesn't have to
* always provide a curve with number of points equivalent to
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
- * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
- * are ignored.</p>
+ * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+ * control points.</p>
* <p>A few examples, and their corresponding graphical mappings; these
* only specify the red channel and the precision is limited to 4
* digits, for conciseness.</p>
diff --git a/core/java/android/hardware/camera2/params/BlackLevelPattern.java b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
index 6d6c094..283977f 100644
--- a/core/java/android/hardware/camera2/params/BlackLevelPattern.java
+++ b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
@@ -16,13 +16,17 @@
package android.hardware.camera2.params;
-import java.util.Arrays;
-
import static com.android.internal.util.Preconditions.checkNotNull;
+import java.util.Arrays;
+
/**
* Immutable class to store a 4-element vector of integers corresponding to a 2x2 pattern
* of color channel offsets used for the black level offsets of each color channel.
+ *
+ * For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 4 elements of the pattern will have the same value.
*/
public final class BlackLevelPattern {
@@ -133,6 +137,12 @@
* {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}).
* </p>
*
+ * <p>A {@link
+ * android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} camera only has one channel. As a result, the returned string will contain 4
+ * identical values.
+ * </p>
+ *
* @return string representation of {@link BlackLevelPattern}
*
* @see android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java
index 71e68a5..90e6355 100644
--- a/core/java/android/hardware/camera2/params/TonemapCurve.java
+++ b/core/java/android/hardware/camera2/params/TonemapCurve.java
@@ -34,6 +34,10 @@
* use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
* set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
*
+ * <p>For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 3 channels will contain the same set of control points.
+ *
* <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
* {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
*
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 1bae3f7..0c1aae8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -199,6 +199,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public static File getProductDirectory() {
return DIR_PRODUCT_ROOT;
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 7ceeb52..ca5b233 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -48,6 +48,8 @@
boolean isPowerSaveMode();
PowerSaveState getPowerSaveState(int serviceType);
boolean setPowerSaveMode(boolean mode);
+ boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled, int disableThreshold);
+ int getPowerSaveMode();
boolean isDeviceIdleMode();
boolean isLightDeviceIdleMode();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 27c281d..a307cd8 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,6 +16,7 @@
package android.os;
+import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -1185,6 +1186,105 @@
}
/**
+ * Updates the current state of dynamic power savings and disable threshold. This is
+ * a signal to the system which an app can update to serve as an indicator that
+ * the user will be in a battery critical situation before being able to plug in.
+ * Only apps with the {@link android.Manifest.permission#POWER_SAVER} permission may do this.
+ * This is a device global state, not a per user setting.
+ *
+ * <p>When enabled, the system may enact various measures for reducing power consumption in
+ * order to help ensure that the user will make it to their next charging point. The most
+ * visible of these will be the automatic enabling of battery saver if the user has set
+ * their battery saver mode to "automatic". Note
+ * that this is NOT simply an on/off switch for features, but rather a hint for the
+ * system to consider enacting these power saving features, some of which have additional
+ * logic around when to activate based on this signal.
+ *
+ * <p>The provided threshold is the percentage the system should consider itself safe at given
+ * the current state of the device. The value is an integer representing a battery level.
+ *
+ * <p>The threshold is meant to set an explicit stopping point for dynamic power savings
+ * functionality so that the dynamic power savings itself remains a signal rather than becoming
+ * an on/off switch for a subset of features.
+ * @hide
+ *
+ * @param dynamicPowerSavingsEnabled A signal indicating to the system if it believes the
+ * dynamic power savings behaviors should be activated.
+ * @param disableThreshold When the suggesting app believes it would be safe to disable dynamic
+ * power savings behaviors.
+ * @return True if the update was allowed and succeeded.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(permission.POWER_SAVER)
+ public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+ int disableThreshold) {
+ try {
+ return mService.setDynamicPowerSavings(dynamicPowerSavingsEnabled, disableThreshold);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Indicates automatic battery saver toggling by the system will be based on percentage.
+ *
+ * @see PowerManager#getPowerSaveMode()
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final int POWER_SAVER_MODE_PERCENTAGE = 0;
+
+ /**
+ * Indicates automatic battery saver toggling by the system will be based on the state
+ * of the dynamic power savings signal.
+ *
+ * @see PowerManager#setDynamicPowerSavings(boolean, int)
+ * @see PowerManager#getPowerSaveMode()
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final int POWER_SAVER_MODE_DYNAMIC = 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ POWER_SAVER_MODE_PERCENTAGE,
+ POWER_SAVER_MODE_DYNAMIC
+
+ })
+ public @interface AutoPowerSaverMode{}
+
+
+ /**
+ * Returns the current battery saver control mode. Values it may return are defined in
+ * AutoPowerSaverMode. Note that this is a global device state, not a per user setting.
+ *
+ * @return The current value power saver mode for the system.
+ *
+ * @see AutoPowerSaverMode
+ * @see PowerManager#getPowerSaveMode()
+ * @hide
+ */
+ @AutoPowerSaverMode
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.POWER_SAVER)
+ public int getPowerSaveMode() {
+ try {
+ return mService.getPowerSaveMode();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Get data about the battery saver mode for a specific service
* @param serviceType unique key for the service, one of {@link ServiceType}
* @return Battery saver state data.
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8a36a78..d679fc7 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -801,7 +801,7 @@
try {
for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
if (vol.path != null && FileUtils.contains(vol.path, pathString)
- && vol.type != VolumeInfo.TYPE_PUBLIC) {
+ && vol.type != VolumeInfo.TYPE_PUBLIC && vol.type != VolumeInfo.TYPE_STUB) {
// TODO: verify that emulated adopted devices have UUID of
// underlying volume
try {
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e55afb6..8c3aa17 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -84,6 +84,7 @@
public static final int TYPE_EMULATED = IVold.VOLUME_TYPE_EMULATED;
public static final int TYPE_ASEC = IVold.VOLUME_TYPE_ASEC;
public static final int TYPE_OBB = IVold.VOLUME_TYPE_OBB;
+ public static final int TYPE_STUB = IVold.VOLUME_TYPE_STUB;
public static final int STATE_UNMOUNTED = IVold.VOLUME_STATE_UNMOUNTED;
public static final int STATE_CHECKING = IVold.VOLUME_STATE_CHECKING;
@@ -295,7 +296,7 @@
}
public boolean isVisibleForUser(int userId) {
- if (type == TYPE_PUBLIC && mountUserId == userId) {
+ if ((type == TYPE_PUBLIC || type == TYPE_STUB) && mountUserId == userId) {
return isVisible();
} else if (type == TYPE_EMULATED) {
return isVisible();
@@ -327,7 +328,7 @@
public File getPathForUser(int userId) {
if (path == null) {
return null;
- } else if (type == TYPE_PUBLIC) {
+ } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
return new File(path);
} else if (type == TYPE_EMULATED) {
return new File(path, Integer.toString(userId));
@@ -344,7 +345,7 @@
public File getInternalPathForUser(int userId) {
if (path == null) {
return null;
- } else if (type == TYPE_PUBLIC) {
+ } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
// TODO: plumb through cleaner path from vold
return new File(path.replace("/storage/", "/mnt/media_rw/"));
} else {
@@ -390,7 +391,7 @@
removable = true;
}
- } else if (type == TYPE_PUBLIC) {
+ } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
emulated = false;
removable = true;
@@ -447,7 +448,8 @@
public @Nullable Intent buildBrowseIntentForUser(int userId) {
final Uri uri;
- if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == userId) {
+ if ((type == VolumeInfo.TYPE_PUBLIC || type == VolumeInfo.TYPE_STUB)
+ && mountUserId == userId) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
} else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0aa3a7b..0402222 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11811,14 +11811,54 @@
/**
* Battery level [1-100] at which low power mode automatically turns on.
- * If 0, it will not automatically turn on.
+ * Pre-Q If 0, it will not automatically turn on. Q and newer it will only automatically
+ * turn on if the {@link #AUTOMATIC_POWER_SAVER_MODE} setting is also set to
+ * {@link android.os.PowerManager.AutoPowerSaverMode#POWER_SAVER_MODE_PERCENTAGE}.
+ *
+ * @see #AUTOMATIC_POWER_SAVER_MODE
+ * @see android.os.PowerManager#getPowerSaveMode()
* @hide
*/
public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
+
private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+ /**
+ * Whether battery saver is currently set to trigger based on percentage, dynamic power
+ * savings trigger, or none. See {@link android.os.PowerManager.AutoPowerSaverMode} for
+ * accepted values.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+
+ private static final Validator AUTOMATIC_POWER_SAVER_MODE_VALIDATOR =
+ new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+
+ /**
+ * The setting that backs the disable threshold for the setPowerSavingsWarning api in
+ * PowerManager
+ *
+ * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+ * @hide
+ */
+ @TestApi
+ public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD =
+ "dynamic_power_savings_disable_threshold";
+ private static final Validator DYNAMIC_POWER_SAVINGS_VALIDATOR =
+ new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+
+ /**
+ * The setting which backs the setDynamicPowerSavings api in PowerManager.
+ *
+ * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+ * @hide
+ */
+ @TestApi
+ public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
/**
* The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
@@ -12636,27 +12676,14 @@
"hidden_api_access_log_sampling_rate";
/**
- * Hidden API enforcement policy for apps targeting SDK versions prior to the latest
- * version.
+ * Hidden API enforcement policy for apps.
*
* Values correspond to @{@link
* android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
*
* @hide
*/
- public static final String HIDDEN_API_POLICY_PRE_P_APPS =
- "hidden_api_policy_pre_p_apps";
-
- /**
- * Hidden API enforcement policy for apps targeting the current SDK version.
- *
- * Values correspond to @{@link
- * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
- *
- * @hide
- */
- public static final String HIDDEN_API_POLICY_P_APPS =
- "hidden_api_policy_p_apps";
+ public static final String HIDDEN_API_POLICY = "hidden_api_policy";
/**
* Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
@@ -12755,6 +12782,9 @@
VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+ VALIDATORS.put(AUTOMATIC_POWER_SAVER_MODE, AUTOMATIC_POWER_SAVER_MODE_VALIDATOR);
+ VALIDATORS.put(DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+ DYNAMIC_POWER_SAVINGS_VALIDATOR);
VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 907f385..0739516 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1978,6 +1978,7 @@
}
/** @hide */
+ @TestApi
@Override
public final void setDisplayId(int displayId) {
mDisplayId = displayId;
@@ -2042,6 +2043,16 @@
}
/**
+ * Modifies the flags of the event.
+ *
+ * @param newFlags New flags for the event, replacing the entire value.
+ * @hide
+ */
+ public final void setFlags(int newFlags) {
+ mFlags = newFlags;
+ }
+
+ /**
* Returns the flags for this key event.
*
* @see #FLAG_WOKE_HERE
@@ -2542,6 +2553,20 @@
}
/**
+ * Modifies the down time and the event time of the event.
+ *
+ * @param downTime The new down time (in {@link android.os.SystemClock#uptimeMillis}) of the
+ * event.
+ * @param eventTime The new event time (in {@link android.os.SystemClock#uptimeMillis}) of the
+ * event.
+ * @hide
+ */
+ public final void setTime(long downTime, long eventTime) {
+ mDownTime = downTime;
+ mEventTime = eventTime;
+ }
+
+ /**
* Retrieve the time of the most recent key down event,
* in the {@link android.os.SystemClock#uptimeMillis} time base. If this
* is a down event, this will be the same as {@link #getEventTime()}.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index bac0154..bf1a005 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -172,6 +172,12 @@
*/
public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
+ /**
+ * Forces smart-dark to be always on.
+ * @hide
+ */
+ public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
+
public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
@@ -675,10 +681,8 @@
mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
- final int ambientShadowAlpha =
- (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
- final int spotShadowAlpha =
- (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+ final float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+ final float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
a.recycle();
setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7ba027f..ec16828 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -112,6 +112,7 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
import android.widget.Checkable;
import android.widget.FrameLayout;
import android.widget.ScrollBarDrawable;
@@ -799,6 +800,11 @@
private static final String AUTOFILL_LOG_TAG = "View.Autofill";
/**
+ * The logging tag used by this class when logging content capture-related messages.
+ */
+ private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
+
+ /**
* When set to true, apps will draw debugging information about their layouts.
*
* @hide
@@ -1337,6 +1343,59 @@
*/
public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
+ /** @hide */
+ @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
+ IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
+ IMPORTANT_FOR_CONTENT_CAPTURE_YES,
+ IMPORTANT_FOR_CONTENT_CAPTURE_NO,
+ IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+ IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentCaptureImportance {}
+
+ /**
+ * Automatically determine whether a view is important for content capture.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ */
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
+
+ /**
+ * The view is important for content capture, and its children (if any) will be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ */
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
+
+ /**
+ * The view is not important for content capture, but its children (if any) will be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ */
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
+
+ /**
+ * The view is important for content capture, but its children (if any) will not be traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ */
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+ /**
+ * The view is not important for content capture, and its children (if any) will not be
+ * traversed.
+ *
+ * @see #isImportantForContentCapture()
+ * @see #setImportantForContentCapture(int)
+ */
+ public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+
/**
* This view is enabled. Interpretation varies by subclass.
* Use with ENABLED_MASK when calling setFlags.
@@ -2243,7 +2302,44 @@
@UnsupportedAppUsage
protected Object mTag = null;
- // for mPrivateFlags:
+ /*
+ * Masks for mPrivateFlags, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1 PFLAG_WANTS_FOCUS
+ * 1 PFLAG_FOCUSED
+ * 1 PFLAG_SELECTED
+ * 1 PFLAG_IS_ROOT_NAMESPACE
+ * 1 PFLAG_HAS_BOUNDS
+ * 1 PFLAG_DRAWN
+ * 1 PFLAG_DRAW_ANIMATION
+ * 1 PFLAG_SKIP_DRAW
+ * 1 PFLAG_REQUEST_TRANSPARENT_REGIONS
+ * 1 PFLAG_DRAWABLE_STATE_DIRTY
+ * 1 PFLAG_MEASURED_DIMENSION_SET
+ * 1 PFLAG_FORCE_LAYOUT
+ * 1 PFLAG_LAYOUT_REQUIRED
+ * 1 PFLAG_PRESSED
+ * 1 PFLAG_DRAWING_CACHE_VALID
+ * 1 PFLAG_ANIMATION_STARTED
+ * 1 PFLAG_SAVE_STATE_CALLED
+ * 1 PFLAG_ALPHA_SET
+ * 1 PFLAG_SCROLL_CONTAINER
+ * 1 PFLAG_SCROLL_CONTAINER_ADDED
+ * 1 PFLAG_DIRTY
+ * 1 PFLAG_DIRTY_MASK
+ * 1 PFLAG_OPAQUE_BACKGROUND
+ * 1 PFLAG_OPAQUE_SCROLLBARS
+ * 11 PFLAG_OPAQUE_MASK
+ * 1 PFLAG_PREPRESSED
+ * 1 PFLAG_CANCEL_NEXT_UP_EVENT
+ * 1 PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
+ * 1 PFLAG_HOVERED
+ * 1 PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
+ * 1 PFLAG_ACTIVATED
+ * 1 PFLAG_INVALIDATED
+ * |-------|-------|-------|-------|
+ */
/** {@hide} */
static final int PFLAG_WANTS_FOCUS = 0x00000001;
/** {@hide} */
@@ -2393,7 +2489,9 @@
*/
static final int PFLAG_INVALIDATED = 0x80000000;
- /**
+ /* End of masks for mPrivateFlags */
+
+ /*
* Masks for mPrivateFlags2, as generated by dumpFlags():
*
* |-------|-------|-------|-------|
@@ -2934,7 +3032,7 @@
/* End of masks for mPrivateFlags2 */
- /**
+ /*
* Masks for mPrivateFlags3, as generated by dumpFlags():
*
* |-------|-------|-------|-------|
@@ -3270,6 +3368,57 @@
/* End of masks for mPrivateFlags3 */
+ /*
+ * Masks for mPrivateFlags4, as generated by dumpFlags():
+ *
+ * |-------|-------|-------|-------|
+ * 1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT
+ * 1 PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED
+ * 1 PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE
+ * |-------|-------|-------|-------|
+ */
+
+ /**
+ * Mask for obtaining the bits which specify how to determine
+ * whether a view is important for autofill.
+ *
+ * <p>NOTE: the important for content capture values were the first flags added and are set in
+ * the rightmost position, so we don't need to shift them
+ */
+ private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
+ IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
+ | IMPORTANT_FOR_CONTENT_CAPTURE_NO
+ | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
+
+ /*
+ * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
+ * should be called.
+ *
+ * The idea is to call notifyNodeAdded() after the view is layout and visible, then call
+ * notifyNodeRemoved() when it's gone (without known when it was removed from the parent).
+ *
+ * TODO(b/111276913): the current algortighm could probably be optimized and some of them
+ * removed
+ */
+ private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT = 0x10;
+ private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED = 0x20;
+ private static final int PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE = 0x40;
+
+ private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED = 1;
+ private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED = 0;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "CONTENT_CAPTURE_NOTIFICATION_TYPE_" }, value = {
+ CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED,
+ CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentCaptureNotificationType {}
+
+ /* End of masks for mPrivateFlags4 */
+
/**
* Always allow a user to over-scroll this view, provided it is a
* view that can scroll.
@@ -3861,6 +4010,8 @@
@UnsupportedAppUsage
int mPrivateFlags3;
+ private int mPrivateFlags4;
+
/**
* This view's request for the visibility of the status bar.
* @hide
@@ -5803,6 +5954,7 @@
mAttributes = trimmed;
}
+ @Override
public String toString() {
StringBuilder out = new StringBuilder(128);
out.append(getClass().getName());
@@ -5875,6 +6027,9 @@
}
}
}
+ if (mAutofillId != null) {
+ out.append(" aid="); out.append(mAutofillId);
+ }
out.append("}");
return out.toString();
}
@@ -7888,7 +8043,8 @@
* fills in all data that can be inferred from the view itself.
*/
public void onProvideStructure(ViewStructure structure) {
- onProvideStructureForAssistOrAutofill(structure, false, 0);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
+ /* forViewCapture= */ false, /* flags= */ 0);
}
/**
@@ -7961,11 +8117,46 @@
* @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
*/
public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
- onProvideStructureForAssistOrAutofill(structure, true, flags);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ true,
+ /* forViewCapture= */ false, flags);
}
- private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
- boolean forAutofill, @AutofillFlags int flags) {
+ /**
+ * Populates a {@link ViewStructure} for Content Capture.
+ *
+ * <p>This method is called after a view is that is eligible for Content Capture
+ * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
+ * the user, and the activity rendering the view is enabled for Content Capture) is laid out and
+ * is visible.
+ *
+ * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+ * <ul>
+ * <li>{@link ViewStructure#setChildCount(int)}
+ * <li>{@link ViewStructure#addChildCount(int)}
+ * <li>{@link ViewStructure#getChildCount()}
+ * <li>{@link ViewStructure#newChild(int)}
+ * <li>{@link ViewStructure#asyncNewChild(int)}
+ * <li>{@link ViewStructure#asyncCommit()}
+ * <li>{@link ViewStructure#setWebDomain(String)}
+ * <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+ * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+ * <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+ * </ul>
+ *
+ * @return whether the IntelligenceService should be notified that the view was added (through
+ * the {@link IntelligenceManager#notifyViewAppeared(ViewStructure)} method) to the view
+ * hierarchy. Most views should return {@code true} here, but views that contains virtual
+ * hierarchy might opt to return {@code false} and notify the manager independently, as the
+ * virtual views are rendered.
+ */
+ public boolean onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
+ /* forViewCapture= */ true, flags);
+ return true;
+ }
+
+ private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure,
+ boolean forAutofill, boolean forViewCapture, @AutofillFlags int flags) {
final int id = mID;
if (id != NO_ID && !isViewIdGenerated(id)) {
String pkg, type, entry;
@@ -7981,8 +8172,11 @@
} else {
structure.setId(id, null, null, null);
}
+ if (forViewCapture) {
+ structure.setDataIsSensitive(false);
+ }
- if (forAutofill) {
+ if (forAutofill || forViewCapture) {
final @AutofillType int autofillType = getAutofillType();
// Don't need to fill autofill info if view does not support it.
// For example, only TextViews that are editable support autofill
@@ -8530,9 +8724,8 @@
if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
|| parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" + getAutofillViewId() + ", "
- + getClass() + ") is not important for autofill because parent "
- + parent + "'s importance is " + parentImportance);
+ Log.v(AUTOFILL_LOG_TAG, "View (" + this + ") is not important for autofill "
+ + "because parent " + parent + "'s importance is " + parentImportance);
}
return false;
}
@@ -8549,14 +8742,18 @@
if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
|| importance == IMPORTANT_FOR_AUTOFILL_NO) {
if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
- Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" + getAutofillViewId() + ", "
- + getClass() + ") is not important for autofill because its "
- + "importance is " + importance);
+ Log.v(AUTOFILL_LOG_TAG, "View (" + this + ") is not important for autofill "
+ + "because its importance is " + importance);
}
return false;
}
// Then use some heuristics to handle AUTO.
+ if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
+ Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
+ + this);
+ return false;
+ }
// Always include views that have an explicit resource id.
final int id = mID;
@@ -8584,6 +8781,198 @@
return false;
}
+ /**
+ * Gets the mode for determining whether this view is important for content capture.
+ *
+ * <p>See {@link #setImportantForContentCapture(int)} and
+ * {@link #isImportantForContentCapture()} for more info about this mode.
+ *
+ * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
+ * {@link #setImportantForContentCapture(int)}.
+ *
+ * @attr ref android.R.styleable#View_importantForContentCapture
+ */
+ @ViewDebug.ExportedProperty(mapping = {
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+ to = "yesExcludeDescendants"),
+ @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+ to = "noExcludeDescendants")})
+ public @ContentCaptureImportance int getImportantForContentCapture() {
+ // NOTE: the important for content capture values were the first flags added and are set in
+ // the rightmost position, so we don't need to shift them
+ return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+ }
+
+ /**
+ * Sets the mode for determining whether this view is considered important for content capture.
+ *
+ * <p>The platform determines the importance for autofill automatically but you
+ * can use this method to customize the behavior. Typically, a view that provides text should
+ * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
+ *
+ * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
+ * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
+ * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
+ * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
+ *
+ * @attr ref android.R.styleable#View_importantForContentCapture
+ */
+ public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
+ // Reset first
+ mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+ // Then set again
+ // NOTE: the important for content capture values were the first flags added and are set in
+ // the rightmost position, so we don't need to shift them
+ mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
+ }
+
+ /**
+ * Hints the Android System whether this view is considered important for Content Capture, based
+ * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
+ * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
+ *
+ * @return whether the view is considered important for autofill.
+ *
+ * @see #setImportantForContentCapture(int)
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ */
+ public final boolean isImportantForContentCapture() {
+ // Check parent mode to ensure we're important
+ ViewParent parent = mParent;
+ while (parent instanceof View) {
+ final int parentImportance = ((View) parent).getImportantForContentCapture();
+ if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for "
+ + "content capture because parent " + parent + "'s importance is "
+ + parentImportance);
+ }
+ return false;
+ }
+ parent = parent.getParent();
+ }
+
+ final int importance = getImportantForContentCapture();
+
+ // First, check the explicit states.
+ if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+ || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
+ return true;
+ }
+ if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+ || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" + this + ") is not important for content "
+ + "capture because its importance is " + importance);
+ }
+ return false;
+ }
+
+ // Then use some heuristics to handle AUTO.
+ if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
+ + " on view " + this);
+ return false;
+ }
+
+ // View group is important if at least one children also is
+ //TODO(b/111276913): decide if we really need to send the relevant parents or just the
+ // leaves (with absolute coordinates). If it's the latter, then we need to update this
+ // javadoc and ViewGroup's implementation.
+ if (this instanceof ViewGroup) {
+ final ViewGroup group = (ViewGroup) this;
+ for (int i = 0; i < group.getChildCount(); i++) {
+ final View child = group.getChildAt(i);
+ if (child.isImportantForContentCapture()) {
+ return true;
+ }
+ }
+ }
+
+ // If the app developer explicitly set hints or autofill hintsfor it, it's important.
+ if (getAutofillHints() != null) {
+ return true;
+ }
+
+ // Otherwise, assume it's not important...
+ return false;
+ }
+
+ /**
+ * Helper used to notify the {@link IntelligenceManager}anager when the view is removed or
+ * added, based on whether it's laid out and visible, and without knowing if the parent removed
+ * it from the view
+ * hierarchy.
+ */
+ // TODO(b/111276913): make sure the current algorithm covers all cases. For example, it should
+ // probably be called every time notifyEnterOrExitForAutoFillIfNeeded() is called as well.
+ private void notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+ @ContentCaptureNotificationType int type) {
+ if (type != CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+ && type != CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+ // Sanity check so it does not screw up the flags
+ Log.wtf(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded(): "
+ + "invalid type " + type + " for " + this);
+ return;
+ }
+
+ if (!isImportantForContentCapture()) return;
+
+ final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+ if (im == null || !im.isContentCaptureEnabled()) return;
+
+ // Make sure event is notified just once, and reset the
+ // PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE flag
+ boolean ignoreNotification = false;
+ if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+ if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+ == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+ ignoreNotification = true;
+ } else {
+ mPrivateFlags4 |= PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+ }
+ } else {
+ if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+ == CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+ ignoreNotification = true;
+ } else {
+ mPrivateFlags4 &= ~PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+ }
+ }
+ if (ignoreNotification) {
+ if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+ // TODO(b/111276913): remove this log statement if the algorithm is not improved
+ // (right now it's called too many times when the activity is stopped and/or views
+ // disappear
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded("
+ + type + "): ignoring repeated notification on " + this);
+ }
+ return;
+ }
+
+ if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+ final ViewStructure structure = im.newViewStructure(this);
+ boolean notifyMgr = onProvideContentCaptureStructure(structure, /* flags= */ 0);
+ if (notifyMgr) {
+ im.notifyViewAppeared(structure);
+ }
+ mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED;
+ } else {
+ if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED) == 0) {
+ return; // skip initial notification
+ }
+ im.notifyViewDisappeared(getAutofillId());
+ }
+ }
+
@Nullable
private AutofillManager getAutofillManager() {
return mContext.getSystemService(AutofillManager.class);
@@ -13094,6 +13483,9 @@
: AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
}
}
+ notifyNodeAddedOrRemovedForContentCaptureIfNeeded(isVisible
+ ? CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+ : CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
}
/**
@@ -18630,6 +19022,8 @@
}
notifyEnterOrExitForAutoFillIfNeeded(false);
+ notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+ CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
}
/**
@@ -20934,6 +21328,13 @@
mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
notifyEnterOrExitForAutoFillIfNeeded(true);
}
+
+ if ((mViewFlags & VISIBILITY_MASK) == VISIBLE
+ && (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT) == 0) {
+ notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+ CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED);
+ mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT;
+ }
}
private boolean hasParentWantsFocus() {
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 38dcdd3..6efb6f3 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -24,7 +24,6 @@
import android.os.LocaleList;
import android.util.Pair;
import android.view.View.AutofillImportance;
-import android.view.ViewStructure.HtmlInfo;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java
index 2530ae3..befcb55 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.java
@@ -16,12 +16,17 @@
package android.view.intelligence;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemClock;
import android.view.autofill.AutofillId;
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -60,14 +65,14 @@
*
* <p>The metadata of the node is available through {@link #getViewNode()}.
*/
- public static final int TYPE_VIEW_ADDED = 5;
+ public static final int TYPE_VIEW_APPEARED = 5;
/**
* Called when a node has been removed from the screen and is not visible to the user anymore.
*
* <p>The id of the node is available through {@link #getId()}.
*/
- public static final int TYPE_VIEW_REMOVED = 6;
+ public static final int TYPE_VIEW_DISAPPEARED = 6;
/**
* Called when the text of a node has been changed.
@@ -85,8 +90,8 @@
TYPE_ACTIVITY_PAUSED,
TYPE_ACTIVITY_RESUMED,
TYPE_ACTIVITY_STOPPED,
- TYPE_VIEW_ADDED,
- TYPE_VIEW_REMOVED,
+ TYPE_VIEW_APPEARED,
+ TYPE_VIEW_DISAPPEARED,
TYPE_VIEW_TEXT_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
@@ -95,7 +100,9 @@
private final int mType;
private final long mEventTime;
private final int mFlags;
-
+ private @Nullable AutofillId mId;
+ private @Nullable ViewNode mNode;
+ private @Nullable CharSequence mText;
/** @hide */
public ContentCaptureEvent(int type, long eventTime, int flags) {
@@ -104,12 +111,42 @@
mFlags = flags;
}
+
+ /** @hide */
+ public ContentCaptureEvent(int type, int flags) {
+ this(type, SystemClock.uptimeMillis(), flags);
+ }
+
+ /** @hide */
+ public ContentCaptureEvent(int type) {
+ this(type, /* flags= */ 0);
+ }
+
+ /** @hide */
+ public ContentCaptureEvent setAutofillId(@NonNull AutofillId id) {
+ mId = Preconditions.checkNotNull(id);
+ return this;
+ }
+
+ /** @hide */
+ public ContentCaptureEvent setViewNode(@NonNull ViewNode node) {
+ mNode = Preconditions.checkNotNull(node);
+ return this;
+ }
+
+ /** @hide */
+ public ContentCaptureEvent setText(@Nullable CharSequence text) {
+ mText = text;
+ return this;
+ }
+
/**
* Gets the type of the event.
*
* @return one of {@link #TYPE_ACTIVITY_STARTED}, {@link #TYPE_ACTIVITY_RESUMED},
* {@link #TYPE_ACTIVITY_PAUSED}, {@link #TYPE_ACTIVITY_STOPPED},
- * {@link #TYPE_VIEW_ADDED}, {@link #TYPE_VIEW_REMOVED}, or {@link #TYPE_VIEW_TEXT_CHANGED}.
+ * {@link #TYPE_VIEW_APPEARED}, {@link #TYPE_VIEW_DISAPPEARED},
+ * or {@link #TYPE_VIEW_TEXT_CHANGED}.
*/
public @EventType int getType() {
return mType;
@@ -135,21 +172,21 @@
/**
* Gets the whole metadata of the node associated with the event.
*
- * <p>Only set on {@link #TYPE_VIEW_ADDED} events.
+ * <p>Only set on {@link #TYPE_VIEW_APPEARED} events.
*/
@Nullable
public ViewNode getViewNode() {
- return null;
+ return mNode;
}
/**
* Gets the {@link AutofillId} of the node associated with the event.
*
- * <p>Only set on {@link #TYPE_VIEW_REMOVED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
+ * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
*/
@Nullable
public AutofillId getId() {
- return null;
+ return mId;
}
/**
@@ -159,16 +196,41 @@
*/
@Nullable
public CharSequence getText() {
- return null;
+ return mText;
+ }
+
+ /** @hide */
+ public void dump(@NonNull PrintWriter pw) {
+ pw.print("type="); pw.print(getTypeAsString(mType));
+ pw.print(", time="); pw.print(mEventTime);
+ if (mFlags > 0) {
+ pw.print(", flags="); pw.print(mFlags);
+ }
+ if (mId != null) {
+ pw.print(", id="); pw.print(mId);
+ }
+ if (mNode != null) {
+ pw.print(", id="); pw.print(mNode.getAutofillId());
+ }
}
@Override
public String toString() {
final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=")
- .append(getTypeAsString(mType)).append(", time=").append(mEventTime);
+ .append(getTypeAsString(mType));
if (mFlags > 0) {
string.append(", flags=").append(mFlags);
}
+ if (mId != null) {
+ string.append(", id=").append(mId);
+ }
+ if (mNode != null) {
+ final String className = mNode.getClassName();
+ if (mNode != null) {
+ string.append(", class=").append(className);
+ }
+ string.append(", id=").append(mNode.getAutofillId());
+ }
return string.append(']').toString();
}
@@ -182,6 +244,9 @@
parcel.writeInt(mType);
parcel.writeLong(mEventTime);
parcel.writeInt(mFlags);
+ parcel.writeParcelable(mId, flags);
+ ViewNode.writeToParcel(parcel, mNode, flags);
+ parcel.writeCharSequence(mText);
}
public static final Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -192,7 +257,17 @@
final int type = parcel.readInt();
final long eventTime = parcel.readLong();
final int flags = parcel.readInt();
- return new ContentCaptureEvent(type, eventTime, flags);
+ final ContentCaptureEvent event = new ContentCaptureEvent(type, eventTime, flags);
+ final AutofillId id = parcel.readParcelable(null);
+ if (id != null) {
+ event.setAutofillId(id);
+ }
+ final ViewNode node = ViewNode.readFromParcel(parcel);
+ if (node != null) {
+ event.setViewNode(node);
+ }
+ event.setText(parcel.readCharSequence());
+ return event;
}
@Override
@@ -201,7 +276,6 @@
}
};
-
/** @hide */
public static String getTypeAsString(@EventType int type) {
switch (type) {
@@ -213,10 +287,10 @@
return "ACTIVITY_PAUSED";
case TYPE_ACTIVITY_STOPPED:
return "ACTIVITY_STOPPED";
- case TYPE_VIEW_ADDED:
- return "VIEW_ADDED";
- case TYPE_VIEW_REMOVED:
- return "VIEW_REMOVED";
+ case TYPE_VIEW_APPEARED:
+ return "VIEW_APPEARED";
+ case TYPE_VIEW_DISAPPEARED:
+ return "VIEW_DISAPPEARED";
case TYPE_VIEW_TEXT_CHANGED:
return "VIEW_TEXT_CHANGED";
default:
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index 9bf6c2c..c02fb32 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -15,6 +15,12 @@
*/
package android.view.intelligence;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -22,11 +28,15 @@
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.service.intelligence.InteractionSessionId;
import android.util.Log;
+import android.view.View;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillId;
import android.view.intelligence.ContentCaptureEvent.EventType;
import com.android.internal.annotations.GuardedBy;
@@ -34,8 +44,7 @@
import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.List;
+import java.util.ArrayList;
import java.util.Set;
/**
@@ -46,8 +55,9 @@
private static final String TAG = "IntelligenceManager";
- // TODO(b/111276913): define a way to dynamically set it (for example, using settings?)
+ // TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
private static final boolean VERBOSE = false;
+ private static final boolean DEBUG = true; // STOPSHIP if not set to false
/**
* Used to indicate that a text change was caused by user input (for example, through IME).
@@ -55,7 +65,6 @@
//TODO(b/111276913): link to notifyTextChanged() method once available
public static final int FLAG_USER_INPUT = 0x1;
-
/**
* Initial state, when there is no session.
*
@@ -77,6 +86,15 @@
*/
public static final int STATE_ACTIVE = 2;
+ 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.
+ */
+ private static final int MAX_DELAYED_SIZE = 20;
+
private final Context mContext;
@Nullable
@@ -99,10 +117,24 @@
@GuardedBy("mLock")
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<>();
+
+ private final Handler mHandler;
+
/** @hide */
public IntelligenceManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
mService = service;
+
+ // TODO(b/111276913): use an existing bg thread instead...
+ final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
+ bgThread.start();
+ mHandler = Handler.createAsync(bgThread.getLooper());
}
/** @hide */
@@ -111,8 +143,9 @@
synchronized (mLock) {
if (mState != STATE_UNKNOWN) {
+ // TODO(b/111276913): revisit this scenario
Log.w(TAG, "ignoring onActivityStarted(" + token + ") while on state "
- + getStateAsStringLocked());
+ + getStateAsString(mState));
return;
}
mState = STATE_WAITING_FOR_SERVER;
@@ -121,8 +154,8 @@
mComponentName = componentName;
if (VERBOSE) {
- Log.v(TAG, "onActivityStarted(): token=" + token + ", act=" + componentName
- + ", id=" + mId);
+ Log.v(TAG, "onActivityCreated(): token=" + token + ", act="
+ + getActivityDebugNameLocked() + ", id=" + mId);
}
final int flags = 0; // TODO(b/111276913): get proper flags
@@ -138,12 +171,12 @@
} else {
// TODO(b/111276913): handle other cases like disabled by
// service
- mState = STATE_UNKNOWN;
+ resetStateLocked();
}
if (VERBOSE) {
Log.v(TAG, "onActivityStarted() result: code=" + resultCode
+ ", id=" + mId
- + ", state=" + getStateAsStringLocked());
+ + ", state=" + getStateAsString(mState));
}
}
}
@@ -154,6 +187,60 @@
}
}
+ //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 handleSendEvent(@NonNull ContentCaptureEvent event) {
+
+ 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.
+ Log.w(TAG, "Closing session for " + getActivityDebugNameLocked()
+ + " after " + numberEvents + " delayed events");
+ // 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;
+ }
+
+ if (mId == null) {
+ // Sanity check - should not happen
+ Log.wtf(TAG, "null session id for " + mComponentName);
+ 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();
+ }
+ }
+ }
+
/**
* Used for intermediate events (i.e, other than created and destroyed).
*
@@ -161,28 +248,11 @@
*/
public void onActivityLifecycleEvent(@EventType int type) {
if (!isContentCaptureEnabled()) return;
-
- //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
- // calling right away
- final ContentCaptureEvent event = new ContentCaptureEvent(type, SystemClock.uptimeMillis(),
- 0);
- final List<ContentCaptureEvent> events = Arrays.asList(event);
-
- synchronized (mLock) {
- //TODO(b/111276913): check session state; for example, how to handle if it's waiting for
- // remote id
-
- if (VERBOSE) {
- Log.v(TAG, "onActivityLifecycleEvent() for " + mComponentName.flattenToShortString()
- + ": " + ContentCaptureEvent.getTypeAsString(type));
- }
-
- try {
- mService.sendEvents(mContext.getUserId(), mId, events);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ if (VERBOSE) {
+ Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugNameLocked()
+ + ": " + ContentCaptureEvent.getTypeAsString(type));
}
+ sendEvent(new ContentCaptureEvent(type));
}
/** @hide */
@@ -194,22 +264,105 @@
// id) and send it to the cache of batched commands
if (VERBOSE) {
- Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsStringLocked()
+ Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsString(mState)
+ ", mId=" + mId);
}
try {
mService.finishSession(mContext.getUserId(), mId);
- mState = STATE_UNKNOWN;
- mId = null;
- mApplicationToken = null;
- mComponentName = null;
+ resetStateLocked();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
+ @GuardedBy("mLock")
+ private void resetStateLocked() {
+ mState = STATE_UNKNOWN;
+ mId = null;
+ mApplicationToken = null;
+ mComponentName = null;
+ mEvents.clear();
+ }
+
+ /**
+ * Notifies the Intelligence Service that a node has been added to the view structure.
+ *
+ * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+ * automatically by the Android System for views that return {@code true} on
+ * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
+ *
+ * @param node node that has been added.
+ */
+ public void notifyViewAppeared(@NonNull ViewStructure node) {
+ Preconditions.checkNotNull(node);
+ if (!isContentCaptureEnabled()) return;
+
+ if (!(node instanceof ViewNode.ViewStructureImpl)) {
+ throw new IllegalArgumentException("Invalid node class: " + node.getClass());
+ }
+ sendEvent(new ContentCaptureEvent(TYPE_VIEW_APPEARED)
+ .setViewNode(((ViewNode.ViewStructureImpl) node).mNode));
+ }
+
+ /**
+ * Notifies the Intelligence Service that a node has been removed from the view structure.
+ *
+ * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+ * automatically by the Android System for standard views.
+ *
+ * @param id id of the node that has been removed.
+ */
+ public void notifyViewDisappeared(@NonNull AutofillId id) {
+ Preconditions.checkNotNull(id);
+ if (!isContentCaptureEnabled()) return;
+
+ sendEvent(new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id));
+ }
+
+ /**
+ * Notifies the Intelligence Service that the value of a text node has been changed.
+ *
+ * @param id of the node.
+ * @param text new text.
+ * @param flags either {@code 0} or {@link #FLAG_USER_INPUT} when the value was explicitly
+ * changed by the user (for example, through the keyboard).
+ */
+ 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));
+ }
+
+ /**
+ * Creates a {@link ViewStructure} for a "standard" view.
+ *
+ * @hide
+ */
+ @NonNull
+ public ViewStructure newViewStructure(@NonNull View view) {
+ return new ViewNode.ViewStructureImpl(view);
+ }
+
+ /**
+ * Creates a {@link ViewStructure} for a "virtual" view, so it can be passed to
+ * {@link #notifyViewAppeared(ViewStructure)} by the view managing the virtual view hierarchy.
+ *
+ * @param parentId id of the virtual view parent (it can be obtained by calling
+ * {@link ViewStructure#getAutofillId()} on the parent).
+ * @param virtualId id of the virtual child, relative to the parent.
+ *
+ * @return a new {@link ViewStructure} that can be used for Content Capture purposes.
+ */
+ @NonNull
+ public ViewStructure newVirtualViewStructure(@NonNull AutofillId parentId, int virtualId) {
+ return new ViewNode.ViewStructureImpl(parentId, virtualId);
+ }
+
/**
* Returns the component name of the {@code android.service.intelligence.IntelligenceService}
* that is enabled for the current user.
@@ -322,15 +475,29 @@
pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
pw.print(prefix2); pw.print("id: "); pw.println(mId);
pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
- pw.print(getStateAsStringLocked()); pw.println(")");
- pw.print(prefix2); pw.print("appToken: "); pw.println(mApplicationToken);
- pw.print(prefix2); pw.print("componentName: "); pw.println(mComponentName);
+ pw.print(getStateAsString(mState)); pw.println(")");
+ pw.print(prefix2); pw.print("app token: "); pw.println(mApplicationToken);
+ pw.print(prefix2); pw.print("component name: ");
+ pw.println(mComponentName == null ? "null" : mComponentName.flattenToShortString());
+ final int numberEvents = mEvents.size();
+ pw.print(prefix2); pw.print("batched events: "); pw.println(numberEvents);
+ if (numberEvents > 0) {
+ for (int i = 0; i < numberEvents; i++) {
+ final ContentCaptureEvent event = mEvents.get(i);
+ pw.println(i); pw.print(": "); event.dump(pw); pw.println();
+ }
+
+ }
}
}
+ /**
+ * Gets a string that can be used to identify the activity on logging statements.
+ */
@GuardedBy("mLock")
- private String getStateAsStringLocked() {
- return getStateAsString(mState);
+ private String getActivityDebugNameLocked() {
+ return mComponentName == null ? mContext.getPackageName()
+ : mComponentName.flattenToShortString();
}
@NonNull
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/intelligence/ViewNode.java
index 357ecf5..cc78e6b 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/intelligence/ViewNode.java
@@ -15,10 +15,24 @@
*/
package android.view.intelligence;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.assist.AssistStructure;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.os.Parcel;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewStructure;
+import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.Preconditions;
//TODO(b/111276913): add javadocs / implement Parcelable / implement
//TODO(b/111276913): for now it's extending ViewNode directly as it needs most of its properties,
@@ -28,6 +42,16 @@
@SystemApi
public final class ViewNode extends AssistStructure.ViewNode {
+ private static final String TAG = "ViewNode";
+
+ private AutofillId mParentAutofillId;
+
+ // TODO(b/111276913): temporarily setting some fields here while they're not accessible from the
+ // superclass
+ private AutofillId mAutofillId;
+ private CharSequence mText;
+ private String mClassName;
+
/** @hide */
public ViewNode() {
}
@@ -38,7 +62,343 @@
*/
@Nullable
public AutofillId getParentAutofillId() {
- //TODO(b/111276913): implement
- return null;
+ return mParentAutofillId;
+ }
+
+ // TODO(b/111276913): temporarily overwriting some methods
+ @Override
+ public AutofillId getAutofillId() {
+ return mAutofillId;
+ }
+ @Override
+ public CharSequence getText() {
+ return mText;
+ }
+ @Override
+ public String getClassName() {
+ return mClassName;
+ }
+
+ /** @hide */
+ public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) {
+ if (node == null) {
+ parcel.writeParcelable(null, flags);
+ return;
+ }
+ parcel.writeParcelable(node.mAutofillId, flags);
+ parcel.writeParcelable(node.mParentAutofillId, flags);
+ parcel.writeCharSequence(node.mText);
+ parcel.writeString(node.mClassName);
+ }
+
+ /** @hide */
+ public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) {
+ final AutofillId id = parcel.readParcelable(null);
+ if (id == null) return null;
+
+ final ViewNode node = new ViewNode();
+
+ node.mAutofillId = id;
+ node.mParentAutofillId = parcel.readParcelable(null);
+ node.mText = parcel.readCharSequence();
+ node.mClassName = parcel.readString();
+
+ return node;
+ }
+
+ /** @hide */
+ static final class ViewStructureImpl extends ViewStructure {
+
+ final ViewNode mNode = new ViewNode();
+
+ ViewStructureImpl(@NonNull View view) {
+ mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId();
+ final ViewParent parent = view.getParent();
+ if (parent instanceof View) {
+ mNode.mParentAutofillId = ((View) parent).getAutofillId();
+ }
+ }
+
+ ViewStructureImpl(@NonNull AutofillId parentId, int virtualId) {
+ mNode.mParentAutofillId = Preconditions.checkNotNull(parentId);
+ mNode.mAutofillId = new AutofillId(parentId, virtualId);
+ }
+
+ @Override
+ public void setId(int id, String packageName, String typeName, String entryName) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setTransformation(Matrix matrix) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setElevation(float elevation) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAssistBlocked(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setEnabled(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setClickable(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setLongClickable(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setContextClickable(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setFocusable(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setFocused(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAccessibilityFocused(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setCheckable(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setChecked(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setSelected(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setActivated(boolean state) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setOpaque(boolean opaque) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setClassName(String className) {
+ // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+ mNode.mClassName = className;
+ }
+
+ @Override
+ public void setContentDescription(CharSequence contentDescription) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setText(CharSequence text) {
+ // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+ mNode.mText = text;
+ }
+
+ @Override
+ public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setTextStyle(float size, int fgColor, int bgColor, int style) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setTextLines(int[] charOffsets, int[] baselines) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setHint(CharSequence hint) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public CharSequence getText() {
+ // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+ return mNode.mText;
+ }
+
+ @Override
+ public int getTextSelectionStart() {
+ // TODO(b/111276913): implement or move to superclass
+ return 0;
+ }
+
+ @Override
+ public int getTextSelectionEnd() {
+ // TODO(b/111276913): implement or move to superclass
+ return 0;
+ }
+
+ @Override
+ public CharSequence getHint() {
+ // TODO(b/111276913): implement or move to superclass
+ return null;
+ }
+
+ @Override
+ public Bundle getExtras() {
+ // TODO(b/111276913): implement or move to superclass
+ return null;
+ }
+
+ @Override
+ public boolean hasExtras() {
+ // TODO(b/111276913): implement or move to superclass
+ return false;
+ }
+
+ @Override
+ public void setChildCount(int num) {
+ Log.w(TAG, "setChildCount() is not supported");
+ }
+
+ @Override
+ public int addChildCount(int num) {
+ Log.w(TAG, "addChildCount() is not supported");
+ return 0;
+ }
+
+ @Override
+ public int getChildCount() {
+ Log.w(TAG, "getChildCount() is not supported");
+ return 0;
+ }
+
+ @Override
+ public ViewStructure newChild(int index) {
+ Log.w(TAG, "newChild() is not supported");
+ return null;
+ }
+
+ @Override
+ public ViewStructure asyncNewChild(int index) {
+ Log.w(TAG, "asyncNewChild() is not supported");
+ return null;
+ }
+
+ @Override
+ public AutofillId getAutofillId() {
+ // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+ return mNode.mAutofillId;
+ }
+
+ @Override
+ public void setAutofillId(AutofillId id) {
+ // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+ mNode.mAutofillId = id;
+ }
+
+ @Override
+ public void setAutofillId(AutofillId parentId, int virtualId) {
+ // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+ mNode.mAutofillId = new AutofillId(parentId, virtualId);
+ }
+
+ @Override
+ public void setAutofillType(int type) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAutofillHints(String[] hint) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAutofillValue(AutofillValue value) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setAutofillOptions(CharSequence[] options) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setInputType(int inputType) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void setDataIsSensitive(boolean sensitive) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public void asyncCommit() {
+ Log.w(TAG, "asyncCommit() is not supported");
+ }
+
+ @Override
+ public Rect getTempRect() {
+ // TODO(b/111276913): implement or move to superclass
+ return null;
+ }
+
+ @Override
+ public void setWebDomain(String domain) {
+ Log.w(TAG, "setWebDomain() is not supported");
+ }
+
+ @Override
+ public void setLocaleList(LocaleList localeList) {
+ // TODO(b/111276913): implement or move to superclass
+ }
+
+ @Override
+ public Builder newHtmlInfoBuilder(String tagName) {
+ Log.w(TAG, "newHtmlInfoBuilder() is not supported");
+ return null;
+ }
+
+ @Override
+ public void setHtmlInfo(HtmlInfo htmlInfo) {
+ Log.w(TAG, "setHtmlInfo() is not supported");
+ }
}
}
diff --git a/core/java/android/view/textclassifier/ModelFileManager.java b/core/java/android/view/textclassifier/ModelFileManager.java
index adea125..896b516 100644
--- a/core/java/android/view/textclassifier/ModelFileManager.java
+++ b/core/java/android/view/textclassifier/ModelFileManager.java
@@ -74,10 +74,9 @@
* @param localeList the required locales, use {@code null} if there is no preference.
*/
public ModelFile findBestModelFile(@Nullable LocaleList localeList) {
- // Specified localeList takes priority over the system default, so it is listed first.
final String languages = localeList == null || localeList.isEmpty()
? LocaleList.getDefault().toLanguageTags()
- : localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
+ : localeList.toLanguageTags();
final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
ModelFile bestModel = null;
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 2fc7422..50801a2 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -90,6 +90,10 @@
"entity_list_not_editable";
private static final String ENTITY_LIST_EDITABLE =
"entity_list_editable";
+ private static final String IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT =
+ "in_app_conversation_action_types_default";
+ private static final String NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT =
+ "notification_conversation_action_types_default";
private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
@@ -111,6 +115,18 @@
.add(TextClassifier.TYPE_DATE)
.add(TextClassifier.TYPE_DATE_TIME)
.add(TextClassifier.TYPE_FLIGHT_NUMBER).toString();
+ private static final String CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES =
+ new StringJoiner(ENTITY_LIST_DELIMITER)
+ .add(ConversationActions.TYPE_TEXT_REPLY)
+ .add(ConversationActions.TYPE_CREATE_REMINDER)
+ .add(ConversationActions.TYPE_CALL_PHONE)
+ .add(ConversationActions.TYPE_OPEN_URL)
+ .add(ConversationActions.TYPE_SEND_EMAIL)
+ .add(ConversationActions.TYPE_SEND_SMS)
+ .add(ConversationActions.TYPE_TRACK_FLIGHT)
+ .add(ConversationActions.TYPE_VIEW_CALENDAR)
+ .add(ConversationActions.TYPE_VIEW_MAP)
+ .toString();
private final boolean mSystemTextClassifierEnabled;
private final boolean mLocalTextClassifierEnabled;
@@ -126,6 +142,8 @@
private final List<String> mEntityListDefault;
private final List<String> mEntityListNotEditable;
private final List<String> mEntityListEditable;
+ private final List<String> mInAppConversationActionTypesDefault;
+ private final List<String> mNotificationConversationActionTypesDefault;
private TextClassificationConstants(@Nullable String settings) {
final KeyValueListParser parser = new KeyValueListParser(',');
@@ -177,6 +195,12 @@
mEntityListEditable = parseEntityList(parser.getString(
ENTITY_LIST_EDITABLE,
ENTITY_LIST_DEFAULT_VALUE));
+ mInAppConversationActionTypesDefault = parseEntityList(parser.getString(
+ IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
+ CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
+ mNotificationConversationActionTypesDefault = parseEntityList(parser.getString(
+ NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
+ CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
}
/** Load from a settings string. */
@@ -240,6 +264,14 @@
return mEntityListEditable;
}
+ public List<String> getInAppConversationActionTypes() {
+ return mInAppConversationActionTypesDefault;
+ }
+
+ public List<String> getNotificationConversationActionTypes() {
+ return mNotificationConversationActionTypesDefault;
+ }
+
private static List<String> parseEntityList(String listStr) {
return Collections.unmodifiableList(Arrays.asList(listStr.split(ENTITY_LIST_DELIMITER)));
}
@@ -261,6 +293,9 @@
pw.printPair("getEntityListDefault", mEntityListDefault);
pw.printPair("getEntityListNotEditable", mEntityListNotEditable);
pw.printPair("getEntityListEditable", mEntityListEditable);
+ pw.printPair("getInAppConversationActionTypes", mInAppConversationActionTypesDefault);
+ pw.printPair("getNotificationConversationActionTypes",
+ mNotificationConversationActionTypesDefault);
pw.decreaseIndent();
pw.println();
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index e675744..524f709 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -48,6 +48,9 @@
/**
* Interface for providing text classification related features.
+ * <p>
+ * The TextClassifier may be used to understand the meaning of text, as well as generating predicted
+ * next actions based on the text.
*
* <p><strong>NOTE: </strong>Unless otherwise stated, methods of this interface are blocking
* operations. Call on a worker thread.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 159bfaa..798a820 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -40,11 +40,13 @@
import android.provider.Browser;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
+import android.text.TextUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.google.android.textclassifier.ActionsSuggestionsModel;
import com.google.android.textclassifier.AnnotatorModel;
import com.google.android.textclassifier.LangIdModel;
@@ -90,6 +92,11 @@
private static final File UPDATED_LANG_ID_MODEL_FILE =
new File("/data/misc/textclassifier/lang_id.model");
+ // Actions
+ private static final String ACTIONS_FACTORY_MODEL_FILENAME_REGEX = "actions_suggestions.model";
+ private static final File UPDATED_ACTIONS_MODEL =
+ new File("/data/misc/textclassifier/actions_suggestions.model");
+
private final Context mContext;
private final TextClassifier mFallback;
private final GenerateLinksLogger mGenerateLinksLogger;
@@ -101,6 +108,8 @@
private AnnotatorModel mAnnotatorImpl;
@GuardedBy("mLock") // Do not access outside this lock.
private LangIdModel mLangIdImpl;
+ @GuardedBy("mLock") // Do not access outside this lock.
+ private ActionsSuggestionsModel mActionsImpl;
private final Object mLoggerLock = new Object();
@GuardedBy("mLoggerLock") // Do not access outside this lock.
@@ -110,6 +119,7 @@
private final ModelFileManager mAnnotatorModelFileManager;
private final ModelFileManager mLangIdModelFileManager;
+ private final ModelFileManager mActionsModelFileManager;
public TextClassifierImpl(
Context context, TextClassificationConstants settings, TextClassifier fallback) {
@@ -131,6 +141,13 @@
UPDATED_LANG_ID_MODEL_FILE,
fd -> -1, // TODO: Replace this with LangIdModel.getVersion(fd)
fd -> ModelFileManager.ModelFile.LANGUAGE_INDEPENDENT));
+ mActionsModelFileManager = new ModelFileManager(
+ new ModelFileManager.ModelFileSupplierImpl(
+ FACTORY_MODEL_DIR,
+ ACTIONS_FACTORY_MODEL_FILENAME_REGEX,
+ UPDATED_ACTIONS_MODEL,
+ ActionsSuggestionsModel::getVersion,
+ ActionsSuggestionsModel::getLocales));
}
public TextClassifierImpl(Context context, TextClassificationConstants settings) {
@@ -346,10 +363,69 @@
return mFallback.detectLanguage(request);
}
+ @Override
+ public ConversationActions suggestConversationActions(ConversationActions.Request request) {
+ Preconditions.checkNotNull(request);
+ Utils.checkMainThread();
+ try {
+ ActionsSuggestionsModel actionsImpl = getActionsImpl();
+ if (actionsImpl == null) {
+ // Actions model is optional, fallback if it is not available.
+ return mFallback.suggestConversationActions(request);
+ }
+ List<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayList<>();
+ for (ConversationActions.Message message : request.getConversation()) {
+ if (TextUtils.isEmpty(message.getText())) {
+ continue;
+ }
+ // TODO: We need to map the Person object to user id.
+ int userId = 1;
+ nativeMessages.add(
+ new ActionsSuggestionsModel.ConversationMessage(
+ userId, message.getText().toString()));
+ }
+ ActionsSuggestionsModel.Conversation nativeConversation =
+ new ActionsSuggestionsModel.Conversation(nativeMessages.toArray(
+ new ActionsSuggestionsModel.ConversationMessage[0]));
+
+ ActionsSuggestionsModel.ActionSuggestion[] nativeSuggestions =
+ actionsImpl.suggestActions(nativeConversation, null);
+
+ Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
+ List<ConversationActions.ConversationAction> conversationActions = new ArrayList<>();
+ int maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length);
+ for (int i = 0; i < maxSuggestions; i++) {
+ ActionsSuggestionsModel.ActionSuggestion nativeSuggestion = nativeSuggestions[i];
+ String actionType = nativeSuggestion.getActionType();
+ if (!expectedTypes.contains(actionType)) {
+ continue;
+ }
+ conversationActions.add(
+ new ConversationActions.ConversationAction.Builder(actionType)
+ .setTextReply(nativeSuggestion.getResponseText())
+ .setConfidenceScore(nativeSuggestion.getScore())
+ .build());
+ }
+ return new ConversationActions(conversationActions);
+ } catch (Throwable t) {
+ // Avoid throwing from this method. Log the error.
+ Log.e(LOG_TAG, "Error suggesting conversation actions.", t);
+ }
+ return mFallback.suggestConversationActions(request);
+ }
+
+ private Collection<String> resolveActionTypesFromRequest(ConversationActions.Request request) {
+ List<String> defaultActionTypes =
+ request.getHints().contains(ConversationActions.HINT_FOR_NOTIFICATION)
+ ? mSettings.getNotificationConversationActionTypes()
+ : mSettings.getInAppConversationActionTypes();
+ return request.getTypeConfig().resolveTypes(defaultActionTypes);
+ }
+
private AnnotatorModel getAnnotatorImpl(LocaleList localeList)
throws FileNotFoundException {
synchronized (mLock) {
- localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
+ localeList = localeList == null ? LocaleList.getDefault() : localeList;
final ModelFileManager.ModelFile bestModel =
mAnnotatorModelFileManager.findBestModelFile(localeList);
if (bestModel == null) {
@@ -386,7 +462,7 @@
synchronized (mLock) {
if (mLangIdImpl == null) {
final ModelFileManager.ModelFile bestModel =
- mLangIdModelFileManager.findBestModelFile(LocaleList.getEmptyLocaleList());
+ mLangIdModelFileManager.findBestModelFile(null);
if (bestModel == null) {
throw new FileNotFoundException("No LangID model is found");
}
@@ -404,6 +480,30 @@
}
}
+ @Nullable
+ private ActionsSuggestionsModel getActionsImpl() throws FileNotFoundException {
+ synchronized (mLock) {
+ if (mActionsImpl == null) {
+ // TODO: Use LangID to determine the locale we should use here?
+ final ModelFileManager.ModelFile bestModel =
+ mActionsModelFileManager.findBestModelFile(LocaleList.getDefault());
+ if (bestModel == null) {
+ return null;
+ }
+ final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
+ new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY);
+ try {
+ if (pfd != null) {
+ mActionsImpl = new ActionsSuggestionsModel(pfd.getFd());
+ }
+ } finally {
+ maybeCloseAndLogError(pfd);
+ }
+ }
+ return mActionsImpl;
+ }
+ }
+
private String createId(String text, int start, int end) {
synchronized (mLock) {
return SelectionSessionLogger.createId(text, start, end, mContext,
@@ -471,11 +571,19 @@
}
printWriter.decreaseIndent();
printWriter.println("LangID model file(s):");
+ printWriter.increaseIndent();
for (ModelFileManager.ModelFile modelFile :
mLangIdModelFileManager.listModelFiles()) {
printWriter.println(modelFile.toString());
}
printWriter.decreaseIndent();
+ printWriter.println("Actions model file(s):");
+ printWriter.increaseIndent();
+ for (ModelFileManager.ModelFile modelFile :
+ mActionsModelFileManager.listModelFiles()) {
+ printWriter.println(modelFile.toString());
+ }
+ printWriter.decreaseIndent();
printWriter.printPair("mFallback", mFallback);
printWriter.decreaseIndent();
printWriter.println();
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index b31438f..02aee50 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
@@ -92,10 +93,12 @@
private final String mFullText;
private final List<TextLink> mLinks;
+ private final Bundle mExtras;
- private TextLinks(String fullText, ArrayList<TextLink> links) {
+ private TextLinks(String fullText, ArrayList<TextLink> links, Bundle extras) {
mFullText = fullText;
mLinks = Collections.unmodifiableList(links);
+ mExtras = extras;
}
/**
@@ -116,6 +119,18 @@
}
/**
+ * Returns the extended data.
+ *
+ * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+ * prefer to hold a reference to the returned bundle rather than frequently calling this
+ * method.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras.deepCopy();
+ }
+
+ /**
* Annotates the given text with the generated links. It will fail if the provided text doesn't
* match the original text used to create the TextLinks.
*
@@ -158,6 +173,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mFullText);
dest.writeTypedList(mLinks);
+ dest.writeBundle(mExtras);
}
public static final Parcelable.Creator<TextLinks> CREATOR =
@@ -176,6 +192,7 @@
private TextLinks(Parcel in) {
mFullText = in.readString();
mLinks = in.createTypedArrayList(TextLink.CREATOR);
+ mExtras = in.readBundle();
}
/**
@@ -304,18 +321,21 @@
@Nullable private final TextClassifier.EntityConfig mEntityConfig;
private final boolean mLegacyFallback;
private String mCallingPackageName;
+ private final Bundle mExtras;
private Request(
CharSequence text,
LocaleList defaultLocales,
TextClassifier.EntityConfig entityConfig,
boolean legacyFallback,
- String callingPackageName) {
+ String callingPackageName,
+ Bundle extras) {
mText = text;
mDefaultLocales = defaultLocales;
mEntityConfig = entityConfig;
mLegacyFallback = legacyFallback;
mCallingPackageName = callingPackageName;
+ mExtras = extras;
}
/**
@@ -362,6 +382,18 @@
}
/**
+ * Returns the extended data.
+ *
+ * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+ * prefer to hold a reference to the returned bundle rather than frequently calling this
+ * method.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras.deepCopy();
+ }
+
+ /**
* A builder for building TextLinks requests.
*/
public static final class Builder {
@@ -372,6 +404,7 @@
@Nullable private TextClassifier.EntityConfig mEntityConfig;
private boolean mLegacyFallback = true; // Use legacy fall back by default.
private String mCallingPackageName;
+ @Nullable private Bundle mExtras;
public Builder(@NonNull CharSequence text) {
mText = Preconditions.checkNotNull(text);
@@ -431,15 +464,25 @@
}
/**
+ * Sets the extended data.
+ *
+ * @return this builder
+ */
+ public Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds and returns the request object.
*/
@NonNull
public Request build() {
return new Request(
mText, mDefaultLocales, mEntityConfig,
- mLegacyFallback, mCallingPackageName);
+ mLegacyFallback, mCallingPackageName,
+ mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
}
-
}
/**
@@ -469,6 +512,7 @@
mEntityConfig.writeToParcel(dest, flags);
}
dest.writeString(mCallingPackageName);
+ dest.writeBundle(mExtras);
}
public static final Parcelable.Creator<Request> CREATOR =
@@ -491,6 +535,7 @@
? null : TextClassifier.EntityConfig.CREATOR.createFromParcel(in);
mLegacyFallback = true;
mCallingPackageName = in.readString();
+ mExtras = in.readBundle();
}
}
@@ -575,6 +620,7 @@
public static final class Builder {
private final String mFullText;
private final ArrayList<TextLink> mLinks;
+ private Bundle mExtras;
/**
* Create a new TextLinks.Builder.
@@ -622,13 +668,24 @@
}
/**
+ * Sets the extended data.
+ *
+ * @return this builder
+ */
+ public Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Constructs a TextLinks instance.
*
* @return the constructed TextLinks
*/
@NonNull
public TextLinks build() {
- return new TextLinks(mFullText, mLinks);
+ return new TextLinks(mFullText, mLinks,
+ mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
}
}
}
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 52d01ea..f236915 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -20,6 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,13 +42,16 @@
private final int mEndIndex;
private final EntityConfidence mEntityConfidence;
@Nullable private final String mId;
+ private final Bundle mExtras;
private TextSelection(
- int startIndex, int endIndex, Map<String, Float> entityConfidence, String id) {
+ int startIndex, int endIndex, Map<String, Float> entityConfidence, String id,
+ Bundle extras) {
mStartIndex = startIndex;
mEndIndex = endIndex;
mEntityConfidence = new EntityConfidence(entityConfidence);
mId = id;
+ mExtras = extras;
}
/**
@@ -103,6 +107,18 @@
return mId;
}
+ /**
+ * Returns the extended data.
+ *
+ * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+ * prefer to hold a reference to the returned bundle rather than frequently calling this
+ * method.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras.deepCopy();
+ }
+
@Override
public String toString() {
return String.format(
@@ -120,6 +136,8 @@
private final int mEndIndex;
private final Map<String, Float> mEntityConfidence = new ArrayMap<>();
@Nullable private String mId;
+ @Nullable
+ private Bundle mExtras;
/**
* Creates a builder used to build {@link TextSelection} objects.
@@ -160,12 +178,23 @@
}
/**
+ * Sets the extended data.
+ *
+ * @return this builder
+ */
+ public Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds and returns {@link TextSelection} object.
*/
@NonNull
public TextSelection build() {
return new TextSelection(
- mStartIndex, mEndIndex, mEntityConfidence, mId);
+ mStartIndex, mEndIndex, mEntityConfidence, mId,
+ mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
}
}
@@ -179,18 +208,21 @@
private final int mEndIndex;
@Nullable private final LocaleList mDefaultLocales;
private final boolean mDarkLaunchAllowed;
+ private final Bundle mExtras;
private Request(
CharSequence text,
int startIndex,
int endIndex,
LocaleList defaultLocales,
- boolean darkLaunchAllowed) {
+ boolean darkLaunchAllowed,
+ Bundle extras) {
mText = text;
mStartIndex = startIndex;
mEndIndex = endIndex;
mDefaultLocales = defaultLocales;
mDarkLaunchAllowed = darkLaunchAllowed;
+ mExtras = extras;
}
/**
@@ -238,6 +270,18 @@
}
/**
+ * Returns the extended data.
+ *
+ * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+ * prefer to hold a reference to the returned bundle rather than frequently calling this
+ * method.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras.deepCopy();
+ }
+
+ /**
* A builder for building TextSelection requests.
*/
public static final class Builder {
@@ -248,6 +292,7 @@
@Nullable private LocaleList mDefaultLocales;
private boolean mDarkLaunchAllowed;
+ private Bundle mExtras;
/**
* @param text text providing context for the selected text (which is specified by the
@@ -296,12 +341,23 @@
}
/**
+ * Sets the extended data.
+ *
+ * @return this builder
+ */
+ public Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds and returns the request object.
*/
@NonNull
public Request build() {
return new Request(mText, mStartIndex, mEndIndex,
- mDefaultLocales, mDarkLaunchAllowed);
+ mDefaultLocales, mDarkLaunchAllowed,
+ mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
}
}
@@ -319,6 +375,7 @@
if (mDefaultLocales != null) {
mDefaultLocales.writeToParcel(dest, flags);
}
+ dest.writeBundle(mExtras);
}
public static final Parcelable.Creator<Request> CREATOR =
@@ -340,6 +397,7 @@
mEndIndex = in.readInt();
mDefaultLocales = in.readInt() == 0 ? null : LocaleList.CREATOR.createFromParcel(in);
mDarkLaunchAllowed = false;
+ mExtras = in.readBundle();
}
}
@@ -354,6 +412,7 @@
dest.writeInt(mEndIndex);
mEntityConfidence.writeToParcel(dest, flags);
dest.writeString(mId);
+ dest.writeBundle(mExtras);
}
public static final Parcelable.Creator<TextSelection> CREATOR =
@@ -374,5 +433,6 @@
mEndIndex = in.readInt();
mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
mId = in.readString();
+ mExtras = in.readBundle();
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a93604f..c0979fe 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -196,12 +196,6 @@
private boolean mIsRoot = true;
/**
- * Optional theme resource id applied in inflateView(). When 0, Theme.DeviceDefault will be
- * used.
- */
- private int mApplyThemeResId;
-
- /**
* Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
* the layout in a way that isn't recoverable, since views are being removed.
*/
@@ -3262,14 +3256,6 @@
}
/**
- * Set the theme used in apply() and applyASync().
- * @hide
- */
- public void setApplyTheme(@StyleRes int themeResId) {
- mApplyThemeResId = themeResId;
- }
-
- /**
* Inflates the view hierarchy represented by this object and applies
* all of the actions.
*
@@ -3290,11 +3276,25 @@
View result = inflateView(context, rvToApply, parent);
rvToApply.performApply(result, parent, handler);
+ return result;
+ }
+ /** @hide */
+ public View applyWithTheme(Context context, ViewGroup parent, OnClickHandler handler,
+ @StyleRes int applyThemeResId) {
+ RemoteViews rvToApply = getRemoteViewsToApply(context);
+
+ View result = inflateView(context, rvToApply, parent, applyThemeResId);
+ rvToApply.performApply(result, parent, handler);
return result;
}
private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
+ return inflateView(context, rv, parent, 0);
+ }
+
+ private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
+ @StyleRes int applyThemeResId) {
// RemoteViews may be built by an application installed in another
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
@@ -3303,8 +3303,8 @@
Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
// If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
- if (mApplyThemeResId != 0) {
- inflationContext = new ContextThemeWrapper(inflationContext, mApplyThemeResId);
+ if (applyThemeResId != 0) {
+ inflationContext = new ContextThemeWrapper(inflationContext, applyThemeResId);
}
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 8bfc151..d55c09f 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1422,17 +1422,24 @@
@Override
public void onProvideStructure(ViewStructure structure) {
super.onProvideStructure(structure);
- onProvideAutoFillStructureForAssistOrAutofill(structure);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure);
}
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
- onProvideAutoFillStructureForAssistOrAutofill(structure);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure);
}
- // NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags
- private void onProvideAutoFillStructureForAssistOrAutofill(ViewStructure structure) {
+ @Override
+ public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+ final boolean notifyManager = super.onProvideContentCaptureStructure(structure, flags);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure);
+ return notifyManager;
+ }
+
+ // NOTE: currently there is no difference for any type, so it doesn't take flags
+ private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure) {
CharSequence switchText = isChecked() ? mTextOn : mTextOff;
if (!TextUtils.isEmpty(switchText)) {
CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 572670f..3bdd7b8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -166,6 +166,7 @@
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassificationContext;
import android.view.textclassifier.TextClassificationManager;
@@ -948,6 +949,9 @@
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
+ if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+ }
setTextInternal("");
@@ -6072,7 +6076,7 @@
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
} else {
- notifyAutoFillManagerAfterTextChanged();
+ notifyManagersAfterTextChanged();
}
// SelectionModifierCursorController depends on textCanBeSelected, which depends on text
@@ -10121,23 +10125,33 @@
}
// Always notify AutoFillManager - it will return right away if autofill is disabled.
- notifyAutoFillManagerAfterTextChanged();
+ notifyManagersAfterTextChanged();
hideErrorIfUnchanged();
}
- private void notifyAutoFillManagerAfterTextChanged() {
- // It is important to not check whether the view is important for autofill
- // since the user can trigger autofill manually on not important views.
- if (!isAutofillable()) {
- return;
- }
- final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
- if (afm != null) {
- if (android.view.autofill.Helper.sVerbose) {
- Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+ private void notifyManagersAfterTextChanged() {
+
+ // Autofill
+ if (isAutofillable()) {
+ // It is important to not check whether the view is important for autofill
+ // since the user can trigger autofill manually on not important views.
+ final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+ if (afm != null) {
+ if (android.view.autofill.Helper.sVerbose) {
+ Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+ }
+ afm.notifyValueChanged(TextView.this);
}
- afm.notifyValueChanged(TextView.this);
+ }
+
+ // ContentCapture
+ if (isImportantForContentCapture() && isTextEditable()) {
+ final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+ if (im != null && im.isContentCaptureEnabled()) {
+ // TODO(b/111276913): pass flags when edited by user / add CTS test
+ im.notifyViewTextChanged(getAutofillId(), getText(), /* flags= */ 0);
+ }
}
}
@@ -10900,21 +10914,33 @@
@Override
public void onProvideStructure(ViewStructure structure) {
super.onProvideStructure(structure);
- onProvideAutoStructureForAssistOrAutofill(structure, false);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
+ /* forViewCapture= */ false);
}
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
- onProvideAutoStructureForAssistOrAutofill(structure, true);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ true,
+ /* forViewCapture= */ false);
}
- private void onProvideAutoStructureForAssistOrAutofill(ViewStructure structure,
- boolean forAutofill) {
+ @Override
+ public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+ final boolean notifyManager = super.onProvideContentCaptureStructure(structure, flags);
+ onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
+ /* forViewCapture= */ true);
+ return notifyManager;
+ }
+
+ private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure,
+ boolean forAutofill, boolean forViewCapture) {
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (forAutofill) {
- structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+ if (forAutofill || forViewCapture) {
+ if (forAutofill) {
+ structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+ }
if (mTextId != ResourceId.ID_NULL) {
try {
structure.setTextIdEntry(getResources().getResourceEntryName(mTextId));
@@ -10927,7 +10953,7 @@
}
}
- if (!isPassword || forAutofill) {
+ if (!isPassword || forAutofill || forViewCapture) {
if (mLayout == null) {
assumeLayout();
}
@@ -11043,7 +11069,8 @@
// of the View (and can be any drawable) or a BackgroundColorSpan inside the text.
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
- } else {
+ }
+ if (forAutofill || forViewCapture) {
structure.setMinTextEms(getMinEms());
structure.setMaxTextEms(getMaxEms());
int maxLength = -1;
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9b8f120..604537f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -142,7 +142,7 @@
// Used to show the dialog when BiometricService starts authentication
void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation);
+ boolean requireConfirmation, int userId);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f2002..9a7094a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -92,7 +92,7 @@
// Used to show the dialog when BiometricService starts authentication
void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation);
+ boolean requireConfirmation, int userId);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
// Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index c977437..29051f1 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -892,6 +892,13 @@
cfaOut[3] = 0;
break;
}
+ // MONO and NIR are degenerate case of RGGB pattern: only Red channel
+ // will be used.
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO:
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR: {
+ cfaOut[0] = 0;
+ break;
+ }
default: {
return BAD_VALUE;
}
@@ -1063,6 +1070,8 @@
uint32_t preWidth = 0;
uint32_t preHeight = 0;
+ uint8_t colorFilter = 0;
+ bool isBayer = true;
{
// Check dimensions
camera_metadata_entry entry =
@@ -1083,10 +1092,25 @@
"either the preCorrectionActiveArraySize or the pixelArraySize.");
return nullptr;
}
+
+ camera_metadata_entry colorFilterEntry =
+ characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+ colorFilter = colorFilterEntry.data.u8[0];
+ camera_metadata_entry capabilitiesEntry =
+ characteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+ size_t capsCount = capabilitiesEntry.count;
+ uint8_t* caps = capabilitiesEntry.data.u8;
+ if (std::find(caps, caps+capsCount, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME)
+ != caps+capsCount) {
+ isBayer = false;
+ } else if (colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO ||
+ colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR) {
+ jniThrowException(env, "java/lang/AssertionError",
+ "A camera device with MONO/NIR color filter must have MONOCHROME capability.");
+ return nullptr;
+ }
}
-
-
writer->addIfd(TIFF_IFD_0);
status_t err = OK;
@@ -1094,9 +1118,12 @@
const uint32_t samplesPerPixel = 1;
const uint32_t bitsPerSample = BITS_PER_SAMPLE;
- OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+ OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_NONE;
uint8_t cfaPlaneColor[3] = {0, 1, 2};
- uint8_t cfaEnum = -1;
+ camera_metadata_entry cfaEntry =
+ characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+ BAIL_IF_EMPTY_RET_NULL_SP(cfaEntry, env, TAG_CFAPATTERN, writer);
+ uint8_t cfaEnum = cfaEntry.data.u8[0];
// TODO: Greensplit.
// TODO: Add remaining non-essential tags
@@ -1141,12 +1168,20 @@
{
// Set photometric interpretation
- uint16_t interpretation = 32803; // CFA
+ uint16_t interpretation = isBayer ? 32803 /* CFA */ :
+ 34892; /* Linear Raw */;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1,
&interpretation, TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer);
}
{
+ uint16_t repeatDim[2] = {2, 2};
+ if (!isBayer) {
+ repeatDim[0] = repeatDim[1] = 1;
+ }
+ BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
+ TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+
// Set blacklevel tags, using dynamic black level if available
camera_metadata_entry entry =
results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
@@ -1165,14 +1200,9 @@
blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
blackLevelRational[i * 2 + 1] = 1;
}
-
}
- BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
- TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
-
- uint16_t repeatDim[2] = {2, 2};
- BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
- TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+ BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, repeatDim[0]*repeatDim[1],
+ blackLevelRational, TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
}
{
@@ -1189,21 +1219,15 @@
TIFF_IFD_0), env, TAG_PLANARCONFIGURATION, writer);
}
- {
+ // All CFA pattern tags are not necessary for monochrome cameras.
+ if (isBayer) {
// Set CFA pattern dimensions
uint16_t repeatDim[2] = {2, 2};
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim,
TIFF_IFD_0), env, TAG_CFAREPEATPATTERNDIM, writer);
- }
- {
// Set CFA pattern
- camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
- BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_CFAPATTERN, writer);
-
const int cfaLength = 4;
- cfaEnum = entry.data.u8[0];
uint8_t cfa[cfaLength];
if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) {
jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
@@ -1214,15 +1238,11 @@
env, TAG_CFAPATTERN, writer);
opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum);
- }
- {
// Set CFA plane color
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor,
TIFF_IFD_0), env, TAG_CFAPLANECOLOR, writer);
- }
- {
// Set CFA layout
uint16_t cfaLayout = 1;
BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
@@ -1442,7 +1462,7 @@
}
bool singleIlluminant = false;
- {
+ if (isBayer) {
// Set calibration illuminants
camera_metadata_entry entry1 =
characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
@@ -1464,7 +1484,7 @@
}
}
- {
+ if (isBayer) {
// Set color transforms
camera_metadata_entry entry1 =
characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
@@ -1497,7 +1517,7 @@
}
}
- {
+ if (isBayer) {
// Set calibration transforms
camera_metadata_entry entry1 =
characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
@@ -1531,7 +1551,7 @@
}
}
- {
+ if (isBayer) {
// Set forward transforms
camera_metadata_entry entry1 =
characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
@@ -1565,7 +1585,7 @@
}
}
- {
+ if (isBayer) {
// Set camera neutral
camera_metadata_entry entry =
results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
@@ -1632,8 +1652,8 @@
camera_metadata_entry entry =
results.find(ANDROID_SENSOR_NOISE_PROFILE);
- const status_t numPlaneColors = 3;
- const status_t numCfaChannels = 4;
+ const status_t numPlaneColors = isBayer ? 3 : 1;
+ const status_t numCfaChannels = isBayer ? 4 : 1;
uint8_t cfaOut[numCfaChannels];
if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
@@ -1710,42 +1730,44 @@
}
}
+ // Hot pixel map is specific to bayer camera per DNG spec.
+ if (isBayer) {
+ // Set up bad pixel correction list
+ camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
- // Set up bad pixel correction list
- camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
-
- if ((entry3.count % 2) != 0) {
- ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
- __FUNCTION__);
- jniThrowRuntimeException(env, "failed to add hotpixel map.");
- return nullptr;
- }
-
- // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
- std::vector<uint32_t> v;
- for (size_t i = 0; i < entry3.count; i += 2) {
- int32_t x = entry3.data.i32[i];
- int32_t y = entry3.data.i32[i + 1];
- x -= static_cast<int32_t>(xmin);
- y -= static_cast<int32_t>(ymin);
- if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
- static_cast<uint32_t>(y) >= height) {
- continue;
- }
- v.push_back(x);
- v.push_back(y);
- }
- const uint32_t* badPixels = &v[0];
- uint32_t badPixelCount = v.size();
-
- if (badPixelCount > 0) {
- err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
-
- if (err != OK) {
- ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+ if ((entry3.count % 2) != 0) {
+ ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
+ __FUNCTION__);
jniThrowRuntimeException(env, "failed to add hotpixel map.");
return nullptr;
}
+
+ // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
+ std::vector<uint32_t> v;
+ for (size_t i = 0; i < entry3.count; i += 2) {
+ int32_t x = entry3.data.i32[i];
+ int32_t y = entry3.data.i32[i + 1];
+ x -= static_cast<int32_t>(xmin);
+ y -= static_cast<int32_t>(ymin);
+ if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
+ static_cast<uint32_t>(y) >= height) {
+ continue;
+ }
+ v.push_back(x);
+ v.push_back(y);
+ }
+ const uint32_t* badPixels = &v[0];
+ uint32_t badPixelCount = v.size();
+
+ if (badPixelCount > 0) {
+ err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
+
+ if (err != OK) {
+ ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+ jniThrowRuntimeException(env, "failed to add hotpixel map.");
+ return nullptr;
+ }
+ }
}
if (builder.getCount() > 0) {
@@ -1960,10 +1982,12 @@
tagsToMove.add(TAG_BLACKLEVELREPEATDIM);
tagsToMove.add(TAG_SAMPLESPERPIXEL);
tagsToMove.add(TAG_PLANARCONFIGURATION);
- tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
- tagsToMove.add(TAG_CFAPATTERN);
- tagsToMove.add(TAG_CFAPLANECOLOR);
- tagsToMove.add(TAG_CFALAYOUT);
+ if (isBayer) {
+ tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
+ tagsToMove.add(TAG_CFAPATTERN);
+ tagsToMove.add(TAG_CFAPLANECOLOR);
+ tagsToMove.add(TAG_CFALAYOUT);
+ }
tagsToMove.add(TAG_XRESOLUTION);
tagsToMove.add(TAG_YRESOLUTION);
tagsToMove.add(TAG_RESOLUTIONUNIT);
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index b3ff4db..b708735 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -175,7 +175,7 @@
}
}
s.tag = rawTag >> 32;
- if (limitTag != -1 && s.tag != limitTag) {
+ if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
//ALOGI("skipping due to tag: %s", buffer);
continue;
}
@@ -188,7 +188,7 @@
if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
&s.uid, &s.set, &s.rxBytes, &s.rxPackets,
&s.txBytes, &s.txPackets) == 6) {
- if (limitUid != -1 && limitUid != s.uid) {
+ if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
//ALOGI("skipping due to uid: %s", buffer);
continue;
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 72892fa..7de8020 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -332,6 +332,18 @@
}
optional Dropbox dropbox = 46;
+ message DynamicPowerSavings {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // When to auto disable interventions that were triggered due to
+ // {@link #DYNAMIC_POWER_SAVINGS_ENABLED}. Value is a percentage indicating
+ // a battery level.
+ optional SettingProto disable_threshold = 1 [ (android.privacy).dest = DEST_AUTOMATIC];
+ // Whether dynamic power savings based behaviors should be running or not.
+ optional SettingProto enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC];
+ }
+ optional DynamicPowerSavings dynamic_power_savings = 143;
+
message Emergency {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -491,6 +503,9 @@
// The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting
// is not set or the value is 0, the default max will be used.
optional SettingProto trigger_level_max = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // Whether automatic battery saver mode is controlled via percentage,
+ // {@link #DYNAMIC_POWER_SAVINGS_ENABLED} or disabled.
+ optional SettingProto automatic_power_saver_mode = 4 [ (android.privacy).dest = DEST_AUTOMATIC];
}
optional LowPowerMode low_power_mode = 70;
@@ -972,5 +987,5 @@
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 143;
+ // Next tag = 144;
}
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
index 941c81f..3d60a86 100644
--- a/core/proto/android/server/usagestatsservice.proto
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -45,11 +45,15 @@
optional string package = 1;
// package_index contains the index + 1 of the package name in the string pool
optional int32 package_index = 2;
+ // Time attributes stored as an offset of the IntervalStats's beginTime.
optional int64 last_time_active_ms = 3;
optional int64 total_time_active_ms = 4;
optional int32 last_event = 5;
optional int32 app_launch_count = 6;
repeated ChooserAction chooser_actions = 7;
+ // Time attributes stored as an offset of the IntervalStats's beginTime.
+ optional int64 last_time_service_used_ms = 8;
+ optional int64 total_time_service_used_ms = 9;
}
// Stores the relevant information an IntervalStats will have about a Configuration
@@ -86,6 +90,8 @@
// stringpool contains all the package and class names used by UsageStats and Event
// They will hold a number that is equal to the index + 1 of their string in the pool
optional StringPool stringpool = 2;
+ optional int32 major_version = 3;
+ optional int32 minor_version = 4;
// The following fields contain aggregated usage stats data
optional CountAndTime interactive = 10;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 68ec342..a99b942 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2448,6 +2448,25 @@
<flag name="noExcludeDescendants" value="0x8" />
</attr>
+ <!-- Hints the Android System whether the view node associated with this View should be
+ use for content capture purposes. -->
+ <attr name="importantForContentCapture">
+ <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
+ <flag name="auto" value="0" />
+ <!-- Hint the Android System that this view is important for content capture,
+ and its children (if any) will be traversed.. -->
+ <flag name="yes" value="0x1" />
+ <!-- Hint the Android System that this view is *not* important for content capture,
+ but its children (if any) will be traversed.. -->
+ <flag name="no" value="0x2" />
+ <!-- Hint the Android System that this view is important for content capture,
+ but its children (if any) will not be traversed. -->
+ <flag name="yesExcludeDescendants" value="0x4" />
+ <!-- Hint the Android System that this view is *not* important for content capture,
+ and its children (if any) will not be traversed. -->
+ <flag name="noExcludeDescendants" value="0x8" />
+ </attr>
+
<!-- Boolean that controls whether a view can take focus while in touch mode.
If this is true for a view, that view can gain focus when clicked on, and can keep
focus if another view is clicked on that doesn't have this attribute set to true. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6ae183b..26f3370 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3531,6 +3531,9 @@
<!-- Whether or not battery saver should be "sticky" when manually enabled. -->
<bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
+ <!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. -->
+ <integer name="config_dynamicPowerSavingsDefaultDisableThreshold">80</integer>
+
<!-- Model of potentially misprovisioned devices. If none is specified in an overlay, an
empty string is passed in. -->
<string name="config_misprovisionedDeviceModel" translatable="false"></string>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 35eee6a..d6c0a10 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -23,80 +23,81 @@
<item>ak-GH</item> <!-- Akan (Ghana) -->
<item>am-ET</item> <!-- Amharic (Ethiopia) -->
<item>ar-AE</item> <!-- Arabic (United Arab Emirates) -->
- <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates,Western Digits) -->
+ <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates, Western Digits) -->
<item>ar-BH</item> <!-- Arabic (Bahrain) -->
- <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain,Western Digits) -->
+ <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain, Western Digits) -->
<item>ar-DJ</item> <!-- Arabic (Djibouti) -->
- <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti,Western Digits) -->
+ <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti, Western Digits) -->
<item>ar-DZ</item> <!-- Arabic (Algeria) -->
- <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria,Arabic-Indic Digits) -->
+ <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria, Arabic-Indic Digits) -->
<item>ar-EG</item> <!-- Arabic (Egypt) -->
- <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt,Western Digits) -->
+ <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt, Western Digits) -->
<item>ar-EH</item> <!-- Arabic (Western Sahara) -->
- <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara,Arabic-Indic Digits) -->
+ <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara, Arabic-Indic Digits) -->
<item>ar-ER</item> <!-- Arabic (Eritrea) -->
- <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea,Western Digits) -->
+ <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea, Western Digits) -->
<item>ar-IL</item> <!-- Arabic (Israel) -->
- <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel,Western Digits) -->
+ <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel, Western Digits) -->
<item>ar-IQ</item> <!-- Arabic (Iraq) -->
- <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq,Western Digits) -->
+ <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq, Western Digits) -->
<item>ar-JO</item> <!-- Arabic (Jordan) -->
- <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan,Western Digits) -->
+ <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan, Western Digits) -->
<item>ar-KM</item> <!-- Arabic (Comoros) -->
- <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros,Western Digits) -->
+ <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros, Western Digits) -->
<item>ar-KW</item> <!-- Arabic (Kuwait) -->
- <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait,Western Digits) -->
+ <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait, Western Digits) -->
<item>ar-LB</item> <!-- Arabic (Lebanon) -->
- <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon,Western Digits) -->
+ <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon, Western Digits) -->
<item>ar-LY</item> <!-- Arabic (Libya) -->
- <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya,Arabic-Indic Digits) -->
+ <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya, Arabic-Indic Digits) -->
<item>ar-MA</item> <!-- Arabic (Morocco) -->
- <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco,Arabic-Indic Digits) -->
+ <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco, Arabic-Indic Digits) -->
<item>ar-MR</item> <!-- Arabic (Mauritania) -->
- <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania,Western Digits) -->
+ <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania, Western Digits) -->
<item>ar-OM</item> <!-- Arabic (Oman) -->
- <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman,Western Digits) -->
+ <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman, Western Digits) -->
<item>ar-PS</item> <!-- Arabic (Palestine) -->
- <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine,Western Digits) -->
+ <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine, Western Digits) -->
<item>ar-QA</item> <!-- Arabic (Qatar) -->
- <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar,Western Digits) -->
+ <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar, Western Digits) -->
<item>ar-SA</item> <!-- Arabic (Saudi Arabia) -->
- <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia,Western Digits) -->
+ <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia, Western Digits) -->
<item>ar-SD</item> <!-- Arabic (Sudan) -->
- <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan,Western Digits) -->
+ <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan, Western Digits) -->
<item>ar-SO</item> <!-- Arabic (Somalia) -->
- <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia,Western Digits) -->
+ <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia, Western Digits) -->
<item>ar-SS</item> <!-- Arabic (South Sudan) -->
- <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan,Western Digits) -->
+ <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan, Western Digits) -->
<item>ar-SY</item> <!-- Arabic (Syria) -->
- <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria,Western Digits) -->
+ <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria, Western Digits) -->
<item>ar-TD</item> <!-- Arabic (Chad) -->
- <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad,Western Digits) -->
+ <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad, Western Digits) -->
<item>ar-TN</item> <!-- Arabic (Tunisia) -->
- <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia,Arabic-Indic Digits) -->
+ <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia, Arabic-Indic Digits) -->
<item>ar-XB</item> <!-- Right-to-left pseudolocale -->
<item>ar-YE</item> <!-- Arabic (Yemen) -->
- <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen,Western Digits) -->
+ <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
<item>as-IN</item> <!-- Assamese (India) -->
<item>asa-TZ</item> <!-- Asu (Tanzania) -->
- <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) -->
- <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin,Azerbaijan) -->
+ <item>ast-ES</item> <!-- Asturian (Spain) -->
+ <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
+ <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin, Azerbaijan) -->
<item>bas-CM</item> <!-- Basaa (Cameroon) -->
<item>be-BY</item> <!-- Belarusian (Belarus) -->
<item>bem-ZM</item> <!-- Bemba (Zambia) -->
<item>bez-TZ</item> <!-- Bena (Tanzania) -->
<item>bg-BG</item> <!-- Bulgarian (Bulgaria) -->
<item>bm-ML</item> <!-- Bambara (Mali) -->
- <item>bn-BD</item> <!-- Bengali (Bangladesh) -->
- <item>bn-BD-u-nu-latn</item> <!-- Bengali (Bangladesh,Western Digits) -->
- <item>bn-IN</item> <!-- Bengali (India) -->
- <item>bn-IN-u-nu-latn</item> <!-- Bengali (India,Western Digits) -->
+ <item>bn-BD</item> <!-- Bangla (Bangladesh) -->
+ <item>bn-BD-u-nu-latn</item> <!-- Bangla (Bangladesh, Western Digits) -->
+ <item>bn-IN</item> <!-- Bangla (India) -->
+ <item>bn-IN-u-nu-latn</item> <!-- Bangla (India, Western Digits) -->
<item>bo-CN</item> <!-- Tibetan (China) -->
<item>bo-IN</item> <!-- Tibetan (India) -->
<item>br-FR</item> <!-- Breton (France) -->
<item>brx-IN</item> <!-- Bodo (India) -->
- <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic,Bosnia & Herzegovina) -->
- <item>bs-Latn-BA</item> <!-- Bosnian (Latin,Bosnia & Herzegovina) -->
+ <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic, Bosnia & Herzegovina) -->
+ <item>bs-Latn-BA</item> <!-- Bosnian (Latin, Bosnia & Herzegovina) -->
<item>ca-AD</item> <!-- Catalan (Andorra) -->
<item>ca-ES</item> <!-- Catalan (Spain) -->
<item>ca-FR</item> <!-- Catalan (France) -->
@@ -113,6 +114,7 @@
<item>de-BE</item> <!-- German (Belgium) -->
<item>de-CH</item> <!-- German (Switzerland) -->
<item>de-DE</item> <!-- German (Germany) -->
+ <item>de-IT</item> <!-- German (Italy) -->
<item>de-LI</item> <!-- German (Liechtenstein) -->
<item>de-LU</item> <!-- German (Luxembourg) -->
<item>dje-NE</item> <!-- Zarma (Niger) -->
@@ -230,6 +232,8 @@
<item>en-ZW</item> <!-- English (Zimbabwe) -->
<item>es-AR</item> <!-- Spanish (Argentina) -->
<item>es-BO</item> <!-- Spanish (Bolivia) -->
+ <item>es-BR</item> <!-- Spanish (Brazil) -->
+ <item>es-BZ</item> <!-- Spanish (Belize) -->
<item>es-CL</item> <!-- Spanish (Chile) -->
<item>es-CO</item> <!-- Spanish (Colombia) -->
<item>es-CR</item> <!-- Spanish (Costa Rica) -->
@@ -257,9 +261,9 @@
<item>eu-ES</item> <!-- Basque (Spain) -->
<item>ewo-CM</item> <!-- Ewondo (Cameroon) -->
<item>fa-AF</item> <!-- Persian (Afghanistan) -->
- <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan,Western Digits) -->
+ <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan, Western Digits) -->
<item>fa-IR</item> <!-- Persian (Iran) -->
- <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran,Western Digits) -->
+ <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran, Western Digits) -->
<item>ff-CM</item> <!-- Fulah (Cameroon) -->
<item>ff-GN</item> <!-- Fulah (Guinea) -->
<item>ff-MR</item> <!-- Fulah (Mauritania) -->
@@ -274,9 +278,9 @@
<item>fr-BJ</item> <!-- French (Benin) -->
<item>fr-BL</item> <!-- French (St. Barthélemy) -->
<item>fr-CA</item> <!-- French (Canada) -->
- <item>fr-CD</item> <!-- French (Congo (DRC)) -->
+ <item>fr-CD</item> <!-- French (Congo - Kinshasa) -->
<item>fr-CF</item> <!-- French (Central African Republic) -->
- <item>fr-CG</item> <!-- French (Congo (Republic)) -->
+ <item>fr-CG</item> <!-- French (Congo - Brazzaville) -->
<item>fr-CH</item> <!-- French (Switzerland) -->
<item>fr-CI</item> <!-- French (Côte d’Ivoire) -->
<item>fr-CM</item> <!-- French (Cameroon) -->
@@ -329,20 +333,20 @@
<item>ha-NE</item> <!-- Hausa (Niger) -->
<item>ha-NG</item> <!-- Hausa (Nigeria) -->
<item>haw-US</item> <!-- Hawaiian (United States) -->
- <item>iw-IL</item> <!-- Hebrew (Israel) -->
<item>hi-IN</item> <!-- Hindi (India) -->
<item>hr-BA</item> <!-- Croatian (Bosnia & Herzegovina) -->
<item>hr-HR</item> <!-- Croatian (Croatia) -->
<item>hsb-DE</item> <!-- Upper Sorbian (Germany) -->
<item>hu-HU</item> <!-- Hungarian (Hungary) -->
<item>hy-AM</item> <!-- Armenian (Armenia) -->
- <item>in-ID</item> <!-- Indonesian (Indonesia) -->
<item>ig-NG</item> <!-- Igbo (Nigeria) -->
<item>ii-CN</item> <!-- Sichuan Yi (China) -->
+ <item>in-ID</item> <!-- Indonesian (Indonesia) -->
<item>is-IS</item> <!-- Icelandic (Iceland) -->
<item>it-CH</item> <!-- Italian (Switzerland) -->
<item>it-IT</item> <!-- Italian (Italy) -->
<item>it-SM</item> <!-- Italian (San Marino) -->
+ <item>iw-IL</item> <!-- Hebrew (Israel) -->
<item>ja-JP</item> <!-- Japanese (Japan) -->
<item>jgo-CM</item> <!-- Ngomba (Cameroon) -->
<item>jmc-TZ</item> <!-- Machame (Tanzania) -->
@@ -372,12 +376,12 @@
<item>lg-UG</item> <!-- Ganda (Uganda) -->
<item>lkt-US</item> <!-- Lakota (United States) -->
<item>ln-AO</item> <!-- Lingala (Angola) -->
- <item>ln-CD</item> <!-- Lingala (Congo (DRC)) -->
+ <item>ln-CD</item> <!-- Lingala (Congo - Kinshasa) -->
<item>ln-CF</item> <!-- Lingala (Central African Republic) -->
- <item>ln-CG</item> <!-- Lingala (Congo (Republic)) -->
+ <item>ln-CG</item> <!-- Lingala (Congo - Brazzaville) -->
<item>lo-LA</item> <!-- Lao (Laos) -->
<item>lt-LT</item> <!-- Lithuanian (Lithuania) -->
- <item>lu-CD</item> <!-- Luba-Katanga (Congo (DRC)) -->
+ <item>lu-CD</item> <!-- Luba-Katanga (Congo - Kinshasa) -->
<item>luo-KE</item> <!-- Luo (Kenya) -->
<item>luy-KE</item> <!-- Luyia (Kenya) -->
<item>lv-LV</item> <!-- Latvian (Latvia) -->
@@ -418,11 +422,11 @@
<item>nyn-UG</item> <!-- Nyankole (Uganda) -->
<item>om-ET</item> <!-- Oromo (Ethiopia) -->
<item>om-KE</item> <!-- Oromo (Kenya) -->
- <item>or-IN</item> <!-- Oriya (India) -->
+ <item>or-IN</item> <!-- Odia (India) -->
<item>os-GE</item> <!-- Ossetic (Georgia) -->
<item>os-RU</item> <!-- Ossetic (Russia) -->
- <item>pa-Arab-PK</item> <!-- Punjabi (Arabic,Pakistan) -->
- <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi,India) -->
+ <item>pa-Arab-PK</item> <!-- Punjabi (Arabic, Pakistan) -->
+ <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi, India) -->
<item>pl-PL</item> <!-- Polish (Poland) -->
<item>ps-AF</item> <!-- Pashto (Afghanistan) -->
<item>pt-AO</item> <!-- Portuguese (Angola) -->
@@ -471,18 +475,18 @@
<item>sq-AL</item> <!-- Albanian (Albania) -->
<item>sq-MK</item> <!-- Albanian (Macedonia (FYROM)) -->
<item>sq-XK</item> <!-- Albanian (Kosovo) -->
- <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic,Bosnia & Herzegovina) -->
- <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic,Montenegro) -->
- <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic,Serbia) -->
- <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic,Kosovo) -->
- <item>sr-Latn-BA</item> <!-- Serbian (Latin,Bosnia & Herzegovina) -->
- <item>sr-Latn-ME</item> <!-- Serbian (Latin,Montenegro) -->
- <item>sr-Latn-RS</item> <!-- Serbian (Latin,Serbia) -->
- <item>sr-Latn-XK</item> <!-- Serbian (Latin,Kosovo) -->
+ <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic, Bosnia & Herzegovina) -->
+ <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic, Montenegro) -->
+ <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic, Serbia) -->
+ <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic, Kosovo) -->
+ <item>sr-Latn-BA</item> <!-- Serbian (Latin, Bosnia & Herzegovina) -->
+ <item>sr-Latn-ME</item> <!-- Serbian (Latin, Montenegro) -->
+ <item>sr-Latn-RS</item> <!-- Serbian (Latin, Serbia) -->
+ <item>sr-Latn-XK</item> <!-- Serbian (Latin, Kosovo) -->
<item>sv-AX</item> <!-- Swedish (Åland Islands) -->
<item>sv-FI</item> <!-- Swedish (Finland) -->
<item>sv-SE</item> <!-- Swedish (Sweden) -->
- <item>sw-CD</item> <!-- Swahili (Congo (DRC)) -->
+ <item>sw-CD</item> <!-- Swahili (Congo - Kinshasa) -->
<item>sw-KE</item> <!-- Swahili (Kenya) -->
<item>sw-TZ</item> <!-- Swahili (Tanzania) -->
<item>sw-UG</item> <!-- Swahili (Uganda) -->
@@ -502,12 +506,12 @@
<item>ug-CN</item> <!-- Uyghur (China) -->
<item>uk-UA</item> <!-- Ukrainian (Ukraine) -->
<item>ur-IN</item> <!-- Urdu (India) -->
- <item>ur-IN-u-nu-latn</item> <!-- Urdu (India,Western Digits) -->
+ <item>ur-IN-u-nu-latn</item> <!-- Urdu (India, Western Digits) -->
<item>ur-PK</item> <!-- Urdu (Pakistan) -->
- <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan,Extended Arabic-Indic Digits) -->
- <item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) -->
- <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) -->
- <item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) -->
+ <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan, Extended Arabic-Indic Digits) -->
+ <item>uz-Arab-AF</item> <!-- Uzbek (Arabic, Afghanistan) -->
+ <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic, Uzbekistan) -->
+ <item>uz-Latn-UZ</item> <!-- Uzbek (Latin, Uzbekistan) -->
<item>vi-VN</item> <!-- Vietnamese (Vietnam) -->
<item>vun-TZ</item> <!-- Vunjo (Tanzania) -->
<item>wae-CH</item> <!-- Walser (Switzerland) -->
@@ -515,15 +519,16 @@
<item>yav-CM</item> <!-- Yangben (Cameroon) -->
<item>yo-BJ</item> <!-- Yoruba (Benin) -->
<item>yo-NG</item> <!-- Yoruba (Nigeria) -->
- <item>yue-HK</item> <!-- Cantonese (Hong Kong) -->
+ <item>yue-Hans-CN</item> <!-- Cantonese (Simplified, China) -->
+ <item>yue-Hant-HK</item> <!-- Cantonese (Traditional, Hong Kong) -->
<item>zgh-MA</item> <!-- Standard Moroccan Tamazight (Morocco) -->
- <item>zh-Hans-CN</item> <!-- Chinese (Simplified Han,China) -->
- <item>zh-Hans-HK</item> <!-- Chinese (Simplified Han,Hong Kong) -->
- <item>zh-Hans-MO</item> <!-- Chinese (Simplified Han,Macau) -->
- <item>zh-Hans-SG</item> <!-- Chinese (Simplified Han,Singapore) -->
- <item>zh-Hant-HK</item> <!-- Chinese (Traditional Han,Hong Kong) -->
- <item>zh-Hant-MO</item> <!-- Chinese (Traditional Han,Macau) -->
- <item>zh-Hant-TW</item> <!-- Chinese (Traditional Han,Taiwan) -->
+ <item>zh-Hans-CN</item> <!-- Chinese (Simplified, China) -->
+ <item>zh-Hans-HK</item> <!-- Chinese (Simplified, Hong Kong) -->
+ <item>zh-Hans-MO</item> <!-- Chinese (Simplified, Macau) -->
+ <item>zh-Hans-SG</item> <!-- Chinese (Simplified, Singapore) -->
+ <item>zh-Hant-HK</item> <!-- Chinese (Traditional, Hong Kong) -->
+ <item>zh-Hant-MO</item> <!-- Chinese (Traditional, Macau) -->
+ <item>zh-Hant-TW</item> <!-- Chinese (Traditional, Taiwan) -->
<item>zu-ZA</item> <!-- Zulu (South Africa) -->
</string-array>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 86879c3..73dae08 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2919,6 +2919,7 @@
<public name="settingsSliceUri" />
<public name="shell" />
<public name="interactiveUiTimeout" />
+ <public name="importantForContentCapture" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6276884..4eb723e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3436,6 +3436,7 @@
<java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
<java-symbol type="bool" name="config_batterySaverStickyBehaviourDisabled" />
+ <java-symbol type="integer" name="config_dynamicPowerSavingsDefaultDisableThreshold" />
<!-- For car devices -->
<java-symbol type="string" name="car_loading_profile" />
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index c6d077d..1f047f9e 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -16,8 +16,19 @@
package android.app.usage;
-import static com.google.common.truth.Truth.assertThat;
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -46,7 +57,7 @@
left.add(right);
- assertThat(left.getFirstTimeStamp()).isEqualTo(99999);
+ assertEquals(left.getFirstTimeStamp(), 99999);
}
@Test
@@ -58,7 +69,7 @@
left.add(right);
- assertThat(left.getLastTimeStamp()).isEqualTo(100001);
+ assertEquals(left.getLastTimeStamp(), 100001);
}
@Test
@@ -72,7 +83,7 @@
left.add(right);
- assertThat(left.getLastTimeUsed()).isEqualTo(200001);
+ assertEquals(left.getLastTimeUsed(), 200001);
}
@Test
@@ -86,7 +97,7 @@
left.add(right);
- assertThat(left.getLastTimeUsed()).isEqualTo(200000);
+ assertEquals(left.getLastTimeUsed(), 200000);
}
@Test
@@ -100,6 +111,373 @@
left.add(right);
- assertThat(left.getTotalTimeInForeground()).isEqualTo(11);
+ assertEquals(left.getTotalTimeInForeground(), 11);
+ }
+
+ @Test
+ public void testParcelable() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+ left.mTotalTimeInForeground = 10;
+
+ left.mLastForegroundActivityEventMap.put("com.test.activity1", MOVE_TO_FOREGROUND);
+ left.mLastForegroundActivityEventMap.put("com.test.activity2", MOVE_TO_FOREGROUND);
+ left.mLastForegroundServiceEventMap.put("com.test.service1", FOREGROUND_SERVICE_START);
+ left.mLastForegroundServiceEventMap.put("com.test.service2", FOREGROUND_SERVICE_START);
+
+ Parcel p = Parcel.obtain();
+ left.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ right = UsageStats.CREATOR.createFromParcel(p);
+ compareUsageStats(left, right);
+ }
+
+ @Test
+ public void testForegroundActivity() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+ assertEquals(left.mLastTimeUsed, 200000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(MOVE_TO_FOREGROUND));
+ assertEquals(left.mLaunchCount, 1);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertFalse(left.mLastForegroundActivityEventMap.containsKey("com.test.activity1"));
+ assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
+ }
+
+ @Test
+ public void testEvent_CONTINUE_PREVIOUS_DAY() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+ }
+
+ @Test
+ public void testEvent_END_OF_DAY() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update(null, 350000, END_OF_DAY);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(END_OF_DAY));
+ assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+ }
+
+ @Test
+ public void testForegroundActivityEventSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+ left.update("com.test.activity1", 450000, MOVE_TO_FOREGROUND);
+ assertEquals(left.mLastTimeUsed, 450000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(MOVE_TO_FOREGROUND));
+ assertEquals(left.mTotalTimeInForeground, 250000);
+
+ left.update("com.test.activity1", 500000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 500000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 + 50000 /*500000 - 450000*/);
+ }
+
+ @Test
+ public void testForegroundActivityEventOutOfSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.activity1", 150000, MOVE_TO_FOREGROUND);
+ assertEquals(left.mLastTimeUsed, 150000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(MOVE_TO_FOREGROUND));
+ assertEquals(left.mLaunchCount, 1);
+ assertEquals(left.mTotalTimeInForeground, 50000 /*150000 - 100000*/);
+
+ left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+ assertEquals(left.mLastTimeUsed, 200000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(MOVE_TO_FOREGROUND));
+ assertEquals(left.mLaunchCount, 2);
+ assertEquals(left.mTotalTimeInForeground, 100000);
+
+ left.update("com.test.activity1", 250000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 250000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 150000);
+
+ left.update("com.test.activity1", 300000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 250000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 150000);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_FOREGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(MOVE_TO_FOREGROUND));
+ assertEquals(left.mTotalTimeInForeground, 150000);
+
+ left.update("com.test.activity1", 400000, END_OF_DAY);
+ assertEquals(left.mLastTimeUsed, 400000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(END_OF_DAY));
+ assertEquals(left.mTotalTimeInForeground, 200000);
+ }
+
+ @Test
+ public void testTwoActivityEventSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+ left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 450000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+ left.update(null, 500000, END_OF_DAY);
+ assertEquals(left.mLastTimeUsed, 450000);
+ assertEquals(left.mTotalTimeInForeground, 350000);
+ }
+
+ @Test
+ public void testForegroundService() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.service1", 200000, FOREGROUND_SERVICE_START);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 200000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(FOREGROUND_SERVICE_START));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 200000);
+ }
+
+ @Test
+ public void testEvent_CONTINUING_FOREGROUND_SERVICE() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.service1", 100000, CONTINUING_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+ }
+
+ @Test
+ public void testEvent_ROLLOVER_FOREGROUND_SERVICE() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.service1", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update(null, 350000, ROLLOVER_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(ROLLOVER_FOREGROUND_SERVICE));
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+ }
+
+ @Test
+ public void testForegroundServiceEventSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.service1", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+ left.update("com.test.service1", 450000, FOREGROUND_SERVICE_START);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(FOREGROUND_SERVICE_START));
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 250000);
+
+ left.update("com.test.service1", 500000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 50000 /*500000 - 450000*/);
+ }
+
+ @Test
+ public void testTwoServiceEventSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.service1", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ left.update("com.test.service2", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+ left.update("com.test.service2", 450000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 100000 /*450000 - 350000*/);
+
+ left.update(null, 500000, ROLLOVER_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 350000);
+ }
+
+ @Test
+ public void testTwoActivityAndTwoServiceEventSequence() {
+ left.mPackageName = "com.test";
+ left.mBeginTimeStamp = 100000;
+
+ left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+ left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+ left.update("com.test.service1", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ left.update("com.test.service2", 100000,
+ CONTINUING_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeUsed, 100000);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+ new Integer(CONTINUE_PREVIOUS_DAY));
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+ new Integer(CONTINUING_FOREGROUND_SERVICE));
+ assertEquals(left.mLaunchCount, 0);
+
+ left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 350000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+ left.update("com.test.service1", 400000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 400000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 /*400000 - 100000*/);
+
+ left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+ assertEquals(left.mLastTimeUsed, 450000);
+ assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+ assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+ left.update("com.test.service2", 500000, FOREGROUND_SERVICE_STOP);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+ assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 + 100000 /*500000 - 400000*/);
+
+
+ left.update(null, 550000, END_OF_DAY);
+ assertEquals(left.mLastTimeUsed, 450000);
+ assertEquals(left.mTotalTimeInForeground, 350000);
+ left.update(null, 550000, ROLLOVER_FOREGROUND_SERVICE);
+ assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+ assertEquals(left.mTotalTimeForegroundServiceUsed, 400000);
+ }
+
+ void compareUsageStats(UsageStats us1, UsageStats us2) {
+ assertEquals(us1.mPackageName, us2.mPackageName);
+ assertEquals(us1.mBeginTimeStamp, us2.mBeginTimeStamp);
+ assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+ assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+ assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+ assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
+ assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
+ assertEquals(us1.mLastForegroundActivityEventMap.size(),
+ us2.mLastForegroundActivityEventMap.size());
+ for (int i = 0; i < us1.mLastForegroundActivityEventMap.size(); i++) {
+ assertEquals(us1.mLastForegroundActivityEventMap.keyAt(i),
+ us2.mLastForegroundActivityEventMap.keyAt(i));
+ assertEquals(us1.mLastForegroundActivityEventMap.valueAt(i),
+ us2.mLastForegroundActivityEventMap.valueAt(i));
+ }
+ assertEquals(us1.mLastForegroundServiceEventMap.size(),
+ us2.mLastForegroundServiceEventMap.size());
+ for (int i = 0; i < us1.mLastForegroundServiceEventMap.size(); i++) {
+ assertEquals(us1.mLastForegroundServiceEventMap.keyAt(i),
+ us2.mLastForegroundServiceEventMap.keyAt(i));
+ assertEquals(us1.mLastForegroundServiceEventMap.valueAt(i),
+ us2.mLastForegroundServiceEventMap.valueAt(i));
+ }
+ assertEquals(us1.mChooserCounts, us2.mChooserCounts);
}
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 78d45d0..8c91c37 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -124,6 +124,7 @@
Settings.Global.AUTOFILL_LOGGING_LEVEL,
Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
+ Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
@@ -235,6 +236,8 @@
Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
Settings.Global.ENABLE_DISKSTATS_LOGGING,
Settings.Global.ENABLE_EPHEMERAL_FEATURE,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
Settings.Global.ENHANCED_4G_MODE_ENABLED,
Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
@@ -261,8 +264,7 @@
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE,
- Settings.Global.HIDDEN_API_POLICY_P_APPS,
- Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS,
+ Settings.Global.HIDDEN_API_POLICY,
Settings.Global.HIDE_ERROR_DIALOGS,
Settings.Global.HTTP_PROXY,
HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
diff --git a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
index 51e5aec..f2efabf 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
@@ -43,7 +43,7 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ModelFileManagerTest {
-
+ private static final Locale DEFAULT_LOCALE = Locale.forLanguageTag("en-US");
@Mock
private Supplier<List<ModelFileManager.ModelFile>> mModelFileSupplier;
private ModelFileManager.ModelFileSupplierImpl mModelFileSupplierImpl;
@@ -71,6 +71,8 @@
mRootTestDir.mkdirs();
mFactoryModelDir.mkdirs();
+
+ Locale.setDefault(DEFAULT_LOCALE);
}
@After
@@ -134,7 +136,7 @@
}
@Test
- public void findBestModel_useIndependentWhenNoLanguageModelMatch() {
+ public void findBestModel_noMatchedLanguageModel() {
Locale locale = Locale.forLanguageTag("ja");
ModelFileManager.ModelFile languageIndependentModelFile =
new ModelFileManager.ModelFile(
@@ -157,6 +159,28 @@
}
@Test
+ public void findBestModel_noMatchedLanguageModel_defaultLocaleModelExists() {
+ ModelFileManager.ModelFile languageIndependentModelFile =
+ new ModelFileManager.ModelFile(
+ new File("/path/a"), 1,
+ Collections.emptyList(), true);
+
+ ModelFileManager.ModelFile languageDependentModelFile =
+ new ModelFileManager.ModelFile(
+ new File("/path/b"), 1,
+ Collections.singletonList(DEFAULT_LOCALE), false);
+
+ when(mModelFileSupplier.get())
+ .thenReturn(
+ Arrays.asList(languageIndependentModelFile, languageDependentModelFile));
+
+ ModelFileManager.ModelFile bestModelFile =
+ mModelFileManager.findBestModelFile(
+ LocaleList.forLanguageTags("zh-hk"));
+ assertThat(bestModelFile).isEqualTo(languageIndependentModelFile);
+ }
+
+ @Test
public void findBestModel_languageIsMoreImportantThanVersion() {
ModelFileManager.ModelFile matchButOlderModel =
new ModelFileManager.ModelFile(
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 8646c68..3a33d57 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -19,6 +19,7 @@
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@@ -325,6 +326,33 @@
}
@Test
+ public void testSuggestConversationActions_textReplyOnly_maxThree() {
+ if (isTextClassifierDisabled()) return;
+ ConversationActions.Message message =
+ new ConversationActions.Message.Builder().setText("Hello").build();
+ ConversationActions.TypeConfig typeConfig =
+ new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
+ .setIncludedTypes(
+ Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+ .build();
+ ConversationActions.Request request =
+ new ConversationActions.Request.Builder(Collections.singletonList(message))
+ .setMaxSuggestions(1)
+ .setTypeConfig(typeConfig)
+ .build();
+
+ ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+ assertTrue(conversationActions.getConversationActions().size() <= 1);
+ for (ConversationActions.ConversationAction conversationAction :
+ conversationActions.getConversationActions()) {
+ assertEquals(conversationAction.getType(), ConversationActions.TYPE_TEXT_REPLY);
+ assertNotNull(conversationAction.getTextReply());
+ assertTrue(conversationAction.getConfidenceScore() > 0);
+ assertTrue(conversationAction.getConfidenceScore() <= 1);
+ }
+ }
+
+ @Test
public void testSetTextClassifier() {
TextClassifier classifier = mock(TextClassifier.class);
mTcm.setTextClassifier(classifier);
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index fff723f..f6ec0e6 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
@@ -38,6 +39,12 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TextLinksTest {
+ private static final String BUNDLE_KEY = "key";
+ private static final String BUNDLE_VALUE = "value";
+ private static final Bundle BUNDLE = new Bundle();
+ static {
+ BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+ }
private Map<String, Float> getEntityScores(float address, float phone, float other) {
final Map<String, Float> result = new ArrayMap<>();
@@ -59,6 +66,7 @@
final TextLinks reference = new TextLinks.Builder(fullText)
.addLink(0, 4, getEntityScores(0.f, 0.f, 1.f))
.addLink(5, 12, getEntityScores(.8f, .1f, .5f))
+ .setExtras(BUNDLE)
.build();
// Parcel and unparcel.
@@ -83,6 +91,7 @@
assertEquals(.8f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
assertEquals(.5f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_OTHER), 1e-7f);
assertEquals(.1f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
+ assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
}
@Test
@@ -94,6 +103,7 @@
final TextLinks.Request reference = new TextLinks.Request.Builder("text")
.setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
.setEntityConfig(entityConfig)
+ .setExtras(BUNDLE)
.build();
// Parcel and unparcel.
@@ -108,5 +118,6 @@
result.getEntityConfig().getHints().toArray());
assertEquals(new HashSet<String>(Arrays.asList("a", "c")),
result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
+ assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
}
}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index 4855dad..7ea5108b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
+import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
@@ -31,6 +32,12 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TextSelectionTest {
+ private static final String BUNDLE_KEY = "key";
+ private static final String BUNDLE_VALUE = "value";
+ private static final Bundle BUNDLE = new Bundle();
+ static {
+ BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+ }
@Test
public void testParcel() {
@@ -42,6 +49,7 @@
.setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
.setEntityType(TextClassifier.TYPE_URL, 0.1f)
.setId(id)
+ .setExtras(BUNDLE)
.build();
// Parcel and unparcel
@@ -61,6 +69,7 @@
assertEquals(0.7f, result.getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
assertEquals(0.3f, result.getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
assertEquals(0.1f, result.getConfidenceScore(TextClassifier.TYPE_URL), 1e-7f);
+ assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
}
@Test
@@ -69,6 +78,7 @@
final TextSelection.Request reference =
new TextSelection.Request.Builder(text, 0, text.length())
.setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
+ .setExtras(BUNDLE)
.build();
// Parcel and unparcel.
@@ -81,5 +91,6 @@
assertEquals(0, result.getStartIndex());
assertEquals(text.length(), result.getEndIndex());
assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
+ assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
}
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a1fbe0a..c7945bd02 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -324,6 +324,7 @@
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<permission name="android.permission.MOVE_PACKAGE"/>
<permission name="android.permission.PACKAGE_USAGE_STATS" />
+ <permission name="android.permission.POWER_SAVER" />
<permission name="android.permission.READ_FRAME_BUFFER"/>
<permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index ee12b91..24b7f36 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -979,6 +979,87 @@
throws DeniedByServerException;
/**
+ * The keys in an offline license allow protected content to be played even
+ * if the device is not connected to a network. Offline licenses are stored
+ * on the device after a key request/response exchange when the key request
+ * KeyType is OFFLINE. Normally each app is responsible for keeping track of
+ * the keySetIds it has created. If an app loses the keySetId for any stored
+ * licenses that it created, however, it must be able to recover the stored
+ * keySetIds so those licenses can be removed when they expire or when the
+ * app is uninstalled.
+ * <p>
+ * This method returns a list of the keySetIds for all offline licenses.
+ * The offline license keySetId may be used to query the status of an
+ * offline license with {@link #getOfflineLicenseState} or remove it with
+ * {@link #removeOfflineLicense}.
+ *
+ * @return a list of offline license keySetIds
+ */
+ @NonNull
+ public native List<byte[]> getOfflineLicenseKeySetIds();
+
+ /**
+ * Normally offline licenses are released using a key request/response
+ * exchange using {@link #getKeyRequest} where the key type is
+ * KEY_TYPE_RELEASE, followed by {@link #provideKeyResponse}. This allows
+ * the server to cryptographically confirm that the license has been removed
+ * and then adjust the count of offline licenses allocated to the device.
+ * <p>
+ * In some exceptional situations it may be necessary to directly remove
+ * offline licenses without notifying the server, which may be performed
+ * using this method.
+ *
+ * @param keySetId the id of the offline license to remove
+ * @throws IllegalArgumentException if the keySetId does not refer to an
+ * offline license.
+ */
+ public native void removeOfflineLicense(@NonNull byte[] keySetId);
+
+ /**
+ * Offline license state is unknown, an error occurred while trying
+ * to access it.
+ */
+ public static final int OFFLINE_LICENSE_STATE_UNKNOWN = 0;
+
+ /**
+ * Offline license state is usable, the keys may be used for decryption.
+ */
+ public static final int OFFLINE_LICENSE_USABLE = 1;
+
+ /**
+ * Offline license state is inactive, the keys have been marked for
+ * release using {@link #getKeyRequest} with KEY_TYPE_RELEASE but the
+ * key response has not been received.
+ */
+ public static final int OFFLINE_LICENSE_INACTIVE = 2;
+
+ /** @hide */
+ @IntDef({
+ OFFLINE_LICENSE_STATE_UNKNOWN,
+ OFFLINE_LICENSE_USABLE,
+ OFFLINE_LICENSE_INACTIVE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OfflineLicenseState {}
+
+ /**
+ * Request the state of an offline license. An offline license may be usable
+ * or inactive. The keys in a usable offline license are available for
+ * decryption. When the offline license state is inactive, the keys have
+ * been marked for release using {@link #getKeyRequest} with
+ * KEY_TYPE_RELEASE but the key response has not been received. The keys in
+ * an inactive offline license are not usable for decryption.
+ *
+ * @param keySetId selects the offline license
+ * @return the offline license state, one of {@link #OFFLINE_LICENSE_USABLE},
+ * {@link #OFFLINE_LICENSE_INACTIVE} or {@link #OFFLINE_LICENSE_STATE_UNKNOWN}.
+ * @throws IllegalArgumentException if the keySetId does not refer to an
+ * offline license.
+ */
+ @OfflineLicenseState
+ public native int getOfflineLicenseState(@NonNull byte[] keySetId);
+
+ /**
* Secure stops are a way to enforce limits on the number of concurrent
* streams per subscriber across devices. They provide secure monitoring of
* the lifetime of content decryption keys in MediaDrm sessions.
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 0b3c973..4e90162 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -294,7 +294,7 @@
* reached end of stream and been paused, or never started before,
* playback will start at the beginning.
*
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object play();
@@ -305,21 +305,21 @@
* After setting the datasource and the display surface, you need to
* call prepare().
*
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object prepare();
/**
* Pauses playback. Call play() to resume.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object pause();
/**
* Tries to play next data source if applicable.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object skipToNext();
@@ -404,7 +404,7 @@
* You must call this method before {@link #play()} and {@link #pause()} in order
* for the audio attributes to become effective thereafter.
* @param attributes a non-null set of audio attributes
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setAudioAttributes(@NonNull AudioAttributes attributes);
@@ -419,7 +419,7 @@
* Sets the data source as described by a DataSourceDesc.
*
* @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 #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setDataSource(@NonNull DataSourceDesc dsd);
@@ -429,7 +429,7 @@
* after current data source is finished.
*
* @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 #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setNextDataSource(@NonNull DataSourceDesc dsd);
@@ -438,14 +438,14 @@
* Sets a list of data sources to be played sequentially after current data source is done.
*
* @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 #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setNextDataSources(@NonNull List<DataSourceDesc> dsds);
/**
* Removes all data sources pending to be played.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object clearNextDataSources();
@@ -460,7 +460,7 @@
/**
* Configures the player to loop on the current data source.
* @param loop true if the current data source is meant to loop.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object loopCurrent(boolean loop);
@@ -473,7 +473,7 @@
* A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified
* gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player.
* @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setPlayerVolume(float volume);
@@ -502,7 +502,7 @@
*
* @param label An application specific Object used to help to identify the completeness
* of a batch of commands.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object notifyWhenCommandLabelReached(@NonNull Object label);
@@ -518,7 +518,7 @@
* played.
*
* @param sh the SurfaceHolder to use for video display
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
public abstract Object setDisplay(SurfaceHolder sh);
@@ -538,7 +538,7 @@
*
* @param surface The {@link Surface} to be used for the video portion of
* the media.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setSurface(Surface surface);
@@ -558,7 +558,7 @@
*
* @param context the Context to use
* @param mode the power/wake mode to set
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
* @see android.os.PowerManager
*/
// This is an asynchronous call.
@@ -572,7 +572,7 @@
* access.
*
* @param screenOn Supply true to keep the screen on, false to allow it to turn off.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setScreenOnWhilePlaying(boolean screenOn);
@@ -667,22 +667,11 @@
* available for the media being handled by this instance of MediaPlayer2
* The attributes are descibed in {@link MetricsConstants}.
*
- * Additional vendor-specific fields may also be present in
- * the return value.
+ * Additional vendor-specific fields may also be present in the return value.
*/
public abstract PersistableBundle getMetrics();
/**
- * Checks whether the MediaPlayer2 is playing.
- *
- * @return true if currently playing, false otherwise
- * @throws IllegalStateException if the internal player engine has not been
- * initialized or has been released.
- * @hide
- */
- public abstract boolean isPlaying();
-
- /**
* Gets the current buffering management params used by the source component.
* Calling it only after {@code setDataSource} has been called.
* Each type of data source might have different set of default params.
@@ -690,10 +679,10 @@
* @return the current buffering management params used by the source component.
* @throws IllegalStateException if the internal player engine has not been
* initialized, or {@code setDataSource} has not been called.
- * @hide
*/
+ // TODO: make it public when ready
@NonNull
- public BufferingParams getBufferingParams() {
+ BufferingParams getBufferingParams() {
return new BufferingParams.Builder().build();
}
@@ -705,80 +694,11 @@
* The input is a hint to MediaPlayer2.
*
* @param params the buffering management params.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
- *
- * @hide
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
+ // TODO: make it public when ready
// This is an asynchronous call.
- public abstract Object setBufferingParams(@NonNull BufferingParams params);
-
- /**
- * Change playback speed of audio by resampling the audio.
- * <p>
- * Specifies resampling as audio mode for variable rate playback, i.e.,
- * resample the waveform based on the requested playback rate to get
- * a new waveform, and play back the new waveform at the original sampling
- * frequency.
- * When rate is larger than 1.0, pitch becomes higher.
- * When rate is smaller than 1.0, pitch becomes lower.
- *
- * @hide
- */
- public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2;
-
- /**
- * Change playback speed of audio without changing its pitch.
- * <p>
- * Specifies time stretching as audio mode for variable rate playback.
- * Time stretching changes the duration of the audio samples without
- * affecting its pitch.
- * <p>
- * This mode is only supported for a limited range of playback speed factors,
- * e.g. between 1/2x and 2x.
- *
- * @hide
- */
- public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;
-
- /**
- * Change playback speed of audio without changing its pitch, and
- * possibly mute audio if time stretching is not supported for the playback
- * speed.
- * <p>
- * Try to keep audio pitch when changing the playback rate, but allow the
- * system to determine how to change audio playback if the rate is out
- * of range.
- *
- * @hide
- */
- public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0;
-
- /** @hide */
- @IntDef(flag = false, prefix = "PLAYBACK_RATE_AUDIO_MODE", value = {
- PLAYBACK_RATE_AUDIO_MODE_DEFAULT,
- PLAYBACK_RATE_AUDIO_MODE_STRETCH,
- PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface PlaybackRateAudioMode {}
-
- /**
- * Sets playback rate and audio mode.
- *
- * @param rate the ratio between desired playback rate and normal one.
- * @param audioMode audio playback mode. Must be one of the supported
- * audio modes.
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- * @throws IllegalArgumentException if audioMode is not supported.
- *
- * @hide
- */
- @NonNull
- public PlaybackParams easyPlaybackParams(float rate, @PlaybackRateAudioMode int audioMode) {
- return new PlaybackParams();
- }
+ abstract Object setBufferingParams(@NonNull BufferingParams params);
/**
* Sets playback rate using {@link PlaybackParams}. The object sets its internal
@@ -787,7 +707,7 @@
* the object state.
*
* @param params the playback params.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setPlaybackParams(@NonNull PlaybackParams params);
@@ -796,6 +716,7 @@
* Gets the playback params, containing the current playback rate.
*
* @return the playback params.
+ * @throws IllegalStateException if the internal player engine has not been initialized.
*/
@NonNull
public abstract PlaybackParams getPlaybackParams();
@@ -804,7 +725,7 @@
* Sets A/V sync mode.
*
* @param params the A/V sync params to apply
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setSyncParams(@NonNull SyncParams params);
@@ -813,6 +734,7 @@
* Gets the A/V sync mode.
*
* @return the A/V sync params
+ * @throws IllegalStateException if the internal player engine has not been initialized.
*/
@NonNull
public abstract SyncParams getSyncParams();
@@ -822,7 +744,7 @@
* Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
*
* @param msec the offset in milliseconds from the start to seek to
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public Object seekTo(long msec) {
@@ -882,7 +804,8 @@
/**
* Moves the media to specified time position by considering the given mode.
* <p>
- * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.
+ * When seekTo is finished, the user will be notified via
+ * {@link EventCallback#onCallCompleted} with {@link #CALL_COMPLETED_SEEK_TO}.
* There is at most one active seekTo processed at any time. If there is a to-be-completed
* seekTo, new seekTo requests will be queued in such a way that only the last request
* is kept. When current seekTo is completed, the queued request will be processed if
@@ -895,7 +818,7 @@
* If msec is negative, time position zero will be used.
* If msec is larger than duration, duration will be used.
* @param mode the mode indicating where exactly to seek to.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object seekTo(long msec, @SeekMode int mode);
@@ -953,7 +876,7 @@
* However, it is possible to force this player to be part of an already existing audio session
* by calling this method.
* This method must be called before one of the overloaded <code> setDataSource </code> methods.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setAudioSessionId(int sessionId);
@@ -979,7 +902,7 @@
* <p>This method must be called after one of the overloaded <code> setDataSource </code>
* methods.
* @param effectId system wide unique id of the effect to attach
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object attachAuxEffect(int effectId);
@@ -996,7 +919,7 @@
* x == 0 -> level = 0
* 0 < x <= R -> level = 10^(72*(x-R)/20/R)
* @param level send level scalar
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object setAuxEffectSendLevel(float level);
@@ -1122,7 +1045,7 @@
* @param index the index of the track to be selected. The valid range of the index
* is 0..total number of track - 1. The total number of tracks as well as the type of
* each individual track can be found by calling {@link #getTrackInfo()} method.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*
* @see MediaPlayer2#getTrackInfo
*/
@@ -1139,7 +1062,7 @@
* @param index the index of the track to be deselected. The valid range of the index
* is 0..total number of tracks - 1. The total number of tracks as well as the type of
* each individual track can be found by calling {@link #getTrackInfo()} method.
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*
* @see MediaPlayer2#getTrackInfo
*/
@@ -1872,7 +1795,7 @@
* from the source through {@code getDrmInfo} or registering a
* {@link DrmEventCallback#onDrmInfo}.
*
- * @return a token which can be used to cancel the operation later with {@link #cancel}.
+ * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
public abstract Object prepareDrm(@NonNull UUID uuid);
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 8f475a1..3534636 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -131,6 +131,13 @@
@GuardedBy("mTaskLock")
private Task mCurrentTask;
+ @GuardedBy("mTaskLock")
+ boolean mIsPreviousCommandSeekTo = false;
+ // |mPreviousSeekPos| and |mPreviousSeekMode| are valid only when |mIsPreviousCommandSeekTo|
+ // is true, and they are accessed on |mHandlerThread| only.
+ long mPreviousSeekPos = -1;
+ int mPreviousSeekMode = SEEK_PREVIOUS_SYNC;
+
@GuardedBy("this")
private boolean mReleased;
@@ -239,15 +246,14 @@
final String msg = "Cannot set AudioAttributes to null";
throw new IllegalArgumentException(msg);
}
- setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, attributes);
+ native_setAudioAttributes(attributes);
}
});
}
@Override
public @NonNull AudioAttributes getAudioAttributes() {
- AudioAttributes attributes = (AudioAttributes) getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
- return attributes;
+ return native_getAudioAttributes();
}
@Override
@@ -927,14 +933,11 @@
private native PersistableBundle native_getMetrics();
@Override
- public native boolean isPlaying();
-
- @Override
@NonNull
- public native BufferingParams getBufferingParams();
+ native BufferingParams getBufferingParams();
@Override
- public Object setBufferingParams(@NonNull BufferingParams params) {
+ Object setBufferingParams(@NonNull BufferingParams params) {
return addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
@Override
void process() {
@@ -946,42 +949,6 @@
private native void _setBufferingParams(@NonNull BufferingParams params);
- /**
- * Sets playback rate and audio mode.
- *
- * @param rate the ratio between desired playback rate and normal one.
- * @param audioMode audio playback mode. Must be one of the supported
- * audio modes.
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- * @throws IllegalArgumentException if audioMode is not supported.
- *
- * @hide
- */
- @Override
- @NonNull
- public PlaybackParams easyPlaybackParams(float rate, @PlaybackRateAudioMode int audioMode) {
- PlaybackParams params = new PlaybackParams();
- params.allowDefaults();
- switch (audioMode) {
- case PLAYBACK_RATE_AUDIO_MODE_DEFAULT:
- params.setSpeed(rate).setPitch(1.0f);
- break;
- case PLAYBACK_RATE_AUDIO_MODE_STRETCH:
- params.setSpeed(rate).setPitch(1.0f)
- .setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_FAIL);
- break;
- case PLAYBACK_RATE_AUDIO_MODE_RESAMPLE:
- params.setSpeed(rate).setPitch(rate);
- break;
- default:
- final String msg = "Audio playback mode " + audioMode + " is not supported";
- throw new IllegalArgumentException(msg);
- }
- return params;
- }
-
@Override
public Object setPlaybackParams(@NonNull PlaybackParams params) {
return addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
@@ -995,26 +962,10 @@
private native void _setPlaybackParams(@NonNull PlaybackParams params);
- /**
- * Gets the playback params, containing the current playback rate.
- *
- * @return the playback params.
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- */
@Override
@NonNull
public native PlaybackParams getPlaybackParams();
- /**
- * Sets A/V sync mode.
- *
- * @param params the A/V sync params to apply
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- * @throws IllegalArgumentException if params are not supported.
- */
@Override
public Object setSyncParams(@NonNull SyncParams params) {
return addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
@@ -1028,48 +979,10 @@
private native void _setSyncParams(@NonNull SyncParams params);
- /**
- * Gets the A/V sync mode.
- *
- * @return the A/V sync params
- *
- * @throws IllegalStateException if the internal player engine has not been
- * initialized.
- */
@Override
@NonNull
public native SyncParams getSyncParams();
- /**
- * Moves the media to specified time position by considering the given mode.
- * <p>
- * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.
- * There is at most one active seekTo processed at any time. If there is a to-be-completed
- * seekTo, new seekTo requests will be queued in such a way that only the last request
- * is kept. When current seekTo is completed, the queued request will be processed if
- * that request is different from just-finished seekTo operation, i.e., the requested
- * position or mode is different.
- *
- * @param msec the offset in milliseconds from the start to seek to.
- * When seeking to the given time position, there is no guarantee that the data source
- * has a frame located at the position. When this happens, a frame nearby will be rendered.
- * If msec is negative, time position zero will be used.
- * If msec is larger than duration, duration will be used.
- * @param mode the mode indicating where exactly to seek to.
- * Use {@link #SEEK_PREVIOUS_SYNC} if one wants to seek to a sync frame
- * that has a timestamp earlier than or the same as msec. Use
- * {@link #SEEK_NEXT_SYNC} if one wants to seek to a sync frame
- * that has a timestamp later than or the same as msec. Use
- * {@link #SEEK_CLOSEST_SYNC} if one wants to seek to a sync frame
- * that has a timestamp closest to or the same as msec. Use
- * {@link #SEEK_CLOSEST} if one wants to seek to a frame that may
- * or may not be a sync frame but is closest to or the same as msec.
- * {@link #SEEK_CLOSEST} often has larger performance overhead compared
- * to the other options if there is no sync frame located at msec.
- * @throws IllegalStateException if the internal player engine has not been
- * initialized
- * @throws IllegalArgumentException if the mode is invalid.
- */
@Override
public Object seekTo(final long msec, @SeekMode int mode) {
return addTask(new Task(CALL_COMPLETED_SEEK_TO, true) {
@@ -1090,7 +1003,23 @@
+ Integer.MIN_VALUE);
posMs = Integer.MIN_VALUE;
}
+
+ synchronized (mTaskLock) {
+ if (mIsPreviousCommandSeekTo
+ && mPreviousSeekPos == posMs
+ && mPreviousSeekMode == mode) {
+ throw new CommandSkippedException(
+ "same as previous seekTo");
+ }
+ }
+
_seekTo(posMs, mode);
+
+ synchronized (mTaskLock) {
+ mIsPreviousCommandSeekTo = true;
+ mPreviousSeekPos = posMs;
+ mPreviousSeekMode = mode;
+ }
}
});
}
@@ -1124,7 +1053,7 @@
return new MediaTimestamp(
getCurrentPosition() * 1000L,
System.nanoTime(),
- isPlaying() ? getPlaybackParams().getSpeed() : 0.f);
+ getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f);
} catch (IllegalStateException e) {
return null;
}
@@ -1152,6 +1081,11 @@
mNextSourceState = NEXT_SOURCE_STATE_INIT;
}
+ synchronized (mTaskLock) {
+ mPendingTasks.clear();
+ mIsPreviousCommandSeekTo = false;
+ }
+
stayAwake(false);
_reset();
// make sure none of the listeners get called anymore
@@ -1167,14 +1101,12 @@
// Keep KEY_PARAMETER_* in sync with include/media/mediaplayer2.h
private final static int KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400;
/**
- * Sets the parameter indicated by key.
- * @param key key indicates the parameter to be set.
+ * Sets the audio attributes.
* @param value value of the parameter to be set.
* @return true if the parameter is set successfully, false otherwise
*/
- private native boolean setParameter(int key, Object value);
-
- private native Object getParameter(int key);
+ private native boolean native_setAudioAttributes(AudioAttributes audioAttributes);
+ private native AudioAttributes native_getAudioAttributes();
/**
@@ -1748,6 +1680,12 @@
case MEDIA_SEEK_COMPLETE:
{
synchronized (mTaskLock) {
+ if (!mPendingTasks.isEmpty()
+ && mPendingTasks.get(0).mMediaCallType != CALL_COMPLETED_SEEK_TO
+ && getState() == PLAYER_STATE_PLAYING) {
+ mIsPreviousCommandSeekTo = false;
+ }
+
if (mCurrentTask != null
&& mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
&& mCurrentTask.mNeedToWaitForEventToComplete) {
@@ -3150,6 +3088,12 @@
mDSD = mCurrentDSD;
}
+ if (mMediaCallType != CALL_COMPLETED_SEEK_TO) {
+ synchronized (mTaskLock) {
+ mIsPreviousCommandSeekTo = false;
+ }
+ }
+
// TODO: Make native implementations asynchronous and let them send notifications.
if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) {
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 8637ada..be71dad5 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -161,6 +161,12 @@
jint kSecurityLevelHwSecureAll;
} gSecurityLevels;
+struct OfflineLicenseState {
+ jint kOfflineLicenseStateUsable;
+ jint kOfflineLicenseStateInactive;
+ jint kOfflineLicenseStateUnknown;
+} gOfflineLicenseStates;
+
struct fields_t {
jfieldID context;
@@ -740,6 +746,15 @@
GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_USABLE", "I");
+ gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_INACTIVE", "I");
+ gOfflineLicenseStates.kOfflineLicenseStateInactive = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
+ gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
+
+ GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
+
jmethodID getMaxSecurityLevel;
GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
@@ -890,9 +905,7 @@
JNIEnv *env, jobject thiz, jint jlevel) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1070,6 +1083,10 @@
JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
sp<IDrm> drm = GetDrm(env, thiz);
+ if (!CheckDrm(env, drm)) {
+ return;
+ }
+
if (jkeysetId == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"keySetId is null");
@@ -1231,9 +1248,7 @@
JNIEnv *env, jobject thiz) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1286,9 +1301,7 @@
JNIEnv *env, jobject thiz, jbyteArray ssid) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return;
}
@@ -1437,6 +1450,65 @@
}
}
+static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
+ JNIEnv *env, jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return NULL;
+ }
+
+ List<Vector<uint8_t> > keySetIds;
+
+ status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
+ return NULL;
+ }
+
+ return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
+}
+
+static void android_media_MediaDrm_removeOfflineLicense(
+ JNIEnv *env, jobject thiz, jbyteArray keySetId) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return;
+ }
+
+ status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
+
+ throwExceptionAsNecessary(env, err, "Failed to remove offline license");
+}
+
+static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
+ jobject thiz, jbyteArray jkeySetId) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+ }
+
+ Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
+
+ DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
+
+ status_t err = drm->getOfflineLicenseState(keySetId, &state);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
+ return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+ }
+
+ switch(state) {
+ case DrmPlugin::kOfflineLicenseStateUsable:
+ return gOfflineLicenseStates.kOfflineLicenseStateUsable;
+ case DrmPlugin::kOfflineLicenseStateInactive:
+ return gOfflineLicenseStates.kOfflineLicenseStateInactive;
+ default:
+ return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+ }
+}
static jstring android_media_MediaDrm_getPropertyString(
JNIEnv *env, jobject thiz, jstring jname) {
@@ -1718,9 +1790,8 @@
android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
{
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1839,6 +1910,15 @@
{ "getSecurityLevel", "([B)I",
(void *)android_media_MediaDrm_getSecurityLevel },
+ { "removeOfflineLicense", "([B)V",
+ (void *)android_media_MediaDrm_removeOfflineLicense },
+
+ { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
+ (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
+
+ { "getOfflineLicenseState", "([B)I",
+ (void *)android_media_MediaDrm_getOfflineLicenseState },
+
{ "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
(void *)android_media_MediaDrm_getPropertyString },
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 520077f..0769e5c 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -598,20 +598,6 @@
process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
}
-static jboolean
-android_media_MediaPlayer2_isPlaying(JNIEnv *env, jobject thiz)
-{
- sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return JNI_FALSE;
- }
- const jboolean is_playing = mp->isPlaying();
-
- ALOGV("isPlaying: %d", is_playing);
- return is_playing;
-}
-
static void
android_media_MediaPlayer2_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params)
{
@@ -860,56 +846,29 @@
}
static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
+android_media_MediaPlayer2_setAudioAttributes(JNIEnv *env, jobject thiz, jobject attributes)
{
- ALOGV("setParameter: key %d", key);
+ ALOGV("setAudioAttributes");
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return false;
}
-
- return false;
- // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
- // Once JAudioTrack migration is done, the AudioAttribute jobject
- // should be directly passed to AudioTrack without native parcel conversion.
- /*
- Parcel *request = parcelForJavaObject(env, java_request);
- status_t err = mp->setParameter(key, *request);
- if (err == OK) {
- return true;
- } else {
- return false;
- }
- */
+ status_t err = mp->setAudioAttributes(attributes);
+ return err == OK;
}
static jobject
-android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key)
+android_media_MediaPlayer2_getAudioAttributes(JNIEnv *env, jobject thiz)
{
- ALOGV("getParameter: key %d", key);
+ ALOGV("getAudioAttributes");
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
if (mp == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return NULL;
}
- return NULL;
- // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
- // Once JAudioTrack migration is done, the AudioAttribute jobject
- // should be directly passed to AudioTrack without native parcel conversion.
- /*
- jobject jParcel = createJavaParcelObject(env);
- if (jParcel != NULL) {
- Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
- status_t err = mp->getParameter(key, nativeParcel);
- if (err != OK) {
- env->DeleteLocalRef(jParcel);
- return NULL;
- }
- }
- return jParcel;
- */
+ return mp->getAudioAttributes();
}
static void
@@ -1442,18 +1401,17 @@
{"native_getState", "()I", (void *)android_media_MediaPlayer2_getState},
{"native_getMetrics", "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
{"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
- {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
- {"_setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer2_setSyncParams},
- {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer2_getSyncParams},
+ {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
+ {"_setSyncParams", "(Landroid/media/SyncParams;)V", (void *)android_media_MediaPlayer2_setSyncParams},
+ {"getSyncParams", "()Landroid/media/SyncParams;", (void *)android_media_MediaPlayer2_getSyncParams},
{"_seekTo", "(JI)V", (void *)android_media_MediaPlayer2_seekTo},
{"_pause", "()V", (void *)android_media_MediaPlayer2_pause},
- {"isPlaying", "()Z", (void *)android_media_MediaPlayer2_isPlaying},
{"getCurrentPosition", "()J", (void *)android_media_MediaPlayer2_getCurrentPosition},
{"getDuration", "()J", (void *)android_media_MediaPlayer2_getDuration},
{"_release", "()V", (void *)android_media_MediaPlayer2_release},
{"_reset", "()V", (void *)android_media_MediaPlayer2_reset},
- {"setParameter", "(ILjava/lang/Object;)Z", (void *)android_media_MediaPlayer2_setParameter},
- {"getParameter", "(I)Ljava/lang/Object;", (void *)android_media_MediaPlayer2_getParameter},
+ {"native_setAudioAttributes", "(Landroid/media/AudioAttributes;)Z", (void *)android_media_MediaPlayer2_setAudioAttributes},
+ {"native_getAudioAttributes", "()Landroid/media/AudioAttributes;", (void *)android_media_MediaPlayer2_getAudioAttributes},
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer2_setLooping},
{"isLooping", "()Z", (void *)android_media_MediaPlayer2_isLooping},
{"native_setVolume", "(F)V", (void *)android_media_MediaPlayer2_setVolume},
diff --git a/native/android/Android.bp b/native/android/Android.bp
index a4306fe..5cfb09b 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -81,6 +81,8 @@
export_static_lib_headers: ["libarect"],
include_dirs: ["bionic/libc/dns/include"],
+
+ version_script: "libandroid.map.txt",
}
// Network library.
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 4e52ff6d..4abcf73 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -186,7 +186,8 @@
title = mStorageManager.getBestVolumeDescription(privateVol);
storageUuid = StorageManager.convert(privateVol.fsUuid);
}
- } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
+ } else if ((volume.getType() == VolumeInfo.TYPE_PUBLIC
+ || volume.getType() == VolumeInfo.TYPE_STUB)
&& volume.getMountUserId() == userId) {
rootId = volume.getFsUuid();
title = mStorageManager.getBestVolumeDescription(volume);
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index b77d4e5..d34820c 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 836ec80..b595e2b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 83c4b8e..f8c2ba2 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -227,11 +226,11 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"اختيار برنامج ترميز LDAC\nلصوت مشغّل البلوتوث: جودة التشغيل"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"البث: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"نظام أسماء النطاقات الخاص"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"اختر وضع نظام أسماء النطاقات الخاص"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"تحديد وضع \"نظام أسماء النطاقات الخاص\""</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"غير مفعّل"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"تلقائي"</string>
- <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد نظام أسماء النطاقات الخاص"</string>
- <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
+ <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد \"نظام أسماء النطاقات الخاص\""</string>
+ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"يُرجى إدخال اسم مضيف \"مزوّد نظام أسماء النطاقات\""</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"تعذّر الاتصال"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
@@ -371,10 +370,10 @@
<string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك"</string>
<string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<string name="power_remaining_duration_only_short" msgid="3463575350656389957">"الوقت المتبقي: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
- <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
- <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_enhanced" msgid="2095821536747992464">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
+ <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_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>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ddd17daf..72122c2 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a6e484f..23008e2 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a446845..3ee8589 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -21,13 +21,12 @@
<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>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nije povezano zbog lošeg kvaliteta mreže"</string>
<string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi veza je otkazala"</string>
- <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom autentičnosti"</string>
+ <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom identiteta"</string>
<string name="wifi_cant_connect" msgid="5410016875644565884">"Povezivanje nije uspelo"</string>
<string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Povezivanje sa „<xliff:g id="AP_NAME">%1$s</xliff:g>“ nije uspelo"</string>
<string name="wifi_check_password_try_again" msgid="516958988102584767">"Proverite lozinku i probajte ponovo"</string>
@@ -448,5 +447,5 @@
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
<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 sada"</string>
+ <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d56db13..64253bf 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c1bc31c..668aa2d 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -21,7 +21,6 @@
<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,7 +373,7 @@
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<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" msgid="107616694963545745">"Следва да издържи до около <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>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1550c00..c6eed2c 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 460e7cf..16179fb 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5638947..f906ea4 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -70,7 +69,7 @@
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actiu"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
- <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
+ <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència de fitxers"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"Dispositiu d\'entrada"</string>
<string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accés a Internet"</string>
<string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartir contactes"</string>
@@ -393,7 +392,7 @@
<string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
<string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
<string name="battery_info_status_not_charging" msgid="8523453668342598579">"El dispositiu està endollat però en aquests moments no es pot carregar"</string>
- <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
+ <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string>
<string name="disabled" msgid="9206776641295849915">"Desactivat"</string>
<string name="external_source_trusted" msgid="2707996266575928037">"Amb permís"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index de02245..f9c8669 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 34608d3..6b2bd98 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 79965d2..ad6f5f2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -231,7 +230,7 @@
<string name="private_dns_mode_off" msgid="8236575187318721684">"Aus"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisch"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname des privaten DNS-Anbieters"</string>
- <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostnamen des DNS-Anbieters eingeben"</string>
+ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Verbindung nicht möglich"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index b9ea843..5bfbf2c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -231,7 +230,7 @@
<string name="private_dns_mode_off" msgid="8236575187318721684">"Ανενεργή"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Αυτόματα"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Όνομα κεντρικού υπολογιστή παρόχου DNS"</string>
- <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
+ <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
<string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Δεν ήταν δυνατή η σύνδεση"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2bfd5b1..6927fda 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 790c0d3..675084f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1dec85d..b51b847 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 406e15d..fb077be 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index bd4724e..3d3b8c3 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 45b8ac7..0af118e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 23c63b1..dde10d0d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ad99000..1257ea5 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -227,7 +226,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Déclencher le codec audio Bluetooth LDAC\nSélection : qualité de lecture"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Diffusion : <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privé"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionnez le mode DNS privé"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionner le mode DNS privé"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Désactivé"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatique"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c23db25..444a52e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -70,7 +69,7 @@
<string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actif"</string>
<string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
- <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
+ <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichiers"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"Périphérique d\'entrée"</string>
<string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accès Internet"</string>
<string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Partage de contacts"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 46532e9..8df2697 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6a74490..4a92f2a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index bd9a6ec..6d88c35 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5270531..32c9a62 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index ad897f8..ed19267 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 82755f9..6d516ea 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 961f892..a5f2317 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 759b7ba..6cf09a6 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bd41e28..a1b9b82 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5da253c..1a50622 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -316,7 +315,7 @@
<string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
<string name="show_all_anrs" msgid="4924885492787069007">"הצגת מקרי ANR ברקע"</string>
<string name="show_all_anrs_summary" msgid="6636514318275139826">"הצגת תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
- <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ הודעות"</string>
+ <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ התראות"</string>
<string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"הצגת אזהרה כשאפליקציה שולחת התראה ללא ערוץ חוקי"</string>
<string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאת אפליקציות באחסון חיצוני"</string>
<string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index f6b81ed..4c544af 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -436,7 +435,7 @@
<string name="cancel" msgid="6859253417269739139">"キャンセル"</string>
<string name="okay" msgid="1997666393121016642">"OK"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ON にする"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"マナーモードを ON にする"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"サイレント モードを ON にする"</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>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d5f5408..92f3049 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c3fbfcd..b56c6fd 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 8e73f81..5860473 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ce225ea..87e18e6 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b47471b..3333c0d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 9853dac..cbbc47c 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1816515..21e4679 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index e6a8e1c..cbff9e7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b55afc0..d200828 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index e28c8ee..db16847 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 6860398..c3af968 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index ba6d601..8627e1b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a5d230a..cd7f175 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a7ac3ef..d0b2e12 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 6cdab67..5f5957c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cf18477..3c240f8 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 8aba0f8..1699870 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index e3f1aea..738df94 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 8ecac4d..2d39cc6 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 6f17e13..61f0447 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3c208e3..519f82c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -227,7 +226,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 66c59ac..f01ddfa 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -278,7 +277,7 @@
<string name="media_category" msgid="4388305075496848353">"Multimédia"</string>
<string name="debug_monitoring_category" msgid="7640508148375798343">"Monitorização"</string>
<string name="strict_mode" msgid="1938795874357830695">"Modo rigoroso ativado"</string>
- <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se aplic. fazem oper. prolong. no tópico princ."</string>
+ <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se app fazem oper. prolong. no tópico princ."</string>
<string name="pointer_location" msgid="6084434787496938001">"Localização do ponteiro"</string>
<string name="pointer_location_summary" msgid="840819275172753713">"Apresentar dados atuais de toque"</string>
<string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
@@ -305,7 +304,7 @@
<string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de clipe não retangulares"</string>
<string name="track_frame_time" msgid="6094365083096851167">"Renderiz. HWUI do perfil"</string>
<string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar cam. depuração GPU"</string>
- <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. aplic."</string>
+ <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. app"</string>
<string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de anim. da janela"</string>
<string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de anim. de trans."</string>
<string name="animator_duration_scale_title" msgid="3406722410819934083">"Esc. de duração do anim."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -227,7 +226,7 @@
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
<string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
<string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
- <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+ <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
<string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
<string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
<string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 703add6..8a7b440 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4eb3ca4..31274d1 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1ab5b79..b22e068 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5c3920f..43923b8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -21,7 +21,6 @@
<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>
@@ -438,7 +437,7 @@
<string name="cancel" msgid="6859253417269739139">"Zrušiť"</string>
<string name="okay" msgid="1997666393121016642">"OK"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Zapnúť"</string>
- <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim Nerušiť"</string>
+ <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim bez vyrušení"</string>
<string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikdy"</string>
<string name="zen_interruption_level_priority" msgid="2078370238113347720">"Iba prioritné"</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>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index f479405..6d392fe 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2741985..e05a019 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 241d9cb..371b909 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -21,13 +21,12 @@
<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>
<string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Није повезано због лошег квалитета мреже"</string>
<string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi веза је отказала"</string>
- <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом аутентичности"</string>
+ <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом идентитета"</string>
<string name="wifi_cant_connect" msgid="5410016875644565884">"Повезивање није успело"</string>
<string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Повезивање са „<xliff:g id="AP_NAME">%1$s</xliff:g>“ није успело"</string>
<string name="wifi_check_password_try_again" msgid="516958988102584767">"Проверите лозинку и пробајте поново"</string>
@@ -448,5 +447,5 @@
<string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Трајање"</string>
<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="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d338e96..e6872bb 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d693077..23efb91 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8f5c7d8..53ba738 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5f7ab996..c8c6b4c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 020baf0..d293d59 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 2164ade..9da4561 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -21,7 +21,6 @@
<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,7 +373,7 @@
<string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
<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 dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$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_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>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 532927c..2d5cd7f 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index cf26d20..512ea86 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c158179..84ad3ed 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ac8bffe..af2ada5 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 78306da..f454127 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4fb26100..10a20be 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c5a8f92..1510545 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 0947ccec..90c0d80 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index cd90d74..e4f9f4d 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -21,7 +21,6 @@
<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>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index c9bcd65..70f9bb6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -930,6 +930,8 @@
<string name="power_discharge_by">Should last until about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string>
<!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
<string name="power_discharge_by_only">Should last until about <xliff:g id="time">%1$s</xliff:g></string>
+ <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
+ <string name="power_discharge_by_only_short">Until <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
<!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount -->
<string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 5a57e69..8f9394f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -152,7 +152,8 @@
final MeasurementDetails details = new MeasurementDetails();
if (mVolume == null) return details;
- if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC) {
+ if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC
+ || mVolume.getType() == VolumeInfo.TYPE_STUB) {
details.totalSize = mVolume.getPath().getTotalSpace();
details.availSize = mVolume.getPath().getUsableSpace();
return details;
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
new file mode 100644
index 0000000..04188e9
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 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.settingslib.media;
+
+import android.app.Notification;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * BluetoothMediaManager provide interface to get Bluetooth device list.
+ */
+public class BluetoothMediaManager extends MediaManager implements BluetoothCallback {
+
+ private static final String TAG = "BluetoothMediaManager";
+
+ private final DeviceAttributeChangeCallback mCachedDeviceCallback =
+ new DeviceAttributeChangeCallback();
+
+ private LocalBluetoothManager mLocalBluetoothManager;
+ private LocalBluetoothProfileManager mProfileManager;
+
+ private MediaDevice mLastAddedDevice;
+ private MediaDevice mLastRemovedDevice;
+
+ BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
+ Notification notification) {
+ super(context, notification);
+
+ mLocalBluetoothManager = localBluetoothManager;
+ mProfileManager = mLocalBluetoothManager.getProfileManager();
+ }
+
+ @Override
+ public void startScan() {
+ mMediaDevices.clear();
+ mLocalBluetoothManager.getEventManager().registerCallback(this);
+ buildBluetoothDeviceList();
+ dispatchDeviceListAdded();
+ }
+
+ private void buildBluetoothDeviceList() {
+ addConnectedA2dpDevices();
+ addConnectedHearingAidDevices();
+ }
+
+ private void addConnectedA2dpDevices() {
+ final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+ if (a2dpProfile == null) {
+ Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
+ return;
+ }
+ final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
+ final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
+ mLocalBluetoothManager.getCachedDeviceManager();
+
+ for (BluetoothDevice device : devices) {
+ final CachedBluetoothDevice cachedDevice =
+ cachedBluetoothDeviceManager.findDevice(device);
+
+ if (cachedDevice == null) {
+ Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
+ continue;
+ }
+
+ Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
+ + ", is connected : " + cachedDevice.isConnected());
+
+ if (cachedDevice.isConnected()) {
+ addMediaDevice(cachedDevice);
+ }
+ }
+ }
+
+ private void addConnectedHearingAidDevices() {
+ final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+ if (hapProfile == null) {
+ Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
+ return;
+ }
+ final List<Long> devicesHiSyncIds = new ArrayList<>();
+ final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
+ final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
+ mLocalBluetoothManager.getCachedDeviceManager();
+
+ for (BluetoothDevice device : devices) {
+ final CachedBluetoothDevice cachedDevice =
+ cachedBluetoothDeviceManager.findDevice(device);
+
+ if (cachedDevice == null) {
+ Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
+ continue;
+ }
+
+ Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
+ + ", is connected : " + cachedDevice.isConnected());
+ final long hiSyncId = hapProfile.getHiSyncId(device);
+
+ // device with same hiSyncId should not be shown in the UI.
+ // So do not add it into connectedDevices.
+ if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
+ devicesHiSyncIds.add(hiSyncId);
+ addMediaDevice(cachedDevice);
+ }
+ }
+ }
+
+ private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
+ MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
+ if (mediaDevice == null) {
+ mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
+ cachedDevice.registerCallback(mCachedDeviceCallback);
+ mLastAddedDevice = mediaDevice;
+ mMediaDevices.add(mediaDevice);
+ }
+ }
+
+ @Override
+ public void stopScan() {
+ mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+ unregisterCachedDeviceCallback();
+ }
+
+ private void unregisterCachedDeviceCallback() {
+ for (MediaDevice device : mMediaDevices) {
+ if (device instanceof BluetoothMediaDevice) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mCachedDeviceCallback);
+ }
+ }
+ }
+
+ @Override
+ public void onBluetoothStateChanged(int bluetoothState) {
+ if (BluetoothAdapter.STATE_ON == bluetoothState) {
+ buildBluetoothDeviceList();
+ dispatchDeviceListAdded();
+ } else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
+ final List<MediaDevice> removeDevicesList = new ArrayList<>();
+ for (MediaDevice device : mMediaDevices) {
+ if (device instanceof BluetoothMediaDevice) {
+ ((BluetoothMediaDevice) device).getCachedDevice()
+ .unregisterCallback(mCachedDeviceCallback);
+ removeDevicesList.add(device);
+ }
+ }
+ mMediaDevices.removeAll(removeDevicesList);
+ dispatchDeviceListRemoved(removeDevicesList);
+ }
+ }
+
+ @Override
+ public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
+ if (isCachedDeviceConnected(cachedDevice)) {
+ addMediaDevice(cachedDevice);
+ dispatchDeviceAdded(cachedDevice);
+ }
+ }
+
+ private boolean isCachedDeviceConnected(CachedBluetoothDevice cachedDevice) {
+ final boolean isConnectedHearingAidDevice = cachedDevice.isConnectedHearingAidDevice();
+ final boolean isConnectedA2dpDevice = cachedDevice.isConnectedA2dpDevice();
+ Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice.getName()
+ + ", is hearing aid connected : " + isConnectedHearingAidDevice
+ + ", is a2dp connected : " + isConnectedA2dpDevice);
+
+ return isConnectedHearingAidDevice || isConnectedA2dpDevice;
+ }
+
+ private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
+ if (mLastAddedDevice != null
+ && MediaDeviceUtils.getId(cachedDevice) == mLastAddedDevice.getId()) {
+ dispatchDeviceAdded(mLastAddedDevice);
+ }
+ }
+
+ @Override
+ public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+ if (!isCachedDeviceConnected(cachedDevice)) {
+ removeMediaDevice(cachedDevice);
+ dispatchDeviceRemoved(cachedDevice);
+ }
+ }
+
+ private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
+ final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
+ if (mediaDevice != null) {
+ cachedDevice.unregisterCallback(mCachedDeviceCallback);
+ mLastRemovedDevice = mediaDevice;
+ mMediaDevices.remove(mediaDevice);
+ }
+ }
+
+ void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
+ if (mLastRemovedDevice != null
+ && MediaDeviceUtils.getId(cachedDevice) == mLastRemovedDevice.getId()) {
+ dispatchDeviceRemoved(mLastRemovedDevice);
+ }
+ }
+
+ @Override
+ public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+ int bluetoothProfile) {
+ Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice.getName()
+ + ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
+
+ if (isCachedDeviceConnected(cachedDevice)) {
+ addMediaDevice(cachedDevice);
+ dispatchDeviceAdded(cachedDevice);
+ } else {
+ removeMediaDevice(cachedDevice);
+ dispatchDeviceRemoved(cachedDevice);
+ }
+ }
+
+ @Override
+ public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+ Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice.getName()
+ + ", state: " + state);
+
+ if (isCachedDeviceConnected(cachedDevice)) {
+ addMediaDevice(cachedDevice);
+ dispatchDeviceAdded(cachedDevice);
+ } else {
+ removeMediaDevice(cachedDevice);
+ dispatchDeviceRemoved(cachedDevice);
+ }
+ }
+
+ class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
+ @Override
+ public void onDeviceAttributesChanged() {
+ dispatchDeviceAttributesChanged();
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
new file mode 100644
index 0000000..6907238
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 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.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.mediarouter.media.MediaRouteSelector;
+import androidx.mediarouter.media.MediaRouter;
+
+/**
+ * InfoMediaManager provide interface to get InfoMediaDevice list.
+ */
+public class InfoMediaManager extends MediaManager {
+
+ private static final String TAG = "InfoMediaManager";
+
+ private final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
+
+ private MediaRouter mMediaRouter;
+ private String mPackageName;
+
+ InfoMediaManager(Context context, String packageName, Notification notification) {
+ super(context, notification);
+
+ mMediaRouter = MediaRouter.getInstance(context);
+ mPackageName = packageName;
+ }
+
+ @Override
+ public void startScan() {
+ mMediaDevices.clear();
+ startScanCastDevice();
+ }
+
+ private void startScanCastDevice() {
+ final MediaRouteSelector selector = new MediaRouteSelector.Builder()
+ .addControlCategory(getControlCategoryByPackageName(mPackageName))
+ .build();
+
+ mMediaRouter.addCallback(selector, mMediaRouterCallback,
+ MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+ }
+
+ private String getControlCategoryByPackageName(String packageName) {
+ //TODO(b/117129183): Use package name to get ControlCategory.
+ //Since api not ready, return fixed ControlCategory for prototype.
+ return "com.google.android.gms.cast.CATEGORY_CAST/4F8B3483";
+ }
+
+ @Override
+ public void stopScan() {
+ mMediaRouter.removeCallback(mMediaRouterCallback);
+ }
+
+ class MediaRouterCallback extends MediaRouter.Callback {
+ @Override
+ public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
+ MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
+ if (mediaDevice == null) {
+ mediaDevice = new InfoMediaDevice(mContext, route);
+ Log.d(TAG, "onRouteAdded() route : " + route.getName());
+ mMediaDevices.add(mediaDevice);
+ dispatchDeviceAdded(mediaDevice);
+ }
+ }
+
+ @Override
+ public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
+ final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
+ if (mediaDevice != null) {
+ Log.d(TAG, "onRouteRemoved() route : " + route.getName());
+ mMediaDevices.remove(mediaDevice);
+ dispatchDeviceRemoved(mediaDevice);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
new file mode 100644
index 0000000..e375ea0
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 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.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.IntDef;
+
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
+ */
+public class LocalMediaManager implements BluetoothCallback {
+
+ private static final String TAG = "LocalMediaManager";
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({MediaDeviceState.STATE_CONNECTED,
+ MediaDeviceState.STATE_CONNECTING,
+ MediaDeviceState.STATE_DISCONNECTED})
+ public @interface MediaDeviceState {
+ int STATE_CONNECTED = 1;
+ int STATE_CONNECTING = 2;
+ int STATE_DISCONNECTED = 3;
+ }
+
+ private final Collection<DeviceCallback> mCallbacks = new ArrayList<>();
+ private final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
+
+ private Context mContext;
+ private List<MediaDevice> mMediaDevices = new ArrayList<>();
+ private BluetoothMediaManager mBluetoothMediaManager;
+ private InfoMediaManager mInfoMediaManager;
+
+ private LocalBluetoothManager mLocalBluetoothManager;
+ private MediaDevice mLastConnectedDevice;
+ private MediaDevice mPhoneDevice;
+
+ /**
+ * Register to start receiving callbacks for MediaDevice events.
+ */
+ public void registerCallback(DeviceCallback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.add(callback);
+ }
+ }
+
+ /**
+ * Unregister to stop receiving callbacks for MediaDevice events
+ */
+ public void unregisterCallback(DeviceCallback callback) {
+ synchronized (mCallbacks) {
+ mCallbacks.remove(callback);
+ }
+ }
+
+ public LocalMediaManager(Context context, String packageName, Notification notification) {
+ mContext = context;
+ mLocalBluetoothManager =
+ LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
+ if (mLocalBluetoothManager == null) {
+ Log.e(TAG, "Bluetooth is not supported on this device");
+ return;
+ }
+
+ mBluetoothMediaManager =
+ new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
+ mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
+ }
+
+ /**
+ * Connect the MediaDevice to transfer media
+ * @param connectDevice the MediaDevice
+ */
+ public void connectDevice(MediaDevice connectDevice) {
+ if (connectDevice == mLastConnectedDevice) {
+ return;
+ }
+
+ if (mLastConnectedDevice != null) {
+ mLastConnectedDevice.disconnect();
+ }
+
+ connectDevice.connect();
+ if (connectDevice.isConnected()) {
+ mLastConnectedDevice = connectDevice;
+ }
+
+ final int state = connectDevice.isConnected()
+ ? MediaDeviceState.STATE_CONNECTED
+ : MediaDeviceState.STATE_DISCONNECTED;
+ dispatchSelectedDeviceStateChanged(connectDevice, state);
+ }
+
+ void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
+ synchronized (mCallbacks) {
+ for (DeviceCallback callback : mCallbacks) {
+ callback.onSelectedDeviceStateChanged(device, state);
+ }
+ }
+ }
+
+ /**
+ * Start scan connected MediaDevice
+ */
+ public void startScan() {
+ mMediaDevices.clear();
+ mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
+ mInfoMediaManager.registerCallback(mMediaDeviceCallback);
+ mBluetoothMediaManager.startScan();
+ mInfoMediaManager.startScan();
+ }
+
+ private void addPhoneDeviceIfNecessary() {
+ // add phone device to list if there have any Bluetooth device and cast device.
+ if (mMediaDevices.size() > 0 && !mMediaDevices.contains(mPhoneDevice)) {
+ if (mPhoneDevice == null) {
+ mPhoneDevice = new PhoneMediaDevice(mContext, mLocalBluetoothManager);
+ }
+ mMediaDevices.add(mPhoneDevice);
+ }
+ }
+
+ private void removePhoneMediaDeviceIfNecessary() {
+ // if PhoneMediaDevice is the last item in the list, remove it.
+ if (mMediaDevices.size() == 1 && mMediaDevices.contains(mPhoneDevice)) {
+ mMediaDevices.clear();
+ }
+ }
+
+ void dispatchDeviceListUpdate() {
+ synchronized (mCallbacks) {
+ for (DeviceCallback callback : mCallbacks) {
+ callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
+ }
+ }
+ }
+
+ /**
+ * Stop scan MediaDevice
+ */
+ public void stopScan() {
+ mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
+ mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
+ mBluetoothMediaManager.stopScan();
+ mInfoMediaManager.stopScan();
+ }
+
+ class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
+ @Override
+ public void onDeviceAdded(MediaDevice device) {
+ if (!mMediaDevices.contains(device)) {
+ mMediaDevices.add(device);
+ addPhoneDeviceIfNecessary();
+ dispatchDeviceListUpdate();
+ }
+ }
+
+ @Override
+ public void onDeviceListAdded(List<MediaDevice> devices) {
+ mMediaDevices.addAll(devices);
+ addPhoneDeviceIfNecessary();
+ dispatchDeviceListUpdate();
+ }
+
+ @Override
+ public void onDeviceRemoved(MediaDevice device) {
+ if (mMediaDevices.contains(device)) {
+ mMediaDevices.remove(device);
+ removePhoneMediaDeviceIfNecessary();
+ dispatchDeviceListUpdate();
+ }
+ }
+
+ @Override
+ public void onDeviceListRemoved(List<MediaDevice> devices) {
+ mMediaDevices.removeAll(devices);
+ removePhoneMediaDeviceIfNecessary();
+ dispatchDeviceListUpdate();
+ }
+
+ @Override
+ public void onDeviceAttributesChanged() {
+ dispatchDeviceListUpdate();
+ }
+ }
+
+
+ /**
+ * Callback for notifying device information updating
+ */
+ public interface DeviceCallback {
+ /**
+ * Callback for notifying device list updated.
+ *
+ * @param devices MediaDevice list
+ */
+ void onDeviceListUpdate(List<MediaDevice> devices);
+
+ /**
+ * Callback for notifying the connected device is changed.
+ *
+ * @param device the changed connected MediaDevice
+ * @param state the current MediaDevice state, the possible values are:
+ * {@link MediaDeviceState#STATE_CONNECTED},
+ * {@link MediaDeviceState#STATE_CONNECTING},
+ * {@link MediaDeviceState#STATE_DISCONNECTED}
+ */
+ void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
new file mode 100644
index 0000000..72b6b09
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 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.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MediaManager provide interface to get MediaDevice list.
+ */
+public abstract class MediaManager {
+
+ private static final String TAG = "MediaManager";
+
+ protected final Collection<MediaDeviceCallback> mCallbacks = new ArrayList<>();
+ protected final List<MediaDevice> mMediaDevices = new ArrayList<>();
+
+ protected Context mContext;
+ protected Notification mNotification;
+
+ MediaManager(Context context, Notification notification) {
+ mContext = context;
+ mNotification = notification;
+ }
+
+ protected void registerCallback(MediaDeviceCallback callback) {
+ synchronized (mCallbacks) {
+ if (!mCallbacks.contains(callback)) {
+ mCallbacks.add(callback);
+ }
+ }
+ }
+
+ protected void unregisterCallback(MediaDeviceCallback callback) {
+ synchronized (mCallbacks) {
+ if (mCallbacks.contains(callback)) {
+ mCallbacks.remove(callback);
+ }
+ }
+ }
+
+ /**
+ * Start scan connected MediaDevice
+ */
+ public abstract void startScan();
+
+ /**
+ * Stop scan MediaDevice
+ */
+ public abstract void stopScan();
+
+ protected MediaDevice findMediaDevice(String id) {
+ for (MediaDevice mediaDevice : mMediaDevices) {
+ if (mediaDevice.getId().equals(id)) {
+ return mediaDevice;
+ }
+ }
+ Log.e(TAG, "findMediaDevice() can't found device");
+ return null;
+ }
+
+ protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceAdded(mediaDevice);
+ }
+ }
+ }
+
+ protected void dispatchDeviceRemoved(MediaDevice mediaDevice) {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceRemoved(mediaDevice);
+ }
+ }
+ }
+
+ protected void dispatchDeviceListAdded() {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceListAdded(mMediaDevices);
+ }
+ }
+ }
+
+ protected void dispatchDeviceListRemoved(List<MediaDevice> devices) {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceListRemoved(devices);
+ }
+ }
+ }
+
+ protected void dispatchDeviceAttributesChanged() {
+ synchronized (mCallbacks) {
+ for (MediaDeviceCallback callback : mCallbacks) {
+ callback.onDeviceAttributesChanged();
+ }
+ }
+ }
+
+ /**
+ * Callback for notifying device is added, removed and attributes changed.
+ */
+ public interface MediaDeviceCallback {
+ /**
+ * Callback for notifying MediaDevice is added.
+ *
+ * @param device the MediaDevice
+ */
+ void onDeviceAdded(MediaDevice device);
+
+ /**
+ * Callback for notifying MediaDevice list is added.
+ *
+ * @param devices the MediaDevice list
+ */
+ void onDeviceListAdded(List<MediaDevice> devices);
+
+ /**
+ * Callback for notifying MediaDevice is removed.
+ *
+ * @param device the MediaDevice
+ */
+ void onDeviceRemoved(MediaDevice device);
+
+ /**
+ * Callback for notifying MediaDevice list is removed.
+ *
+ * @param devices the MediaDevice list
+ */
+ void onDeviceListRemoved(List<MediaDevice> devices);
+
+ /**
+ * Callback for notifying MediaDevice attributes is changed.
+ */
+ void onDeviceAttributesChanged();
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index fa59688..43c97df 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -81,6 +81,30 @@
return null;
}
+ /**
+ * Method to produce a shortened string describing the remaining battery. Suitable for Quick
+ * Settings and other areas where space is constrained.
+ *
+ * @param context context to fetch descriptions from
+ * @param drainTimeMs The estimated time remaining before the phone dies in milliseconds.
+ *
+ * @return a properly formatted and localized short string describing how much time remains
+ * before the battery runs out.
+ */
+ @Nullable
+ public static String getBatteryRemainingShortStringFormatted(
+ Context context, long drainTimeMs) {
+ if (drainTimeMs <= 0) {
+ return null;
+ }
+
+ if (drainTimeMs <= ONE_DAY_MILLIS) {
+ return getRegularTimeRemainingShortString(context, drainTimeMs);
+ } else {
+ return getMoreThanOneDayShortString(context, drainTimeMs);
+ }
+ }
+
private static String getShutdownImminentString(Context context, String percentageString) {
return TextUtils.isEmpty(percentageString)
? context.getString(R.string.power_remaining_duration_only_shutdown_imminent)
@@ -120,6 +144,14 @@
}
}
+ private static String getMoreThanOneDayShortString(Context context, long drainTimeMs) {
+ final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
+ CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
+ false /* withSeconds */);
+
+ return context.getString(R.string.power_remaining_duration_only_short, timeString);
+ }
+
private static String getMoreThanTwoDaysString(Context context, String percentageString) {
final Locale currentLocale = context.getResources().getConfiguration().getLocales().get(0);
final MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.SHORT);
@@ -162,6 +194,22 @@
}
}
+ private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
+ // Get the time of day we think device will die rounded to the nearest 15 min.
+ final long roundedTimeOfDayMs =
+ roundTimeToNearestThreshold(
+ System.currentTimeMillis() + drainTimeMs,
+ FIFTEEN_MINUTES_MILLIS);
+
+ // convert the time to a properly formatted string.
+ String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+ DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+ Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+ CharSequence timeString = fmt.format(date);
+
+ return context.getString(R.string.power_discharge_by_only_short, timeString);
+ }
+
public static long convertUsToMs(long timeUs) {
return timeUs / 1000;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 448a963..cbb6e82 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -572,6 +572,15 @@
GlobalSettingsProto.Dropbox.SETTINGS);
p.end(dropboxToken);
+ final long dynamicPowerSavingsToken = p.start(GlobalSettingsProto.DYNAMIC_POWER_SAVINGS);
+ dumpSetting(s, p,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+ GlobalSettingsProto.DynamicPowerSavings.DISABLE_THRESHOLD);
+ dumpSetting(s, p,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+ GlobalSettingsProto.DynamicPowerSavings.ENABLED);
+ p.end(dynamicPowerSavingsToken);
+
final long emergencyToken = p.start(GlobalSettingsProto.EMERGENCY);
dumpSetting(s, p,
Settings.Global.EMERGENCY_TONE,
@@ -794,6 +803,9 @@
dumpSetting(s, p,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
GlobalSettingsProto.LowPowerMode.TRIGGER_LEVEL_MAX);
+ dumpSetting(s, p,
+ Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+ GlobalSettingsProto.LowPowerMode.AUTOMATIC_POWER_SAVER_MODE);
p.end(lpmToken);
dumpSetting(s, p,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 822c39b..89690fb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -83,6 +83,7 @@
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
+ <uses-permission android:name="android.permission.POWER_SAVER" />
<uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
<uses-permission android:name="android.permission.BACKUP" />
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
diff --git a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
new file mode 100644
index 0000000..311f30bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 67c0adf..5ca34b0 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -14,157 +14,169 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="bottom"
- android:background="@color/biometric_dialog_dim_color"
- android:orientation="vertical">
+ android:layout_height="match_parent">
- <!-- This is not a Space since Spaces cannot be clicked -->
- <View
- android:id="@+id/space"
+ <ImageView
+ android:id="@+id/background"
android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
+ android:layout_height="match_parent"
+ android:scaleType="center" />
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:layout_height="match_parent"
+ android:gravity="bottom"
+ android:background="@color/biometric_dialog_dim_color"
+ android:orientation="vertical">
- <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
- on horizontal/portrait orientation -->
+ <!-- This is not a Space since Spaces cannot be clicked -->
<View
- android:id="@+id/left_space"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="match_parent"/>
+ android:id="@+id/space"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
<LinearLayout
- android:id="@+id/dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@drawable/biometric_dialog_bg"
- android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
- android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
- android:layout_marginRight="@dimen/biometric_dialog_border_padding">
+ android:orientation="horizontal">
- <TextView
- android:id="@+id/title"
- android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:layout_marginTop="24dp"
- android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="20sp"
- android:maxLines="1"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <TextView
- android:id="@+id/subtitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginStart="24dp"
- android:layout_marginEnd="24dp"
- android:gravity="@integer/biometric_dialog_text_gravity"
- android:textSize="16sp"
- android:maxLines="1"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:marqueeRepeatLimit="marquee_forever"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <TextView
- android:id="@+id/description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:gravity="@integer/biometric_dialog_text_gravity"
- android:paddingTop="8dp"
- android:textSize="16sp"
- android:maxLines="4"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <ImageView
- android:id="@+id/biometric_icon"
- android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
- android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
- android:layout_gravity="center_horizontal"
- android:layout_marginTop="48dp"
- android:scaleType="fitXY" />
-
- <TextView
- android:id="@+id/error"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="24dp"
- android:layout_marginStart="24dp"
- android:paddingTop="16dp"
- android:paddingBottom="24dp"
- android:textSize="12sp"
- android:gravity="center_horizontal"
- android:accessibilityLiveRegion="polite"
- android:contentDescription="@string/accessibility_biometric_dialog_help_area"
- android:textColor="?android:attr/textColorSecondary"/>
+ <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+ on horizontal/portrait orientation -->
+ <View
+ android:id="@+id/left_space"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"/>
<LinearLayout
+ android:id="@+id/dialog"
android:layout_width="match_parent"
- android:layout_height="72dip"
- android:paddingTop="24dp"
- android:layout_gravity="center_vertical"
- style="?android:attr/buttonBarStyle"
- android:orientation="horizontal"
- android:measureWithLargestChild="true">
- <Space android:id="@+id/leftSpacer"
- android:layout_width="12dp"
- android:layout_height="match_parent"
- android:visibility="visible" />
- <!-- Negative Button -->
- <Button android:id="@+id/button2"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
- android:gravity="center"
- android:maxLines="2" />
- <Space android:id="@+id/middleSpacer"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:visibility="visible" />
- <!-- Positive Button -->
- <Button android:id="@+id/button1"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- style="@*android:style/Widget.DeviceDefault.Button.Colored"
- android:gravity="center"
- android:maxLines="2"
- android:text="@string/biometric_dialog_confirm"
- android:visibility="gone"/>
- <Space android:id="@+id/rightSpacer"
- android:layout_width="12dip"
- android:layout_height="match_parent"
- android:visibility="visible" />
- </LinearLayout>
- </LinearLayout>
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:background="@drawable/biometric_dialog_bg"
+ android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+ android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+ android:layout_marginRight="@dimen/biometric_dialog_border_padding">
- <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
- on horizontal/portrait orientation -->
- <View
- android:id="@+id/right_space"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="match_parent" />
+ <TextView
+ android:id="@+id/title"
+ android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginTop="24dp"
+ android:gravity="@integer/biometric_dialog_text_gravity"
+ android:textSize="20sp"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/subtitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
+ android:gravity="@integer/biometric_dialog_text_gravity"
+ android:textSize="16sp"
+ android:maxLines="1"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:gravity="@integer/biometric_dialog_text_gravity"
+ android:paddingTop="8dp"
+ android:textSize="16sp"
+ android:maxLines="4"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <ImageView
+ android:id="@+id/biometric_icon"
+ android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+ android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="48dp"
+ android:scaleType="fitXY" />
+
+ <TextView
+ android:id="@+id/error"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="24dp"
+ android:layout_marginStart="24dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="24dp"
+ android:textSize="12sp"
+ android:gravity="center_horizontal"
+ android:accessibilityLiveRegion="polite"
+ android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+ android:textColor="?android:attr/textColorSecondary"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="72dip"
+ android:paddingTop="24dp"
+ android:layout_gravity="center_vertical"
+ style="?android:attr/buttonBarStyle"
+ android:orientation="horizontal"
+ android:measureWithLargestChild="true">
+ <Space android:id="@+id/leftSpacer"
+ android:layout_width="12dp"
+ android:layout_height="match_parent"
+ android:visibility="visible" />
+ <!-- Negative Button -->
+ <Button android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+ android:gravity="center"
+ android:maxLines="2" />
+ <Space android:id="@+id/middleSpacer"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="visible" />
+ <!-- Positive Button -->
+ <Button android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@*android:style/Widget.DeviceDefault.Button.Colored"
+ android:gravity="center"
+ android:maxLines="2"
+ android:text="@string/biometric_dialog_confirm"
+ android:visibility="gone"/>
+ <Space android:id="@+id/rightSpacer"
+ android:layout_width="12dip"
+ android:layout_height="match_parent"
+ android:visibility="visible" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+ on horizontal/portrait orientation -->
+ <View
+ android:id="@+id/right_space"
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent" />
+
+ </LinearLayout>
</LinearLayout>
-</LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 5e952e3..ddefb6a 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -21,7 +21,8 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="@dimen/ongoing_appops_chip_margin"
- android:gravity="center_vertical|end"
+ android:gravity="center_vertical|center_horizontal"
+ android:layout_gravity="center_vertical|end"
android:orientation="horizontal"
android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
@@ -32,13 +33,17 @@
android:id="@+id/icons_container"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:gravity="center_vertical|start"
+ android:layout_gravity="center_vertical|start"
+ android:gravity="center_vertical"
/>
<TextView
android:id="@+id/app_name"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:gravity="center_vertical|end"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_gravity="center_vertical|end"
+ android:gravity="center_vertical"
/>
</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 94189bb..2000104 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -42,6 +42,20 @@
android:id="@+id/statusIcons"
android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_weight="1" />
+ android:layout_weight="1"
+ android:paddingEnd="@dimen/signal_cluster_battery_padding" />
+
+ <com.android.systemui.BatteryMeterView
+ android:id="@+id/batteryRemainingIcon"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:paddingEnd="2dp" />
+
+ <TextView
+ android:id="@+id/batteryRemainingText"
+ android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:gravity="center_vertical" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 007070e..e7f2c51 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -27,6 +27,13 @@
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end" >
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_vertical|start" >
+
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:layout_width="wrap_content"
@@ -38,13 +45,21 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
systemui:showDark="false" />
+ </LinearLayout>
<android.widget.Space
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:layout_gravity="center_vertical|center_horizontal"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical|center_horizontal" />
+ android:orientation="horizontal"
+ android:gravity="center_vertical|end">
<include layout="@layout/ongoing_privacy_chip" />
@@ -53,4 +68,5 @@
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:gravity="center_vertical|end" />
+ </LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index f6fec54..053ea67 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -19,7 +19,10 @@
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.animation.ArgbEvaluator;
+import android.annotation.IntDef;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
@@ -55,15 +58,23 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.Utils.DisableStateTracker;
-import com.android.systemui.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
import java.text.NumberFormat;
public class BatteryMeterView extends LinearLayout implements
BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
+
+ @Retention(SOURCE)
+ @IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF})
+ public @interface BatteryPercentMode {}
+ public static final int MODE_DEFAULT = 0;
+ public static final int MODE_ON = 1;
+ public static final int MODE_OFF = 2;
+
private final BatteryMeterDrawableBase mDrawable;
private final String mSlotBattery;
private final ImageView mBatteryIconView;
@@ -74,6 +85,7 @@
private SettingObserver mSettingObserver;
private int mTextColor;
private int mLevel;
+ private int mShowPercentMode = MODE_DEFAULT;
private boolean mForceShowPercent;
private boolean mShowPercentAvailable;
@@ -154,7 +166,19 @@
}
public void setForceShowPercent(boolean show) {
- mForceShowPercent = show;
+ setPercentShowMode(show ? MODE_ON : MODE_DEFAULT);
+ }
+
+ /**
+ * Force a particular mode of showing percent
+ *
+ * 0 - No preference
+ * 1 - Force on
+ * 2 - Force off
+ * @param mode desired mode (none, on, off)
+ */
+ public void setPercentShowMode(@BatteryPercentMode int mode) {
+ mShowPercentMode = mode;
updateShowPercent();
}
@@ -273,7 +297,8 @@
.getIntForUser(getContext().getContentResolver(),
SHOW_BATTERY_PERCENT, 0, mUser);
- if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) {
+ if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
+ || mShowPercentMode == MODE_ON) {
if (!showing) {
mBatteryPercentView = loadPercentView();
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 67bc8b6..c0047c0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -140,7 +140,7 @@
@Override
public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation) {
+ boolean requireConfirmation, int userId) {
if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
// Remove these messages as they are part of the previous client
mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
@@ -151,6 +151,7 @@
args.arg2 = receiver;
args.argi1 = type;
args.arg3 = requireConfirmation;
+ args.argi2 = userId;
mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
}
@@ -194,7 +195,8 @@
}
mReceiver = (IBiometricPromptReceiver) args.arg2;
mCurrentDialog.setBundle((Bundle)args.arg1);
- mCurrentDialog.setRequireConfirmation((boolean)args.arg3);
+ mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
+ mCurrentDialog.setUserId(args.argi2);
mCurrentDialog.setSkipIntro(skipAnimation);
mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
mDialogShowing = true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 1faae9d..38427ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -16,15 +16,19 @@
package com.android.systemui.biometrics;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricPrompt;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -64,6 +68,8 @@
private final IBinder mWindowToken = new Binder();
private final Interpolator mLinearOutSlowIn;
private final WindowManager mWindowManager;
+ private final UserManager mUserManager;
+ private final DevicePolicyManager mDevicePolicyManager;
private final float mAnimationTranslationOffset;
private final int mErrorColor;
private final int mTextColor;
@@ -79,6 +85,7 @@
private boolean mWasForceRemoved;
private boolean mSkipIntro;
protected boolean mRequireConfirmation;
+ private int mUserId; // used to determine if we should show work background
protected abstract void updateIcon(int lastState, int newState);
protected abstract int getHintStringResourceId();
@@ -121,7 +128,9 @@
super(context);
mCallback = callback;
mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
mAnimationTranslationOffset = getResources()
.getDimension(R.dimen.biometric_dialog_animation_translation_offset);
@@ -199,6 +208,18 @@
final TextView description = mLayout.findViewById(R.id.description);
final Button negative = mLayout.findViewById(R.id.button2);
final Button positive = mLayout.findViewById(R.id.button1);
+ final ImageView backgroundView = mLayout.findViewById(R.id.background);
+
+ if (mUserManager.isManagedProfile(mUserId)) {
+ final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
+ mContext.getTheme());
+ image.setColorFilter(mDevicePolicyManager.getOrganizationColorForUser(mUserId),
+ PorterDuff.Mode.DARKEN);
+ backgroundView.setImageDrawable(image);
+ } else {
+ backgroundView.setImageDrawable(null);
+ backgroundView.setBackgroundColor(R.color.biometric_dialog_dim_color);
+ }
if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
mDialog.getLayoutParams().width = (int) mDialogWidth;
@@ -329,6 +350,10 @@
positive.setVisibility(View.VISIBLE);
}
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
public ViewGroup getLayout() {
return mLayout;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
index 30dfd36..4a2e06c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
@@ -22,11 +22,6 @@
public interface DozeReceiver {
/**
- * If device enters or leaves doze mode
- */
- void setDozing(boolean dozing);
-
- /**
* Invoked every time a minute is elapsed in doze mode
*/
void dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 3953139d..fc1baef 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -14,21 +14,14 @@
package com.android.systemui.privacy
-import android.app.ActivityManager
-import android.app.AppOpsManager
import android.content.Context
import android.graphics.Color
-import android.os.UserHandle
-import android.os.UserManager
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
-import com.android.systemui.Dependency
import com.android.systemui.R
-import com.android.systemui.appops.AppOpItem
-import com.android.systemui.appops.AppOpsController
class OngoingPrivacyChip @JvmOverloads constructor(
context: Context,
@@ -37,37 +30,15 @@
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
- companion object {
- val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
- AppOpsManager.OP_RECORD_AUDIO,
- AppOpsManager.OP_COARSE_LOCATION,
- AppOpsManager.OP_FINE_LOCATION)
- }
-
private lateinit var appName: TextView
private lateinit var iconsContainer: LinearLayout
- private var privacyList = emptyList<PrivacyItem>()
- private val appOpsController = Dependency.get(AppOpsController::class.java)
- private val userManager = context.getSystemService(UserManager::class.java)
- private val currentUser = ActivityManager.getCurrentUser()
- private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
- private var listening = false
-
- var builder = PrivacyDialogBuilder(context, privacyList)
-
- private val callback = object : AppOpsController.Callback {
- override fun onActiveStateChanged(
- code: Int,
- uid: Int,
- packageName: String,
- active: Boolean
- ) {
- val userId = UserHandle.getUserId(uid)
- if (userId in currentUserIds) {
- updatePrivacyList()
- }
+ var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
+ var privacyList = emptyList<PrivacyItem>()
+ set(value) {
+ field = value
+ builder = PrivacyDialogBuilder(context, value)
+ updateView()
}
- }
override fun onFinishInflate() {
super.onFinishInflate()
@@ -76,36 +47,6 @@
iconsContainer = findViewById(R.id.icons_container)
}
- fun setListening(listen: Boolean) {
- if (listening == listen) return
- listening = listen
- if (listening) {
- appOpsController.addCallback(OPS, callback)
- updatePrivacyList()
- } else {
- appOpsController.removeCallback(OPS, callback)
- }
- }
-
- private fun updatePrivacyList() {
- privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
- .mapNotNull { toPrivacyItem(it) }
- builder = PrivacyDialogBuilder(context, privacyList)
- updateView()
- }
-
- private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
- val type: PrivacyType = when (appOpItem.code) {
- AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
- AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
- AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
- AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
- else -> return null
- }
- val app = PrivacyApplication(appOpItem.packageName, context)
- return PrivacyItem(type, app, appOpItem.timeStarted)
- }
-
// Should only be called if the builder icons or app changed
private fun updateView() {
fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
@@ -121,11 +62,9 @@
}
if (privacyList.isEmpty()) {
- visibility = GONE
return
} else {
generateContentDescription()
- visibility = VISIBLE
setIcons(builder, iconsContainer)
appName.visibility = GONE
builder.app?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
new file mode 100644
index 0000000..5141e50
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -0,0 +1,105 @@
+/*
+ * 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.systemui.privacy
+
+import android.app.ActivityManager
+import android.app.AppOpsManager
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import android.os.UserManager
+import com.android.systemui.Dependency
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+
+class PrivacyItemController(val context: Context, val callback: Callback) {
+
+ companion object {
+ val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_FINE_LOCATION)
+ }
+
+ private var privacyList = emptyList<PrivacyItem>()
+ private val appOpsController = Dependency.get(AppOpsController::class.java)
+ private val userManager = context.getSystemService(UserManager::class.java)
+ private val currentUser = ActivityManager.getCurrentUser()
+ private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
+ private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER))
+ private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER)
+ private val notifyChanges = Runnable {
+ callback.privacyChanged(privacyList)
+ }
+ private val updateListAndNotifyChanges = Runnable {
+ updatePrivacyList()
+ uiHandler.post(notifyChanges)
+ }
+
+ private var listening = false
+
+ private val cb = object : AppOpsController.Callback {
+ override fun onActiveStateChanged(
+ code: Int,
+ uid: Int,
+ packageName: String,
+ active: Boolean
+ ) {
+ val userId = UserHandle.getUserId(uid)
+ if (userId in currentUserIds) {
+ update()
+ }
+ }
+ }
+
+ private fun update() {
+ bgHandler.post(updateListAndNotifyChanges)
+ }
+
+ fun setListening(listen: Boolean) {
+ if (listening == listen) return
+ listening = listen
+ if (listening) {
+ appOpsController.addCallback(OPS, cb)
+ update()
+ } else {
+ appOpsController.removeCallback(OPS, cb)
+ }
+ }
+
+ private fun updatePrivacyList() {
+ privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
+ .mapNotNull { toPrivacyItem(it) }
+ }
+
+ private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
+ val type: PrivacyType = when (appOpItem.code) {
+ AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
+ AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
+ AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
+ AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
+ else -> return null
+ }
+ val app = PrivacyApplication(appOpItem.packageName, context)
+ return PrivacyItem(type, app, appOpItem.timeStarted)
+ }
+
+ // Used by containing class to get notified of changes
+ interface Callback {
+ fun privacyChanged(privacyItems: List<PrivacyItem>)
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 3ee6195..e3f85d9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -15,6 +15,7 @@
package com.android.systemui.qs;
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -28,23 +29,29 @@
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.Color;
import android.graphics.Rect;
import android.media.AudioManager;
+import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.AlarmClock;
+import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
+import android.view.DisplayCutout;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.RelativeLayout;
+import android.widget.Space;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
@@ -57,12 +64,15 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.privacy.OngoingPrivacyDialog;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.QSDetail.Callback;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
@@ -70,6 +80,7 @@
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -125,9 +136,14 @@
private Clock mClockView;
private DateView mDateView;
private OngoingPrivacyChip mPrivacyChip;
+ private Space mSpace;
+ private BatteryMeterView mBatteryRemainingIcon;
+ private TextView mBatteryRemainingText;
+ private boolean mShowBatteryPercentAndEstimate;
private NextAlarmController mAlarmController;
private ZenModeController mZenController;
+ private PrivacyItemController mPrivacyItemController;
/** Counts how many times the long press tooltip has been shown to the user. */
private int mShownCount;
@@ -138,16 +154,29 @@
updateStatusText();
}
};
+ private boolean mHasTopCutout = false;
+
+ private final PercentSettingObserver mPercentSettingObserver =
+ new PercentSettingObserver(new Handler(mContext.getMainLooper()));
/**
* Runnable for automatically fading out the long press tooltip (as if it were animating away).
*/
private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
+ private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
+ @Override
+ public void privacyChanged(List<PrivacyItem> privacyItems) {
+ mPrivacyChip.setPrivacyList(privacyItems);
+ setChipVisibility(!privacyItems.isEmpty());
+ }
+ };
+
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
mAlarmController = Dependency.get(NextAlarmController.class);
mZenController = Dependency.get(ZenModeController.class);
+ mPrivacyItemController = new PrivacyItemController(context, mPICCallback);
mShownCount = getStoredShownCount();
}
@@ -186,14 +215,28 @@
// Set the correct tint for the status icons so they contrast
mIconManager.setTint(fillColor);
+ mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_battery_percentage_setting_available);
+
mBatteryMeterView = findViewById(R.id.battery);
- mBatteryMeterView.setForceShowPercent(true);
+ mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate
+ ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF);
mBatteryMeterView.setOnClickListener(this);
mClockView = findViewById(R.id.clock);
mClockView.setOnClickListener(this);
mDateView = findViewById(R.id.date);
mPrivacyChip = findViewById(R.id.privacy_chip);
mPrivacyChip.setOnClickListener(this);
+ mSpace = findViewById(R.id.space);
+
+ // Tint for the battery icons are handled in setupHost()
+ mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
+ mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF);
+
+ mBatteryRemainingText = findViewById(R.id.batteryRemainingText);
+ mBatteryRemainingText.setTextColor(fillColor);
+
+ updateShowPercent();
}
private void updateStatusText() {
@@ -208,6 +251,16 @@
}
}
+ private void setChipVisibility(boolean chipVisible) {
+ mBatteryMeterView.setVisibility(View.VISIBLE);
+ if (chipVisible) {
+ mPrivacyChip.setVisibility(View.VISIBLE);
+ if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE);
+ } else {
+ mPrivacyChip.setVisibility(View.GONE);
+ }
+ }
+
private boolean updateRingerStatus() {
boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
CharSequence originalRingerText = mRingerModeTextView.getText();
@@ -342,6 +395,14 @@
.build();
}
+ private void updateBatteryRemainingText() {
+ if (!mShowBatteryPercentAndEstimate) {
+ return;
+ }
+ mBatteryRemainingText.setText(
+ Dependency.get(BatteryController.class).getEstimatedTimeRemainingString());
+ }
+
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -407,12 +468,16 @@
super.onAttachedToWindow();
Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
requestApplyInsets();
+ mContext.getContentResolver().registerContentObserver(
+ Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
+ ActivityManager.getCurrentUser());
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ DisplayCutout cutout = insets.getDisplayCutout();
Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
- insets.getDisplayCutout(), getDisplay());
+ cutout, getDisplay());
if (padding == null) {
mSystemIconsView.setPaddingRelative(
getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
@@ -421,6 +486,22 @@
mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
}
+ LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
+ if (cutout != null) {
+ Rect topCutout = cutout.getBoundingRectTop();
+ if (topCutout.isEmpty()) {
+ mHasTopCutout = false;
+ lp.width = 0;
+ mSpace.setVisibility(View.GONE);
+ } else {
+ mHasTopCutout = true;
+ lp.width = topCutout.width();
+ mSpace.setVisibility(View.VISIBLE);
+ }
+ }
+ mSpace.setLayoutParams(lp);
+ // Decide whether to show BatteryMeterView
+ setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
return super.onApplyWindowInsets(insets);
}
@@ -429,6 +510,7 @@
public void onDetachedFromWindow() {
setListening(false);
Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager);
+ mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
super.onDetachedFromWindow();
}
@@ -437,7 +519,7 @@
return;
}
mHeaderQsPanel.setListening(listening);
- mPrivacyChip.setListening(listening);
+ mPrivacyItemController.setListening(listening);
mListening = listening;
if (listening) {
@@ -445,6 +527,7 @@
mAlarmController.addCallback(this);
mContext.registerReceiver(mRingerReceiver,
new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+ updateBatteryRemainingText();
} else {
mZenController.removeCallback(this);
mAlarmController.removeCallback(this);
@@ -614,6 +697,14 @@
// Use SystemUI context to get battery meter colors, and let it use the default tint (white)
mBatteryMeterView.setColorsFromContext(mHost.getContext());
mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+
+ Rect tintArea = new Rect(0, 0, 0, 0);
+ int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
+ android.R.attr.colorForeground);
+ float intensity = getColorIntensity(colorForeground);
+ int fillColor = fillColorForIntensity(intensity, getContext());
+ mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
+ mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
}
public void setCallback(Callback qsPanelCallback) {
@@ -646,4 +737,39 @@
lp.rightMargin = sideMargins;
}
}
+
+ private void updateShowPercent() {
+ final boolean systemSetting = 0 != Settings.System
+ .getIntForUser(getContext().getContentResolver(),
+ SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
+
+ mShowBatteryPercentAndEstimate = systemSetting;
+
+ updateBatteryViews();
+ }
+
+ private void updateBatteryViews() {
+ if (mShowBatteryPercentAndEstimate) {
+ mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON);
+ mBatteryRemainingIcon.setVisibility(View.VISIBLE);
+ mBatteryRemainingText.setVisibility(View.VISIBLE);
+ updateBatteryRemainingText();
+ } else {
+ mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF);
+ mBatteryRemainingIcon.setVisibility(View.GONE);
+ mBatteryRemainingText.setVisibility(View.GONE);
+ }
+ }
+
+ private final class PercentSettingObserver extends ContentObserver {
+ PercentSettingObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateShowPercent();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 7f3537c..da2828e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable;
import android.service.quicksettings.Tile;
import android.widget.Switch;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index daaefb9..0c8f487 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -27,9 +27,9 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.util.Pair;
import androidx.annotation.VisibleForTesting;
-import android.util.Pair;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
@@ -164,7 +164,7 @@
default void onRotationProposal(int rotation, boolean isValid) { }
default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
- int type, boolean requireConfirmation) { }
+ int type, boolean requireConfirmation, int userId) { }
default void onBiometricAuthenticated() { }
default void onBiometricHelp(String message) { }
default void onBiometricError(String error) { }
@@ -524,13 +524,14 @@
@Override
public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation) {
+ boolean requireConfirmation, int userId) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
args.argi1 = type;
args.arg3 = requireConfirmation;
+ args.argi2 = userId;
mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
.sendToTarget();
}
@@ -774,8 +775,9 @@
mCallbacks.get(i).showBiometricDialog(
(Bundle) someArgs.arg1,
(IBiometricPromptReceiver) someArgs.arg2,
- someArgs.argi1,
- (boolean) someArgs.arg3);
+ someArgs.argi1 /* type */,
+ (boolean) someArgs.arg3 /* requireConfirmation */,
+ someArgs.argi2 /* userId */);
}
someArgs.recycle();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 12c0fcb..eaf52cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -18,11 +18,17 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.annotation.IntDef;
-import android.util.ArraySet;
-import android.util.Log;
+import android.util.FloatProperty;
+import android.view.animation.Interpolator;
+
import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.StatusBar;
+
import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Comparator;
@@ -38,14 +44,51 @@
private static final Comparator <RankedListener> mComparator
= (o1, o2) -> Integer.compare(o1.rank, o2.rank);
+ private static final FloatProperty<StatusBarStateController> SET_DARK_AMOUNT_PROPERTY =
+ new FloatProperty<StatusBarStateController>("mDozeAmount") {
+
+ @Override
+ public void setValue(StatusBarStateController object, float value) {
+ object.setDozeAmountInternal(value);
+ }
+
+ @Override
+ public Float get(StatusBarStateController object) {
+ return object.mDozeAmount;
+ }
+ };
private final ArrayList<RankedListener> mListeners = new ArrayList<>();
- private boolean mIsDozing;
private int mState;
private int mLastState;
private boolean mLeaveOpenOnKeyguardHide;
private boolean mKeyguardRequested;
+ /**
+ * If the device is currently dozing or not.
+ */
+ private boolean mIsDozing;
+
+ /**
+ * Current {@link #mDozeAmount} animator.
+ */
+ private ValueAnimator mDarkAnimator;
+
+ /**
+ * Current doze amount in this frame.
+ */
+ private float mDozeAmount;
+
+ /**
+ * Where the animator will stop.
+ */
+ private float mDozeAmountTarget;
+
+ /**
+ * The type of interpolator that should be used to the doze animation.
+ */
+ private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+
// TODO: b/115739177 (remove this explicit ordering if we can)
@Retention(SOURCE)
@IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
@@ -94,6 +137,14 @@
return mIsDozing;
}
+ public float getDozeAmount() {
+ return mDozeAmount;
+ }
+
+ public float getInterpolatedDozeAmount() {
+ return mDozeInterpolator.getInterpolation(mDozeAmount);
+ }
+
/**
* Update the dozing state from {@link StatusBar}'s perspective
* @param isDozing well, are we dozing?
@@ -116,6 +167,51 @@
return true;
}
+ /**
+ * Changes the current doze amount.
+ *
+ * @param dozeAmount New doze/dark amount.
+ * @param animated If change should be animated or not. This will cancel current animations.
+ */
+ public void setDozeAmount(float dozeAmount, boolean animated) {
+ if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
+ if (animated && mDozeAmountTarget == dozeAmount) {
+ return;
+ } else {
+ mDarkAnimator.cancel();
+ }
+ }
+
+ mDozeAmountTarget = dozeAmount;
+ if (animated) {
+ startDozeAnimation();
+ } else {
+ setDozeAmountInternal(dozeAmount);
+ }
+ }
+
+ private void startDozeAnimation() {
+ if (mDozeAmount == 0f || mDozeAmount == 1f) {
+ mDozeInterpolator = mIsDozing
+ ? Interpolators.FAST_OUT_SLOW_IN
+ : Interpolators.TOUCH_RESPONSE_REVERSE;
+ }
+ mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozeAmountTarget);
+ mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+ mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+ mDarkAnimator.start();
+ }
+
+ private void setDozeAmountInternal(float dozeAmount) {
+ mDozeAmount = dozeAmount;
+ float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
+ synchronized (mListeners) {
+ for (RankedListener rl : new ArrayList<>(mListeners)) {
+ rl.listener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
+ }
+ }
+ }
+
public boolean goingToFullShade() {
return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
}
@@ -202,7 +298,8 @@
public interface StateListener {
/**
- * Callback before the new state is applied, for those who need to preempt the change
+ * Callback before the new state is applied, for those who need to preempt the change.
+ *
* @param oldState state before the change
* @param newState new state to be applied in {@link #onStateChanged}
*/
@@ -218,17 +315,29 @@
/**
* Required callback. Get the new state and do what you will with it. Keep in mind that
* other listeners are typically unordered and don't rely on your work being done before
- * other peers
+ * other peers.
*
- * Only called if the state is actually different
+ * Only called if the state is actually different.
+ *
* @param newState the new {@link StatusBarState}
*/
public void onStateChanged(int newState);
/**
* Callback to be notified when Dozing changes. Dozing is stored separately from state.
+ *
* @param isDozing {@code true} if dozing according to {@link StatusBar}
*/
public default void onDozingChanged(boolean isDozing) {}
+
+ /**
+ * Callback to be notified when the doze amount changes. Useful for animations.
+ * Note: this will be called for each animation frame. Please be careful to avoid
+ * performance regressions.
+ *
+ * @param linear A number from 0 to 1, where 1 means that the device is dozing.
+ * @param eased Same as {@code linear} but transformed by an interpolator.
+ */
+ default void onDozeAmountChanged(float linear, float eased) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
index fb362c5..ef042ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -26,7 +26,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import java.util.function.Consumer;
@@ -63,13 +63,14 @@
}
}
+ // TODO: this should be using StatusBarStateController#getDozeAmount
public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
boolean dark, long delay, Animator.AnimatorListener listener) {
float startIntensity = dark ? 0f : 1f;
float endIntensity = dark ? 1f : 0f;
ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
animator.addUpdateListener(updateListener);
- animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+ animator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
animator.setStartDelay(delay);
if (listener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 9daba83..7bd58203 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2312,7 +2312,7 @@
View child = getChildAt(i);
if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if (mEntryManager.getNotificationData().isHighPriority(
+ if (!mEntryManager.getNotificationData().isHighPriority(
row.getStatusBarNotification())) {
break;
} else {
@@ -4399,16 +4399,6 @@
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public long getDarkAnimationDuration(boolean dark) {
- long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
- // Longer animation when sleeping with more than 1 notification
- if (dark && getNotGoneChildCount() > 2) {
- duration *= 1.2f;
- }
- return duration;
- }
-
- @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
if (screenLocation == null || screenLocation.y < mTopPadding) {
return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index ecf6b6a..fa71df2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,7 +22,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.Fragment;
@@ -41,7 +40,6 @@
import android.os.PowerManager;
import android.os.SystemProperties;
import android.util.AttributeSet;
-import android.util.FloatProperty;
import android.util.Log;
import android.util.MathUtils;
import android.view.LayoutInflater;
@@ -51,7 +49,6 @@
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.accessibility.AccessibilityManager;
-import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -104,7 +101,7 @@
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
OnHeadsUpChangedListener, QS.HeightListener, ZenModeController.Callback,
- ConfigurationController.ConfigurationListener {
+ ConfigurationController.ConfigurationListener, StateListener {
private static final boolean DEBUG = false;
@@ -139,25 +136,9 @@
private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
- public static final long DOZE_ANIMATION_DURATION = 700;
-
private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY =
- new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") {
- @Override
- public void setValue(NotificationPanelView object, float value) {
- object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value));
- }
-
- @Override
- public Float get(NotificationPanelView object) {
- return object.mLinearDarkAmount;
- }
- };
-
- private Interpolator mDarkInterpolator;
private final PowerManager mPowerManager;
private final AccessibilityManager mAccessibilityManager;
@@ -295,11 +276,9 @@
*/
private boolean mSemiAwake;
- private float mDarkAmountTarget;
private boolean mPulsing;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mNoVisibleNotifications = true;
- private ValueAnimator mDarkAnimator;
private boolean mUserSetupComplete;
private int mQsNotificationTopPadding;
private float mExpandOffset;
@@ -339,7 +318,6 @@
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
- private final StateListener mListener = this::setBarState;
private final CommandQueue mCommandQueue;
private final NotificationLockscreenUserManager mLockscreenUserManager =
Dependency.get(NotificationLockscreenUserManager.class);
@@ -388,7 +366,7 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
- Dependency.get(StatusBarStateController.class).addListener(mListener);
+ Dependency.get(StatusBarStateController.class).addListener(this);
Dependency.get(ZenModeController.class).addCallback(this);
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -397,7 +375,7 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
- Dependency.get(StatusBarStateController.class).removeListener(mListener);
+ Dependency.get(StatusBarStateController.class).removeListener(this);
Dependency.get(ZenModeController.class).removeCallback(this);
Dependency.get(ConfigurationController.class).removeCallback(this);
}
@@ -475,7 +453,8 @@
mKeyguardBottomArea.initFrom(oldBottomArea);
addView(mKeyguardBottomArea, index);
initBottomArea();
- setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
+ onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
+ mStatusBarStateController.getInterpolatedDozeAmount());
if (mKeyguardStatusBar != null) {
mKeyguardStatusBar.onThemeChanged();
@@ -1221,7 +1200,8 @@
}
}
- private void setBarState(int statusBarState) {
+ @Override
+ public void onStateChanged(int statusBarState) {
boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
boolean keyguardFadingAway = mKeyguardMonitor.isKeyguardFadingAway();
int oldState = mBarState;
@@ -2806,24 +2786,10 @@
updateDozingVisibilities(animate);
}
- final float darkAmount = dozing ? 1 : 0;
- if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
- if (animate && mDarkAmountTarget == darkAmount) {
- return;
- } else {
- mDarkAnimator.cancel();
- }
- if (mSemiAwake) {
- setDarkAmount(0, 0);
- }
- }
- mDarkAmountTarget = darkAmount;
- if (!mSemiAwake) {
- if (animate) {
- startDarkAnimation();
- } else {
- setDarkAmount(darkAmount, darkAmount);
- }
+ final float darkAmount = dozing && !mSemiAwake ? 1 : 0;
+ mStatusBarStateController.setDozeAmount(darkAmount, animate);
+ if (animate) {
+ mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
}
}
@@ -2831,21 +2797,8 @@
return mSemiAwake;
}
- private void startDarkAnimation() {
- if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
- mDarkInterpolator = mDozing
- ? Interpolators.FAST_OUT_SLOW_IN
- : Interpolators.TOUCH_RESPONSE_REVERSE;
- }
- mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
- mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozing ? 1 : 0);
- mDarkAnimator.setInterpolator(Interpolators.LINEAR);
- mDarkAnimator.setDuration(
- mNotificationStackScroller.getDarkAnimationDuration(mDozing));
- mDarkAnimator.start();
- }
-
- private void setDarkAmount(float linearAmount, float amount) {
+ @Override
+ public void onDozeAmountChanged(float linearAmount, float amount) {
mInterpolatedDarkAmount = amount;
mLinearDarkAmount = linearAmount;
mKeyguardStatusBar.setDarkAmount(mInterpolatedDarkAmount);
@@ -3047,7 +3000,8 @@
mSemiAwake = false;
mNotificationStackScroller.setDark(false /* dark */, true /* animate */,
null /* touchLocation */);
- startDarkAnimation();
+ mStatusBarStateController.setDozeAmount(0f, true /* animated */);
+ mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
mStatusBar.updateScrimController();
return WAKE_UP_TO_SHADE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 6f4026d..f65f826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -55,4 +55,11 @@
default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {}
default void onPowerSaveChanged(boolean isPowerSave) {}
}
+
+ /**
+ * If available, get the estimated battery time remaining as a string
+ */
+ default String getEstimatedTimeRemainingString() {
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 7221efa..ddcfbf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -29,9 +29,14 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
+import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.Estimate;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.text.NumberFormat;
import java.util.ArrayList;
/**
@@ -44,7 +49,9 @@
public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
+ private final EnhancedEstimates mEstimates = Dependency.get(EnhancedEstimates.class);
private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
private final Handler mHandler;
@@ -58,6 +65,8 @@
protected boolean mAodPowerSave;
private boolean mTestmode = false;
private boolean mHasReceivedBattery = false;
+ private Estimate mEstimate;
+ private long mLastEstimateTimestamp = -1;
public BatteryControllerImpl(Context context) {
this(context, context.getSystemService(PowerManager.class));
@@ -71,6 +80,7 @@
registerReceiver();
updatePowerSave();
+ updateEstimate();
}
private void registerReceiver() {
@@ -180,6 +190,26 @@
return mAodPowerSave;
}
+ @Override
+ public String getEstimatedTimeRemainingString() {
+ if (mEstimate == null
+ || System.currentTimeMillis() > mLastEstimateTimestamp + UPDATE_GRANULARITY_MSEC) {
+ updateEstimate();
+ }
+ // Estimates may not exist yet even if we've checked
+ if (mEstimate == null) {
+ return null;
+ }
+ final String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
+ return PowerUtil.getBatteryRemainingShortStringFormatted(
+ mContext, mEstimate.estimateMillis);
+ }
+
+ private void updateEstimate() {
+ mEstimate = mEstimates.getEstimate();
+ mLastEstimateTimestamp = System.currentTimeMillis();
+ }
+
private void updatePowerSave() {
setPowerSave(mPowerManager.isPowerSaveMode());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
new file mode 100644
index 0000000..48491d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -0,0 +1,85 @@
+/*
+ * 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.systemui.privacy
+
+import android.app.AppOpsManager
+import android.os.Handler
+import android.support.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import com.android.systemui.Dependency
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+@RunWithLooper
+class PrivacyItemControllerTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var appOpsController: AppOpsController
+ @Mock
+ private lateinit var callback: PrivacyItemController.Callback
+
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var privacyItemController: PrivacyItemController
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+
+ appOpsController = mDependency.injectMockDependency(AppOpsController:: class.java)
+ mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper)
+ mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler(testableLooper.looper))
+
+ doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, 0, "", 0)))
+ .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+ privacyItemController = PrivacyItemController(mContext, callback)
+ }
+ @Test
+ fun testSetListeningTrue() {
+ privacyItemController.setListening(true)
+ verify(appOpsController).addCallback(eq(PrivacyItemController.OPS),
+ any(AppOpsController.Callback::class.java))
+ testableLooper.processAllMessages()
+ verify(callback).privacyChanged(anyList())
+ }
+
+ @Test
+ fun testSetListeningFalse() {
+ privacyItemController.setListening(true)
+ privacyItemController.setListening(false)
+ verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
+ any(AppOpsController.Callback:: class.java))
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 098fa62..dcd5946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -44,6 +44,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -55,6 +56,7 @@
* Tests for {@link NotificationSwipeHelper}.
*/
@SmallTest
+@Ignore
@RunWith(AndroidJUnit4.class)
@UiThreadTest
public class NotificationSwipeHelperTest extends SysuiTestCase {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index a947ea1..8ae5872 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6584,6 +6584,18 @@
// OS: Q
TOP_LEVEL_PRIVACY = 1587;
+ // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+ // Allow apps to override
+ // CATEGORY: SETTINGS
+ // OS: Q
+ NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+ // Allow apps to override > Choose app
+ // CATEGORY: SETTINGS
+ // OS: Q
+ NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d1fe970c..7a65a53 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -218,8 +218,8 @@
ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
final View content;
try {
- response.getPresentation().setApplyTheme(mThemeId);
- content = response.getPresentation().apply(mContext, decor, interceptionHandler);
+ content = response.getPresentation().applyWithTheme(
+ mContext, decor, interceptionHandler, mThemeId);
container.addView(content);
} catch (RuntimeException e) {
callback.onCanceled();
@@ -259,8 +259,7 @@
RemoteViews.OnClickHandler clickBlocker = null;
if (headerPresentation != null) {
clickBlocker = newClickBlocker();
- headerPresentation.setApplyTheme(mThemeId);
- mHeader = headerPresentation.apply(mContext, null, clickBlocker);
+ mHeader = headerPresentation.applyWithTheme(mContext, null, clickBlocker, mThemeId);
final LinearLayout headerContainer =
decor.findViewById(R.id.autofill_dataset_header);
if (sVerbose) Slog.v(TAG, "adding header");
@@ -277,8 +276,8 @@
if (clickBlocker == null) { // already set for header
clickBlocker = newClickBlocker();
}
- footerPresentation.setApplyTheme(mThemeId);
- mFooter = footerPresentation.apply(mContext, null, clickBlocker);
+ mFooter = footerPresentation.applyWithTheme(
+ mContext, null, clickBlocker, mThemeId);
// Footer not supported on some platform e.g. TV
if (sVerbose) Slog.v(TAG, "adding footer");
footerContainer.addView(mFooter);
@@ -304,8 +303,8 @@
final View view;
try {
if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
- presentation.setApplyTheme(mThemeId);
- view = presentation.apply(mContext, null, interceptionHandler);
+ view = presentation.applyWithTheme(
+ mContext, null, interceptionHandler, mThemeId);
} catch (RuntimeException e) {
Slog.e(TAG, "Error inflating remote views", e);
continue;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1e30c8a..843aa74 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -339,8 +339,8 @@
try {
// Create the remote view peer.
- template.setApplyTheme(mThemeId);
- final View customSubtitleView = template.apply(context, null, handler);
+ final View customSubtitleView = template.applyWithTheme(
+ context, null, handler, mThemeId);
// Apply batch updates (if any).
final ArrayList<Pair<InternalValidator, BatchUpdates>> updates =
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 5b3ab85..78e82b6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1235,6 +1235,9 @@
} else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
+ } else if (vol.type == VolumeInfo.TYPE_STUB) {
+ vol.mountUserId = mCurrentUserId;
+ mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
} else {
Slog.d(TAG, "Skipping automatic mounting of " + vol);
}
@@ -1245,6 +1248,7 @@
case VolumeInfo.TYPE_PRIVATE:
case VolumeInfo.TYPE_PUBLIC:
case VolumeInfo.TYPE_EMULATED:
+ case VolumeInfo.TYPE_STUB:
break;
default:
return false;
@@ -1321,7 +1325,8 @@
}
}
- if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
+ if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
+ && vol.state == VolumeInfo.STATE_EJECTING) {
// TODO: this should eventually be handled by new ObbVolume state changes
/*
* Some OBBs might have been unmounted when this volume was
@@ -1403,7 +1408,8 @@
}
boolean isTypeRestricted = false;
- if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
+ if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
+ || vol.type == VolumeInfo.TYPE_STUB) {
isTypeRestricted = userManager
.hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
Binder.getCallingUserHandle());
@@ -2834,6 +2840,7 @@
final VolumeInfo vol = mVolumes.valueAt(i);
switch (vol.getType()) {
case VolumeInfo.TYPE_PUBLIC:
+ case VolumeInfo.TYPE_STUB:
case VolumeInfo.TYPE_EMULATED:
break;
default:
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2d3912b..a33ac70 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -17,40 +17,69 @@
package com.android.server.am;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.android.server.am.ActivityManagerDebugConfig.*;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.IApplicationThread;
+import android.app.IServiceConnection;
+import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
import android.app.ServiceStartArgs;
+import android.content.ComponentName;
import android.content.ComponentName.WithComponentName;
+import android.content.Context;
import android.content.IIntentSender;
+import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.net.Uri;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.TransactionTooLargeException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.EventLog;
+import android.util.PrintWriterPrinter;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.StatsLog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.webkit.WebViewZygote;
import com.android.internal.R;
import com.android.internal.app.procstats.ServiceState;
@@ -64,39 +93,20 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.am.ActivityManagerService.ItemMatcher;
-
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.IApplicationThread;
-import android.app.IServiceConnection;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.EventLog;
-import android.util.PrintWriterPrinter;
-import android.util.Slog;
-import android.util.StatsLog;
-import android.util.SparseArray;
-import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-import android.webkit.WebViewZygote;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityServiceConnectionsHolder;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
public final class ActiveServices {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
private static final String TAG_MU = TAG + POSTFIX_MU;
@@ -1285,6 +1295,7 @@
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid, r.shortName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
+ mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
}
r.postNotification();
if (r.app != null) {
@@ -1334,6 +1345,7 @@
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
r.appInfo.uid, r.shortName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+ mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
if (r.app != null) {
mAm.updateLruProcessLocked(r.app, false, null);
updateServiceForegroundLocked(r.app, true);
@@ -2797,6 +2809,7 @@
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+ mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
}
r.isForeground = false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7e6d6b1..0bae1f3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -68,9 +68,7 @@
import static android.os.Process.THREAD_GROUP_RESTRICTED;
import static android.os.Process.THREAD_GROUP_TOP_APP;
import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
-import static android.os.Process.getPidsForCommands;
import static android.os.Process.getTotalMemory;
-import static android.os.Process.getUidForPid;
import static android.os.Process.isThreadInProcess;
import static android.os.Process.killProcess;
import static android.os.Process.killProcessQuiet;
@@ -127,11 +125,8 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
import static com.android.server.am.MemoryStatUtil.hasMemcg;
-import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -2060,8 +2055,7 @@
private String mExemptionsStr;
private List<String> mExemptions = Collections.emptyList();
private int mLogSampleRate = -1;
- @HiddenApiEnforcementPolicy private int mPolicyPreP = HIDDEN_API_ENFORCEMENT_DEFAULT;
- @HiddenApiEnforcementPolicy private int mPolicyP = HIDDEN_API_ENFORCEMENT_DEFAULT;
+ @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
public HiddenApiSettings(Handler handler, Context context) {
super(handler);
@@ -2078,11 +2072,7 @@
false,
this);
mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS),
- false,
- this);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_P_APPS),
+ Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY),
false,
this);
update();
@@ -2117,8 +2107,7 @@
mLogSampleRate = logSampleRate;
zygoteProcess.setHiddenApiAccessLogSampleRate(mLogSampleRate);
}
- mPolicyPreP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS);
- mPolicyP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_P_APPS);
+ mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY);
}
private @HiddenApiEnforcementPolicy int getValidEnforcementPolicy(String settingsKey) {
@@ -2135,12 +2124,8 @@
return mBlacklistDisabled;
}
- @HiddenApiEnforcementPolicy int getPolicyForPrePApps() {
- return mPolicyPreP;
- }
-
- @HiddenApiEnforcementPolicy int getPolicyForPApps() {
- return mPolicyP;
+ @HiddenApiEnforcementPolicy int getPolicy() {
+ return mPolicy;
}
public void onChange(boolean selfChange) {
@@ -2691,8 +2676,10 @@
}
void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
- if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
- "updateUsageStats: comp=" + activity + "res=" + resumed);
+ if (DEBUG_SWITCH) {
+ Slog.d(TAG_SWITCH,
+ "updateUsageStats: comp=" + activity + "res=" + resumed);
+ }
final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
uid, activity.getPackageName(),
@@ -2719,6 +2706,20 @@
}
}
+ void updateForegroundServiceUsageStats(ComponentName service, int userId, boolean started) {
+ if (DEBUG_SWITCH) {
+ Slog.d(TAG_SWITCH, "updateForegroundServiceUsageStats: comp="
+ + service + "started=" + started);
+ }
+ synchronized (this) {
+ if (mUsageStatsService != null) {
+ mUsageStatsService.reportEvent(service, userId,
+ started ? UsageEvents.Event.FOREGROUND_SERVICE_START
+ : UsageEvents.Event.FOREGROUND_SERVICE_STOP);
+ }
+ }
+ }
+
CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
return mAtmInternal.compatibilityInfoForPackage(ai);
}
@@ -17162,6 +17163,179 @@
}
@GuardedBy("this")
+ final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
+ final int N = mProcessList.getLruSizeLocked();
+ final long now = SystemClock.uptimeMillis();
+ // Now determine the memory trimming level of background processes.
+ // Unfortunately we need to start at the back of the list to do this
+ // properly. We only do this if the number of background apps we
+ // are managing to keep around is less than half the maximum we desire;
+ // if we are keeping a good number around, we'll let them use whatever
+ // memory they want.
+ final int numCachedAndEmpty = numCached + numEmpty;
+ int memFactor;
+ if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
+ && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
+ if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
+ } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
+ } else {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+ }
+ } else {
+ memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+ }
+ // We always allow the memory level to go up (better). We only allow it to go
+ // down if we are in a state where that is allowed, *and* the total number of processes
+ // has gone down since last time.
+ if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+ + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
+ + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
+ if (memFactor > mLastMemoryLevel) {
+ if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
+ memFactor = mLastMemoryLevel;
+ if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
+ }
+ }
+ if (memFactor != mLastMemoryLevel) {
+ EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
+ StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
+ }
+ mLastMemoryLevel = memFactor;
+ mLastNumProcesses = mProcessList.getLruSizeLocked();
+ boolean allChanged = mProcessStats.setMemFactorLocked(
+ memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
+ final int trackerMemFactor = mProcessStats.getMemFactorLocked();
+ if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
+ if (mLowRamStartTime == 0) {
+ mLowRamStartTime = now;
+ }
+ int step = 0;
+ int fgTrimLevel;
+ switch (memFactor) {
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+ break;
+ default:
+ fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+ break;
+ }
+ int factor = numTrimming/3;
+ int minFactor = 2;
+ if (mAtmInternal.getHomeProcess() != null) minFactor++;
+ if (mAtmInternal.getPreviousProcess() != null) minFactor++;
+ if (factor < minFactor) factor = minFactor;
+ int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
+ for (int i=N-1; i>=0; i--) {
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
+ if (allChanged || app.procStateChanged) {
+ setProcessTrackerStateLocked(app, trackerMemFactor, now);
+ app.procStateChanged = false;
+ }
+ if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
+ && !app.killedByAm) {
+ if (app.trimMemoryLevel < curLevel && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of " + app.processName + " to " + curLevel);
+ app.thread.scheduleTrimMemory(curLevel);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = curLevel;
+ step++;
+ if (step >= factor) {
+ step = 0;
+ switch (curLevel) {
+ case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+ curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
+ break;
+ case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+ curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+ break;
+ }
+ }
+ } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+ && !app.killedByAm) {
+ if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
+ && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of heavy-weight " + app.processName
+ + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+ app.thread.scheduleTrimMemory(
+ ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+ } else {
+ if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || app.systemNoUi) && app.hasPendingUiClean()) {
+ // If this application is now in the background and it
+ // had done UI, then give it the special trim level to
+ // have it free UI resources.
+ final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+ if (app.trimMemoryLevel < level && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of bg-ui " + app.processName
+ + " to " + level);
+ app.thread.scheduleTrimMemory(level);
+ } catch (RemoteException e) {
+ }
+ }
+ app.setPendingUiClean(false);
+ }
+ if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of fg " + app.processName
+ + " to " + fgTrimLevel);
+ app.thread.scheduleTrimMemory(fgTrimLevel);
+ } catch (RemoteException e) {
+ }
+ }
+ app.trimMemoryLevel = fgTrimLevel;
+ }
+ }
+ } else {
+ if (mLowRamStartTime != 0) {
+ mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
+ mLowRamStartTime = 0;
+ }
+ for (int i=N-1; i>=0; i--) {
+ ProcessRecord app = mProcessList.mLruProcesses.get(i);
+ if (allChanged || app.procStateChanged) {
+ setProcessTrackerStateLocked(app, trackerMemFactor, now);
+ app.procStateChanged = false;
+ }
+ if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+ || app.systemNoUi) && app.hasPendingUiClean()) {
+ if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
+ && app.thread != null) {
+ try {
+ if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+ "Trimming memory of ui hidden " + app.processName
+ + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ app.thread.scheduleTrimMemory(
+ ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ } catch (RemoteException e) {
+ }
+ }
+ app.setPendingUiClean(false);
+ }
+ app.trimMemoryLevel = 0;
+ }
+ }
+ return allChanged;
+ }
+
+ @GuardedBy("this")
final void updateOomAdjLocked() {
mOomAdjProfiler.oomAdjStarted();
final ProcessRecord TOP_APP = getTopAppLocked();
@@ -17393,172 +17567,7 @@
mNumServiceProcs = mNewNumServiceProcs;
- // Now determine the memory trimming level of background processes.
- // Unfortunately we need to start at the back of the list to do this
- // properly. We only do this if the number of background apps we
- // are managing to keep around is less than half the maximum we desire;
- // if we are keeping a good number around, we'll let them use whatever
- // memory they want.
- final int numCachedAndEmpty = numCached + numEmpty;
- int memFactor;
- if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
- && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
- if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
- } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
- } else {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
- }
- } else {
- memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
- }
- // We always allow the memory level to go up (better). We only allow it to go
- // down if we are in a state where that is allowed, *and* the total number of processes
- // has gone down since last time.
- if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
- + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
- + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
- if (memFactor > mLastMemoryLevel) {
- if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
- memFactor = mLastMemoryLevel;
- if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
- }
- }
- if (memFactor != mLastMemoryLevel) {
- EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
- StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
- }
- mLastMemoryLevel = memFactor;
- mLastNumProcesses = mProcessList.getLruSizeLocked();
- boolean allChanged = mProcessStats.setMemFactorLocked(
- memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
- final int trackerMemFactor = mProcessStats.getMemFactorLocked();
- if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
- if (mLowRamStartTime == 0) {
- mLowRamStartTime = now;
- }
- int step = 0;
- int fgTrimLevel;
- switch (memFactor) {
- case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
- break;
- case ProcessStats.ADJ_MEM_FACTOR_LOW:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
- break;
- default:
- fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
- break;
- }
- int factor = numTrimming/3;
- int minFactor = 2;
- if (mAtmInternal.getHomeProcess() != null) minFactor++;
- if (mAtmInternal.getPreviousProcess() != null) minFactor++;
- if (factor < minFactor) factor = minFactor;
- int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
- for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (allChanged || app.procStateChanged) {
- setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
- }
- if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
- && !app.killedByAm) {
- if (app.trimMemoryLevel < curLevel && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of " + app.processName + " to " + curLevel);
- app.thread.scheduleTrimMemory(curLevel);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = curLevel;
- step++;
- if (step >= factor) {
- step = 0;
- switch (curLevel) {
- case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
- break;
- case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
- curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
- break;
- }
- }
- } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
- && !app.killedByAm) {
- if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
- && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of heavy-weight " + app.processName
- + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
- } else {
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && app.hasPendingUiClean()) {
- // If this application is now in the background and it
- // had done UI, then give it the special trim level to
- // have it free UI resources.
- final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
- if (app.trimMemoryLevel < level && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of bg-ui " + app.processName
- + " to " + level);
- app.thread.scheduleTrimMemory(level);
- } catch (RemoteException e) {
- }
- }
- app.setPendingUiClean(false);
- }
- if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of fg " + app.processName
- + " to " + fgTrimLevel);
- app.thread.scheduleTrimMemory(fgTrimLevel);
- } catch (RemoteException e) {
- }
- }
- app.trimMemoryLevel = fgTrimLevel;
- }
- }
- } else {
- if (mLowRamStartTime != 0) {
- mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
- mLowRamStartTime = 0;
- }
- for (int i=N-1; i>=0; i--) {
- ProcessRecord app = mProcessList.mLruProcesses.get(i);
- if (allChanged || app.procStateChanged) {
- setProcessTrackerStateLocked(app, trackerMemFactor, now);
- app.procStateChanged = false;
- }
- if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
- || app.systemNoUi) && app.hasPendingUiClean()) {
- if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
- && app.thread != null) {
- try {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Trimming memory of ui hidden " + app.processName
- + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
- app.thread.scheduleTrimMemory(
- ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
- } catch (RemoteException e) {
- }
- }
- app.setPendingUiClean(false);
- }
- app.trimMemoryLevel = 0;
- }
- }
+ boolean allChanged = updateLowMemStateLocked(numCached, numEmpty, numTrimming);
if (mAlwaysFinishActivities) {
// Need to do this on its own message because the stack may not
@@ -18759,28 +18768,6 @@
}
@Override
- public List<ProcessMemoryState> getMemoryStateForNativeProcesses() {
- List<ProcessMemoryState> processMemoryStates = new ArrayList<>();
- int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
- for (int i = 0; i < pids.length; i++) {
- int pid = pids[i];
- MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
- if (memoryStat == null) {
- continue;
- }
- int uid = getUidForPid(pid);
- String processName = readCmdlineFromProcfs(pid);
- int oomScore = -1; // Unused, not included in the NativeProcessMemoryState atom.
- ProcessMemoryState processMemoryState = new ProcessMemoryState(uid, processName,
- oomScore, memoryStat.pgfault, memoryStat.pgmajfault,
- memoryStat.rssInBytes, memoryStat.cacheInBytes, memoryStat.swapInBytes,
- memoryStat.rssHighWatermarkInBytes, memoryStat.startTimeNanos);
- processMemoryStates.add(processMemoryState);
- }
- return processMemoryStates;
- }
-
- @Override
public int handleIncomingUser(int callingPid, int callingUid, int userId,
boolean allowAll, int allowMode, String name, String callerPackage) {
return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index c978c13..80b4f77 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -16,9 +16,9 @@
package com.android.server.am;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
import android.annotation.Nullable;
import android.os.FileUtils;
@@ -45,7 +45,7 @@
* <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
* /system/bin/statsd for the stats daemon.
*/
- static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
+ public static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
"/system/bin/statsd", // Stats daemon.
"/system/bin/surfaceflinger",
"/system/bin/apexd", // APEX daemon.
@@ -146,7 +146,7 @@
* Returns null if file is not found in procfs or if file has unrecognized contents.
*/
@Nullable
- static MemoryStat readMemoryStatFromProcfs(int pid) {
+ public static MemoryStat readMemoryStatFromProcfs(int pid) {
final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
MemoryStat stat = parseMemoryStatFromProcfs(readFileContents(statPath));
if (stat == null) {
@@ -163,7 +163,7 @@
* Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
* if the file is not available.
*/
- static String readCmdlineFromProcfs(int pid) {
+ public static String readCmdlineFromProcfs(int pid) {
String path = String.format(Locale.US, PROC_CMDLINE_FILE_FMT, pid);
String cmdline = readFileContents(path);
return cmdline != null ? cmdline : "";
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index c1b720e..84b364b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1363,8 +1363,7 @@
if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
app.info.maybeUpdateHiddenApiEnforcementPolicy(
- mService.mHiddenApiBlacklist.getPolicyForPrePApps(),
- mService.mHiddenApiBlacklist.getPolicyForPApps());
+ mService.mHiddenApiBlacklist.getPolicy());
@ApplicationInfo.HiddenApiEnforcementPolicy int policy =
app.info.getHiddenApiEnforcementPolicy();
int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 61836fdd..2c2d404 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -358,7 +358,7 @@
if (mBundle != null) {
try {
mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
- getBiometricType(), mRequireConfirmation);
+ getBiometricType(), mRequireConfirmation, getTargetUserId());
} catch (RemoteException e) {
Slog.e(getLogTag(), "Unable to show biometric dialog", e);
}
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index 635db19..0e727c5 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -90,6 +90,8 @@
mNotifier = notifier;
mDailyLimit = dailyLimit;
mRateLimitMillis = rateLimitMillis;
+ // Ensure that (now - mFirstNotificationMillis) >= rateLimitMillis at first
+ mFirstNotificationMillis = -rateLimitMillis;
}
private static HashMap<String, Integer> makeTransportToNameMap() {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index f074573..9e6e381 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -2075,8 +2075,8 @@
// note that this assumes the message will not be removed from the queue before
// it is handled (otherwise the wake lock would be leaked).
mWakeLock.acquire();
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
+ if (DEBUG) {
+ Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
+ ", " + obj + ")");
}
mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
@@ -2133,8 +2133,8 @@
if (msg.arg2 == 1) {
// wakelock was taken for this message, release it
mWakeLock.release();
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
+ if (DEBUG) {
+ Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
+ ", " + msg.arg1 + ", " + msg.obj + ")");
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 95c70d5..95d2154 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -49,7 +49,7 @@
import dalvik.system.DexFile;
-import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
@@ -548,7 +548,7 @@
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
// TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
- int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+ int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_DISABLED
? 0
: DEXOPT_ENABLE_HIDDEN_API_CHECKS;
// Avoid generating CompactDex for modes that are latency critical.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 77045fb..72d3406 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16337,17 +16337,6 @@
+ oldPackage.mSharedUserId);
}
- // check if the new package supports all of the abis which the old package
- // supports
- boolean oldPkgSupportMultiArch =
- oldPackage.applicationInfo.secondaryCpuAbi != null;
- boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
- if (isSystemApp(oldPackage) && oldPkgSupportMultiArch
- && !newPkgSupportMultiArch) {
- throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
- "Update to package " + pkgName11 + " doesn't support multi arch");
- }
-
// In case of rollback, remember per-user/profile install state
allUsers = sUserManager.getUserIds();
installedUsers = ps.queryInstalledUsers(allUsers, true);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 43a9c78..29d6237 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4439,6 +4439,42 @@
}
@Override // Binder call
+ public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+ int disableThreshold) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER,
+ "updateDynamicPowerSavings");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final ContentResolver resolver = mContext.getContentResolver();
+ boolean success = Settings.Global.putInt(resolver,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+ disableThreshold);
+ if (success) {
+ // abort updating if we weren't able to succeed on the threshold
+ success &= Settings.Global.putInt(resolver,
+ Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+ dynamicPowerSavingsEnabled ? 1 : 0);
+ }
+ return success;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public int getPowerSaveMode() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+ PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public boolean isDeviceIdleMode() {
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 5569822..6400c88 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -93,8 +93,8 @@
*/
private final Plugin[] mPlugins;
- public static final int REASON_AUTOMATIC_ON = 0;
- public static final int REASON_AUTOMATIC_OFF = 1;
+ public static final int REASON_PERCENTAGE_AUTOMATIC_ON = 0;
+ public static final int REASON_PERCENTAGE_AUTOMATIC_OFF = 1;
public static final int REASON_MANUAL_ON = 2;
public static final int REASON_MANUAL_OFF = 3;
public static final int REASON_STICKY_RESTORE = 4;
@@ -102,6 +102,8 @@
public static final int REASON_POLICY_CHANGED = 6;
public static final int REASON_PLUGGED_IN = 7;
public static final int REASON_SETTING_CHANGED = 8;
+ public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON = 9;
+ public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF = 10;
/**
* Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index 20ceed43..f262f6d 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
@@ -87,6 +88,11 @@
/** Config flag to track if battery saver's sticky behaviour is disabled. */
private final boolean mBatterySaverStickyBehaviourDisabled;
+ /** Config flag to track default disable threshold for Dynamic Power Savings enabled battery
+ * saver. */
+ @GuardedBy("mLock")
+ private final int mDynamicPowerSavingsDefaultDisableThreshold;
+
/**
* Previously known value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
* (Currently only used in dumpsys.)
@@ -94,6 +100,23 @@
@GuardedBy("mLock")
private int mSettingBatterySaverTriggerThreshold;
+ /** Previously known value of Global.AUTOMATIC_POWER_SAVER_MODE. */
+ @GuardedBy("mLock")
+ private int mSettingAutomaticBatterySaver;
+
+ /** When to disable battery saver again if it was enabled due to an external suggestion.
+ * Corresponds to Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD.
+ */
+ @GuardedBy("mLock")
+ private int mDynamicPowerSavingsDisableThreshold;
+
+ /**
+ * Whether we've received a suggestion that battery saver should be on from an external app.
+ * Updates when Global.DYNAMIC_POWER_SAVINGS_ENABLED changes.
+ */
+ @GuardedBy("mLock")
+ private boolean mDynamicPowerSavingsBatterySaver;
+
/**
* Whether BS has been manually disabled while the battery level is low, in which case we
* shouldn't auto re-enable it until the battery level is not low.
@@ -130,13 +153,15 @@
mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
+ mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
}
private boolean isBatterySaverEnabled() {
return mBatterySaverController.isEnabled();
}
- private boolean isAutoBatterySaverConfigured() {
+ private boolean isAutoBatterySaverConfiguredLocked() {
return mSettingBatterySaverTriggerThreshold > 0;
}
@@ -165,6 +190,15 @@
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
+ cr.registerContentObserver(Settings.Global.getUriFor(
+ Global.AUTOMATIC_POWER_SAVER_MODE),
+ false, mSettingsObserver, UserHandle.USER_SYSTEM);
+ cr.registerContentObserver(Settings.Global.getUriFor(
+ Global.DYNAMIC_POWER_SAVINGS_ENABLED),
+ false, mSettingsObserver, UserHandle.USER_SYSTEM);
+ cr.registerContentObserver(Settings.Global.getUriFor(
+ Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD),
+ false, mSettingsObserver, UserHandle.USER_SYSTEM);
synchronized (mLock) {
@@ -202,11 +236,20 @@
Settings.Global.LOW_POWER_MODE, 0) != 0;
final boolean lowPowerModeEnabledSticky = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
+ final boolean dynamicPowerSavingsBatterySaver = getGlobalSetting(
+ Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0;
final int lowPowerModeTriggerLevel = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+ final int automaticBatterySaver = getGlobalSetting(
+ Global.AUTOMATIC_POWER_SAVER_MODE,
+ PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+ final int dynamicPowerSavingsDisableThreshold = getGlobalSetting(
+ Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+ mDynamicPowerSavingsDefaultDisableThreshold);
setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
- lowPowerModeTriggerLevel);
+ lowPowerModeTriggerLevel, automaticBatterySaver, dynamicPowerSavingsBatterySaver,
+ dynamicPowerSavingsDisableThreshold);
}
/**
@@ -218,11 +261,16 @@
@GuardedBy("mLock")
@VisibleForTesting
void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
- int batterySaverTriggerThreshold) {
+ int batterySaverTriggerThreshold, int automaticBatterySaver,
+ boolean dynamicPowerSavingsBatterySaver, int dynamicPowerSavingsDisableThreshold) {
if (DEBUG) {
Slog.d(TAG, "setSettings: enabled=" + batterySaverEnabled
+ " sticky=" + batterySaverEnabledSticky
- + " threshold=" + batterySaverTriggerThreshold);
+ + " threshold=" + batterySaverTriggerThreshold
+ + " automaticBatterySaver=" + automaticBatterySaver
+ + " dynamicPowerSavingsBatterySaver=" + dynamicPowerSavingsBatterySaver
+ + " dynamicPowerSavingsDisableThreshold="
+ + dynamicPowerSavingsDisableThreshold);
}
mSettingsLoaded = true;
@@ -232,14 +280,23 @@
mSettingBatterySaverEnabledSticky != batterySaverEnabledSticky;
final boolean thresholdChanged
= mSettingBatterySaverTriggerThreshold != batterySaverTriggerThreshold;
+ final boolean automaticModeChanged = mSettingAutomaticBatterySaver != automaticBatterySaver;
+ final boolean dynamicPowerSavingsThresholdChanged =
+ mDynamicPowerSavingsDisableThreshold != dynamicPowerSavingsDisableThreshold;
+ final boolean dynamicPowerSavingsBatterySaverChanged =
+ mDynamicPowerSavingsBatterySaver != dynamicPowerSavingsBatterySaver;
- if (!(enabledChanged || stickyChanged || thresholdChanged)) {
+ if (!(enabledChanged || stickyChanged || thresholdChanged || automaticModeChanged
+ || dynamicPowerSavingsThresholdChanged || dynamicPowerSavingsBatterySaverChanged)) {
return;
}
mSettingBatterySaverEnabled = batterySaverEnabled;
mSettingBatterySaverEnabledSticky = batterySaverEnabledSticky;
mSettingBatterySaverTriggerThreshold = batterySaverTriggerThreshold;
+ mSettingAutomaticBatterySaver = automaticBatterySaver;
+ mDynamicPowerSavingsDisableThreshold = dynamicPowerSavingsDisableThreshold;
+ mDynamicPowerSavingsBatterySaver = dynamicPowerSavingsBatterySaver;
if (thresholdChanged) {
// To avoid spamming the event log, we throttle logging here.
@@ -287,6 +344,17 @@
}
}
+ @GuardedBy("mLock")
+ private boolean isBatteryLowLocked() {
+ final boolean percentageLow =
+ mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+ && mIsBatteryLevelLow;
+ final boolean dynamicPowerSavingsLow =
+ mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_DYNAMIC
+ && mBatteryLevel <= mDynamicPowerSavingsDisableThreshold;
+ return percentageLow || dynamicPowerSavingsLow;
+ }
+
/**
* Decide whether to auto-start / stop battery saver.
*/
@@ -299,12 +367,14 @@
+ " mIsBatteryLevelLow=" + mIsBatteryLevelLow
+ " mBatterySaverSnoozing=" + mBatterySaverSnoozing
+ " mIsPowered=" + mIsPowered
+ + " mSettingAutomaticBatterySaver=" + mSettingAutomaticBatterySaver
+ " mSettingBatterySaverEnabledSticky=" + mSettingBatterySaverEnabledSticky);
}
if (!(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
return; // Not fully initialized yet.
}
- if (!mIsBatteryLevelLow) {
+
+ if (!isBatteryLowLocked()) {
updateSnoozingLocked(false, "Battery not low");
}
if (mIsPowered) {
@@ -319,20 +389,35 @@
BatterySaverController.REASON_STICKY_RESTORE,
"Sticky restore");
- } else if (mIsBatteryLevelLow) {
- if (!mBatterySaverSnoozing && isAutoBatterySaverConfigured()) {
+ } else if (mSettingAutomaticBatterySaver
+ == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+ && isAutoBatterySaverConfiguredLocked()) {
+ if (mIsBatteryLevelLow && !mBatterySaverSnoozing) {
enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
- BatterySaverController.REASON_AUTOMATIC_ON,
- "Auto ON");
+ BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON,
+ "Percentage Auto ON");
+ } else {
+ // Battery not low
+ enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+ BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF,
+ "Percentage Auto OFF");
}
- } else { // Battery not low
- enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
- BatterySaverController.REASON_AUTOMATIC_OFF,
- "Auto OFF");
+ } else if (mSettingAutomaticBatterySaver
+ == PowerManager.POWER_SAVER_MODE_DYNAMIC) {
+ if (mBatteryLevel >= mDynamicPowerSavingsDisableThreshold) {
+ enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+ BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF,
+ "Dynamic Warning Auto OFF");
+ } else if (mDynamicPowerSavingsBatterySaver && !mBatterySaverSnoozing) {
+ enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
+ BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON,
+ "Dynamic Warning Auto ON");
+ }
}
+ // do nothing if automatic battery saver mode = PERCENTAGE and low warning threshold = 0%
}
- /**
+ /**
* {@link com.android.server.power.PowerManagerService} calls it when
* {@link android.os.PowerManager#setPowerSaveMode} is called.
*
@@ -383,7 +468,7 @@
// When battery saver is disabled manually (while battery saver is enabled)
// when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
// We resume auto-BS once the battery level is not low, or the device is plugged in.
- if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
+ if (isBatterySaverEnabled() && isBatteryLowLocked()) {
updateSnoozingLocked(true, "Manual snooze");
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b7d2ce2..ded075d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -104,12 +104,18 @@
@Override
public void onStart() {
publishBinderService(Context.ROLE_SERVICE, new Stub());
+ //TODO add watch for new user creation and run default grants for them
}
@Override
public void onStartUser(@UserIdInt int userId) {
synchronized (mLock) {
+ //TODO only call into PermissionController if it or system upgreaded (for boot time)
+ // (add package changes watch;
+ // we can detect upgrade using build fingerprint and app version)
getUserStateLocked(userId);
+ //TODO call permission grant policy here
+ Slog.i(LOG_TAG, "Granting default permissions...");
}
}
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index caa7c28..becc962 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -73,7 +73,7 @@
* Maps role names to its holders' package names. The values should never be null.
*/
@GuardedBy("RoleManagerService.mLock")
- private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
+ private ArrayMap<String, ArraySet<String>> mRoles = null;
@GuardedBy("RoleManagerService.mLock")
private boolean mDestroyed;
@@ -188,7 +188,8 @@
roles.put(roleName, roleHolders);
}
mWriteHandler.removeCallbacksAndMessages(null);
- mWriteHandler.sendMessage(PooledLambda.obtainMessage(this::writeSync, version, roles));
+ mWriteHandler.sendMessage(PooledLambda.obtainMessage(
+ RoleUserState::writeSync, this, version, roles));
}
@WorkerThread
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 70c86a1..cef484f 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -15,7 +15,13 @@
*/
package com.android.server.stats;
+import static android.os.Process.getPidsForCommands;
+import static android.os.Process.getUidForPid;
+
import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
+import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
@@ -96,6 +102,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
+import com.android.server.am.MemoryStatUtil.MemoryStat;
import com.android.server.storage.DiskStatsFileLogger;
import com.android.server.storage.DiskStatsLoggingService;
@@ -1012,17 +1019,23 @@
private void pullNativeProcessMemoryState(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
- List<ProcessMemoryState> processMemoryStates = LocalServices.getService(
- ActivityManagerInternal.class).getMemoryStateForNativeProcesses();
- for (ProcessMemoryState processMemoryState : processMemoryStates) {
+ int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
+ for (int i = 0; i < pids.length; i++) {
+ int pid = pids[i];
+ MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
+ if (memoryStat == null) {
+ continue;
+ }
+ int uid = getUidForPid(pid);
+ String processName = readCmdlineFromProcfs(pid);
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(processMemoryState.uid);
- e.writeString(processMemoryState.processName);
- e.writeLong(processMemoryState.pgfault);
- e.writeLong(processMemoryState.pgmajfault);
- e.writeLong(processMemoryState.rssInBytes);
- e.writeLong(processMemoryState.rssHighWatermarkInBytes);
- e.writeLong(processMemoryState.startTimeNanos);
+ e.writeInt(uid);
+ e.writeString(processName);
+ e.writeLong(memoryStat.pgfault);
+ e.writeLong(memoryStat.pgmajfault);
+ e.writeLong(memoryStat.rssInBytes);
+ e.writeLong(memoryStat.rssHighWatermarkInBytes);
+ e.writeLong(memoryStat.startTimeNanos);
pulledData.add(e);
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ec78560..10121c4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -567,11 +567,11 @@
@Override
public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation) {
+ boolean requireConfirmation, int userId) {
enforceBiometricDialog();
if (mBar != null) {
try {
- mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation);
+ mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation, userId);
} catch (RemoteException ex) {
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b88165e..a7542d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -491,6 +491,11 @@
*/
final boolean mIsWatch;
+ /**
+ * Whether this device has the telephony feature.
+ */
+ final boolean mHasTelephonyFeature;
+
private final CertificateMonitor mCertificateMonitor;
private final SecurityLogMonitor mSecurityLogMonitor;
@@ -2133,6 +2138,8 @@
mHasFeature = mInjector.hasFeature();
mIsWatch = mInjector.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ mHasTelephonyFeature = mInjector.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
mBackgroundHandler = BackgroundThread.getHandler();
// Needed when mHasFeature == false, because it controls the certificate warning text.
@@ -12927,7 +12934,7 @@
@Override
public int addOverrideApn(@NonNull ComponentName who, @NonNull ApnSetting apnSetting) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return -1;
}
Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
@@ -12956,7 +12963,7 @@
@Override
public boolean updateOverrideApn(@NonNull ComponentName who, int apnId,
@NonNull ApnSetting apnSetting) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
@@ -12978,7 +12985,7 @@
@Override
public boolean removeOverrideApn(@NonNull ComponentName who, int apnId) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
@@ -13004,7 +13011,7 @@
@Override
public List<ApnSetting> getOverrideApns(@NonNull ComponentName who) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return Collections.emptyList();
}
Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
@@ -13040,7 +13047,7 @@
@Override
public void setOverrideApnsEnabled(@NonNull ComponentName who, boolean enabled) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
@@ -13063,7 +13070,7 @@
@Override
public boolean isOverrideApnEnabled(@NonNull ComponentName who) {
- if (!mHasFeature) {
+ if (!mHasFeature || !mHasTelephonyFeature) {
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 86eb6f3..73990f8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -118,6 +118,7 @@
import com.android.server.power.ShutdownThread;
import com.android.server.power.ThermalManagerService;
import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.role.RoleManagerService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.soundtrigger.SoundTriggerService;
@@ -1911,6 +1912,11 @@
}
traceEnd();
+ // Grants default permissions and defines roles
+ traceBeginAndSlog("StartRoleManagerService");
+ mSystemServiceManager.startService(RoleManagerService.class);
+ traceEnd();
+
// No dependency on Webview preparation in system server. But this should
// be completed before allowing 3rd party
final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index fd04970..f31ca55 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -115,7 +115,12 @@
mTarget.setSettingsLocked(
mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE, 0) != 0,
mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE_STICKY, 0) != 0,
- mDevice.getLowPowerModeTriggerLevel());
+ mDevice.getLowPowerModeTriggerLevel(),
+ mPersistedState.global.getOrDefault(Global.AUTOMATIC_POWER_SAVER_MODE, 0),
+ mPersistedState.global.getOrDefault(
+ Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0,
+ mPersistedState.global.getOrDefault(
+ Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 100));
}
public void putGlobalSetting(String key, int value) {
@@ -174,6 +179,9 @@
when(mMockResources.getBoolean(
com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
.thenReturn(false);
+ when(mMockResources.getInteger(
+ com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold))
+ .thenReturn(80);
mPersistedState = new DevicePersistedState();
initDevice();
@@ -303,6 +311,7 @@
@Test
public void testAutoBatterySaver() {
mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+ mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
assertEquals(false, mDevice.batterySaverEnabled);
assertEquals(100, mPersistedState.batteryLevel);
@@ -515,6 +524,7 @@
.thenReturn(true);
initDevice();
mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+ mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
mTarget.setBatterySaverEnabledManually(true);
@@ -626,4 +636,123 @@
assertEquals(90, mPersistedState.batteryLevel);
assertEquals(false, mPersistedState.batteryLow);
}
+
+ @Test
+ public void testAutoBatterySaver_smartBatterySaverEnabled() {
+ mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
+ mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 1);
+ mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(100, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(90);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(90, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(51);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(51, mPersistedState.batteryLevel);
+
+ // Hit the threshold. BS should be disabled since dynamic power savings still off
+ mDevice.setBatteryLevel(50);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(50, mPersistedState.batteryLevel);
+
+ // dynamic power savings comes on, battery saver should turn on
+ mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1);
+ mDevice.setBatteryLevel(40);
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(40, mPersistedState.batteryLevel);
+
+ mDevice.setPowered(true);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(40, mPersistedState.batteryLevel);
+
+ mDevice.setPowered(false);
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(40, mPersistedState.batteryLevel);
+
+ mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(40, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(30);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(30, mPersistedState.batteryLevel);
+
+ // Plug in and out, snooze will reset.
+ mDevice.setPowered(true);
+ mDevice.setPowered(false);
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(30, mPersistedState.batteryLevel);
+
+ mDevice.setPowered(true);
+ mDevice.setBatteryLevel(60);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(60, mPersistedState.batteryLevel);
+
+ mDevice.setPowered(false);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(60, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(40);
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(40, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(70);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(70, mPersistedState.batteryLevel);
+
+ // Bump up the threshold.
+ mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 71);
+ mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+ // changes are only registered if some battery level changed
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(70, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(69);
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(69, mPersistedState.batteryLevel);
+
+ // Then down.
+ mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 60);
+ mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+ // changes are only registered if battery level changed
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(69, mPersistedState.batteryLevel);
+
+ mDevice.setBatteryLevel(68);
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(68, mPersistedState.batteryLevel);
+
+ // Reboot in low state -> automatically enable BS.
+ mDevice.setPowered(false);
+ mDevice.setBatteryLevel(30);
+ mTarget.setBatterySaverEnabledManually(false);
+
+ assertEquals(false, mDevice.batterySaverEnabled);
+ assertEquals(30, mPersistedState.batteryLevel);
+
+ initDevice();
+
+ assertEquals(true, mDevice.batterySaverEnabled);
+ assertEquals(30, mPersistedState.batteryLevel);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index 473682d..bf7f53d 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -16,13 +16,12 @@
package com.android.server.usage;
-import static junit.framework.TestCase.assertNull;
import static junit.framework.TestCase.fail;
import static org.testng.Assert.assertEquals;
import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
@@ -112,6 +111,8 @@
long time = System.currentTimeMillis() - (numberOfEvents*timeProgression);
mIntervalStats = new IntervalStats();
+ mIntervalStats.majorVersion = 7;
+ mIntervalStats.minorVersion = 8;
mIntervalStats.beginTime = time;
mIntervalStats.interactiveTracker.count = 2;
mIntervalStats.interactiveTracker.duration = 111111;
@@ -127,41 +128,39 @@
}
for (int i = 0; i < numberOfEvents; i++) {
- UsageEvents.Event event = new UsageEvents.Event();
+ Event event = new Event();
final int packageInt = ((i / 3) % 7);
event.mPackage = "fake.package.name" + packageInt; //clusters of 3 events from 7 "apps"
if (packageInt == 3) {
// Third app is an instant app
- event.mFlags |= UsageEvents.Event.FLAG_IS_PACKAGE_INSTANT_APP;
- } else if (packageInt == 2 || packageInt == 4) {
- event.mClass = ".fake.class.name" + i % 11;
+ event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
}
-
+ event.mClass = ".fake.class.name" + i % 11;
event.mTimeStamp = time;
event.mEventType = i % 19; //"random" event type
switch (event.mEventType) {
- case UsageEvents.Event.CONFIGURATION_CHANGE:
+ case Event.CONFIGURATION_CHANGE:
//empty config,
event.mConfiguration = new Configuration();
break;
- case UsageEvents.Event.SHORTCUT_INVOCATION:
+ case Event.SHORTCUT_INVOCATION:
//"random" shortcut
event.mShortcutId = "shortcut" + (i % 8);
break;
- case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+ case Event.STANDBY_BUCKET_CHANGED:
//"random" bucket and reason
event.mBucketAndReason = (((i % 5 + 1) * 10) << 16) & (i % 5 + 1) << 8;
break;
- case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+ case Event.NOTIFICATION_INTERRUPTION:
//"random" channel
event.mNotificationChannelId = "channel" + (i % 5);
break;
}
mIntervalStats.events.insert(event);
- mIntervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ mIntervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType);
time += timeProgression; // Arbitrary progression of time
}
@@ -221,29 +220,30 @@
// mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking
assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+ assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+ assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
// mLaunchCount not persisted, so skipped
assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
- assertEquals(us1.mLastEvent, us2.mLastEvent);
assertEquals(us1.mChooserCounts, us2.mChooserCounts);
}
- void compareUsageEvent(UsageEvents.Event e1, UsageEvents.Event e2, int debugId) {
+ void compareUsageEvent(Event e1, Event e2, int debugId) {
assertEquals(e1.mPackage, e2.mPackage, "Usage event " + debugId);
assertEquals(e1.mClass, e2.mClass, "Usage event " + debugId);
assertEquals(e1.mTimeStamp, e2.mTimeStamp, "Usage event " + debugId);
assertEquals(e1.mEventType, e2.mEventType, "Usage event " + debugId);
switch (e1.mEventType) {
- case UsageEvents.Event.CONFIGURATION_CHANGE:
+ case Event.CONFIGURATION_CHANGE:
assertEquals(e1.mConfiguration, e2.mConfiguration,
"Usage event " + debugId + e2.mConfiguration.toString());
break;
- case UsageEvents.Event.SHORTCUT_INVOCATION:
+ case Event.SHORTCUT_INVOCATION:
assertEquals(e1.mShortcutId, e2.mShortcutId, "Usage event " + debugId);
break;
- case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+ case Event.STANDBY_BUCKET_CHANGED:
assertEquals(e1.mBucketAndReason, e2.mBucketAndReason, "Usage event " + debugId);
break;
- case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+ case Event.NOTIFICATION_INTERRUPTION:
assertEquals(e1.mNotificationChannelId, e2.mNotificationChannelId,
"Usage event " + debugId);
break;
@@ -252,6 +252,8 @@
}
void compareIntervalStats(IntervalStats stats1, IntervalStats stats2) {
+ assertEquals(stats1.majorVersion, stats2.majorVersion);
+ assertEquals(stats1.minorVersion, stats2.minorVersion);
assertEquals(stats1.beginTime, stats2.beginTime);
assertEquals(stats1.endTime, stats2.endTime);
assertEquals(stats1.interactiveTracker.count, stats2.interactiveTracker.count);
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 4f573a4..152831f 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -27,6 +27,8 @@
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN;
@@ -844,6 +846,8 @@
// Inform listeners if necessary
if ((event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND
|| event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
+ || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START
+ || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_STOP
|| event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
|| event.mEventType == UsageEvents.Event.USER_INTERACTION
|| event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
@@ -896,6 +900,10 @@
switch (eventType) {
case UsageEvents.Event.MOVE_TO_FOREGROUND: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
case UsageEvents.Event.MOVE_TO_BACKGROUND: return REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
+ case UsageEvents.Event.FOREGROUND_SERVICE_START:
+ return REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+ case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+ return REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
case UsageEvents.Event.SYSTEM_INTERACTION: return REASON_SUB_USAGE_SYSTEM_INTERACTION;
case UsageEvents.Event.USER_INTERACTION: return REASON_SUB_USAGE_USER_INTERACTION;
case UsageEvents.Event.NOTIFICATION_SEEN: return REASON_SUB_USAGE_NOTIFICATION_SEEN;
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index db9972f..8405267 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -18,7 +18,6 @@
import android.app.usage.ConfigurationStats;
import android.app.usage.EventList;
import android.app.usage.EventStats;
-import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.content.res.Configuration;
@@ -26,12 +25,16 @@
import android.util.ArraySet;
import android.util.proto.ProtoInputStream;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.IOException;
import java.util.List;
-import com.android.internal.annotations.VisibleForTesting;
-
public class IntervalStats {
+ public static final int CURRENT_MAJOR_VERSION = 1;
+ public static final int CURRENT_MINOR_VERSION = 1;
+ public int majorVersion = CURRENT_MAJOR_VERSION;
+ public int minorVersion = CURRENT_MINOR_VERSION;
public long beginTime;
public long endTime;
public long lastTimeSaved;
@@ -219,8 +222,12 @@
switch (eventType) {
case UsageEvents.Event.MOVE_TO_FOREGROUND:
case UsageEvents.Event.MOVE_TO_BACKGROUND:
+ case UsageEvents.Event.FOREGROUND_SERVICE_START:
+ case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
case UsageEvents.Event.END_OF_DAY:
+ case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
+ case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
return true;
}
return false;
@@ -239,32 +246,9 @@
* @hide
*/
@VisibleForTesting
- public void update(String packageName, long timeStamp, int eventType) {
+ public void update(String packageName, String className, long timeStamp, int eventType) {
UsageStats usageStats = getOrCreateUsageStats(packageName);
-
- // TODO(adamlesinski): Ensure that we recover from incorrect event sequences
- // like double MOVE_TO_BACKGROUND, etc.
- if (eventType == UsageEvents.Event.MOVE_TO_BACKGROUND ||
- eventType == UsageEvents.Event.END_OF_DAY) {
- if (usageStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
- usageStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
- usageStats.mTotalTimeInForeground += timeStamp - usageStats.mLastTimeUsed;
- }
- }
-
- if (isStatefulEvent(eventType)) {
- usageStats.mLastEvent = eventType;
- }
-
- if (isUserVisibleEvent(eventType)) {
- usageStats.mLastTimeUsed = timeStamp;
- }
- usageStats.mEndTimeStamp = timeStamp;
-
- if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
- usageStats.mLaunchCount += 1;
- }
-
+ usageStats.update(className, timeStamp, eventType);
endTime = timeStamp;
}
@@ -372,4 +356,19 @@
}
return mStringCache.valueAt(index);
}
+
+ /**
+ * When an IntervalStats object is deserialized, if the object's version number
+ * is lower than current version number, optionally perform a upgrade.
+ */
+ void upgradeIfNeeded() {
+ // We only uprade on majorVersion change, no need to upgrade on minorVersion change.
+ if (!(majorVersion < CURRENT_MAJOR_VERSION)) {
+ return;
+ }
+ /*
+ Optional upgrade code here.
+ */
+ majorVersion = CURRENT_MAJOR_VERSION;
+ }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 30d303f..8e1c060 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -21,13 +21,12 @@
import android.app.usage.UsageStats;
import android.content.res.Configuration;
import android.util.ArrayMap;
-
import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.net.ProtocolException;
import java.util.ArrayList;
@@ -105,6 +104,7 @@
stats = tempPackageIndex;
break;
case (int) IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS:
+ // Time attributes stored is an offset of the beginTime.
stats.mLastTimeUsed = statsOut.beginTime + proto.readLong(
IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS);
break;
@@ -113,7 +113,8 @@
IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS);
break;
case (int) IntervalStatsProto.UsageStats.LAST_EVENT:
- stats.mLastEvent = proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
+ stats.mLastEvent =
+ proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
break;
case (int) IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT:
stats.mAppLaunchCount = proto.readInt(
@@ -125,6 +126,15 @@
loadChooserCounts(proto, stats);
proto.end(chooserToken);
break;
+ case (int) IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS:
+ // Time attributes stored is an offset of the beginTime.
+ stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + proto.readLong(
+ IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS);
+ break;
+ case (int) IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS:
+ stats.mTotalTimeForegroundServiceUsed = proto.readLong(
+ IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS);
+ break;
}
}
if (stats.mLastTimeUsed == 0) {
@@ -315,11 +325,18 @@
+ ") not found in IntervalStats string cache");
proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
}
+ // Time attributes stored as an offset of the beginTime.
proto.write(IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
usageStats.mLastTimeUsed - stats.beginTime);
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS,
usageStats.mTotalTimeInForeground);
- proto.write(IntervalStatsProto.UsageStats.LAST_EVENT, usageStats.mLastEvent);
+ proto.write(IntervalStatsProto.UsageStats.LAST_EVENT,
+ usageStats.mLastEvent);
+ // Time attributes stored as an offset of the beginTime.
+ proto.write(IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
+ usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
+ proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
+ usageStats.mTotalTimeForegroundServiceUsed);
proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
writeChooserCounts(proto, usageStats);
proto.end(token);
@@ -471,6 +488,14 @@
statsOut.endTime = statsOut.beginTime + proto.readLong(
IntervalStatsProto.END_TIME_MS);
break;
+ case (int) IntervalStatsProto.MAJOR_VERSION:
+ statsOut.majorVersion = proto.readInt(
+ IntervalStatsProto.MAJOR_VERSION);
+ break;
+ case (int) IntervalStatsProto.MINOR_VERSION:
+ statsOut.minorVersion = proto.readInt(
+ IntervalStatsProto.MINOR_VERSION);
+ break;
case (int) IntervalStatsProto.INTERACTIVE:
loadCountAndTime(proto, IntervalStatsProto.INTERACTIVE,
statsOut.interactiveTracker);
@@ -505,6 +530,7 @@
// endTime not assigned, assume default value of 0 plus beginTime
statsOut.endTime = statsOut.beginTime;
}
+ statsOut.upgradeIfNeeded();
return;
}
}
@@ -519,6 +545,8 @@
public static void write(OutputStream out, IntervalStats stats) throws IOException {
final ProtoOutputStream proto = new ProtoOutputStream(out);
proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
+ proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
+ proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
// String pool should be written before the rest of the usage stats
writeStringPool(proto, stats);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index a68f9d3..d940620 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -15,19 +15,18 @@
*/
package com.android.server.usage;
+import android.app.usage.ConfigurationStats;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.content.res.Configuration;
+import android.util.ArrayMap;
+
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-import android.app.usage.ConfigurationStats;
-import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
-import android.content.res.Configuration;
-import android.util.ArrayMap;
-
import java.io.IOException;
import java.net.ProtocolException;
@@ -61,6 +60,7 @@
private static final String FLAGS_ATTR = "flags";
private static final String CLASS_ATTR = "class";
private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
+ private static final String TOTAL_TIME_SERVICE_USED_ATTR = "timeServiceUsed";
private static final String COUNT_ATTR = "count";
private static final String ACTIVE_ATTR = "active";
private static final String LAST_EVENT_ATTR = "lastEvent";
@@ -69,9 +69,12 @@
private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount";
private static final String NOTIFICATION_CHANNEL_ATTR = "notificationChannel";
+ private static final String MAJOR_VERSION_ATTR = "majorVersion";
+ private static final String MINOR_VERSION_ATTR = "minorVersion";
// Time attributes stored as an offset of the beginTime.
private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+ private static final String LAST_TIME_SERVICE_USED_ATTR = "lastTimeServiceUsed";
private static final String END_TIME_ATTR = "endTime";
private static final String TIME_ATTR = "time";
@@ -86,9 +89,14 @@
// Apply the offset to the beginTime to find the absolute time.
stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
parser, LAST_TIME_ACTIVE_ATTR);
+ stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
+ parser, LAST_TIME_SERVICE_USED_ATTR);
stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
+ stats.mTotalTimeForegroundServiceUsed = XmlUtils.readLongAttribute(parser,
+ TOTAL_TIME_SERVICE_USED_ATTR);
stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
- stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR, 0);
+ stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR,
+ 0);
int eventCode;
while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) {
final String tag = parser.getName();
@@ -206,9 +214,12 @@
// Write the time offset.
XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
usageStats.mLastTimeUsed - stats.beginTime);
-
+ XmlUtils.writeLongAttribute(xml, LAST_TIME_SERVICE_USED_ATTR,
+ usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+ XmlUtils.writeLongAttribute(xml, TOTAL_TIME_SERVICE_USED_ATTR,
+ usageStats.mTotalTimeForegroundServiceUsed);
XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
if (usageStats.mAppLaunchCount > 0) {
XmlUtils.writeIntAttribute(xml, APP_LAUNCH_COUNT_ATTR, usageStats.mAppLaunchCount);
@@ -339,6 +350,8 @@
}
statsOut.endTime = statsOut.beginTime + XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
+ statsOut.majorVersion = XmlUtils.readIntAttribute(parser, MAJOR_VERSION_ATTR);
+ statsOut.minorVersion = XmlUtils.readIntAttribute(parser, MINOR_VERSION_ATTR);
int eventCode;
int outerDepth = parser.getDepth();
@@ -391,6 +404,8 @@
*/
public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
+ XmlUtils.writeIntAttribute(xml, MAJOR_VERSION_ATTR, stats.majorVersion);
+ XmlUtils.writeIntAttribute(xml, MINOR_VERSION_ATTR, stats.minorVersion);
writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveTracker.count,
stats.interactiveTracker.duration);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 1a8aba0..32875da 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -22,9 +22,9 @@
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
+import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemClock;
-import android.content.Context;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -129,11 +129,17 @@
for (IntervalStats stat : mCurrentStats) {
final int pkgCount = stat.packageStats.size();
for (int i = 0; i < pkgCount; i++) {
- UsageStats pkgStats = stat.packageStats.valueAt(i);
- if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
- pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
- stat.update(pkgStats.mPackageName, stat.lastTimeSaved,
- UsageEvents.Event.END_OF_DAY);
+ final UsageStats pkgStats = stat.packageStats.valueAt(i);
+ if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+ || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+ if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+ stat.update(pkgStats.mPackageName, null, stat.lastTimeSaved,
+ UsageEvents.Event.END_OF_DAY);
+ }
+ if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+ stat.update(pkgStats.mPackageName, null , stat.lastTimeSaved,
+ UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+ }
notifyStatsChanged();
}
}
@@ -218,7 +224,8 @@
stats.updateKeyguardHidden(event.mTimeStamp);
} break;
default: {
- stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ stats.update(event.mPackage, event.getClassName(),
+ event.mTimeStamp, event.mEventType);
if (incrementAppLaunch) {
stats.incrementAppLaunchCount(event.mPackage);
}
@@ -481,25 +488,43 @@
final long startTime = SystemClock.elapsedRealtime();
Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
- // Finish any ongoing events with an END_OF_DAY event. Make a note of which components
- // need a new CONTINUE_PREVIOUS_DAY entry.
+ // Finish any ongoing events with an END_OF_DAY or ROLLOVER_FOREGROUND_SERVICE event.
+ // Make a note of which components need a new CONTINUE_PREVIOUS_DAY or
+ // CONTINUING_FOREGROUND_SERVICE entry.
final Configuration previousConfig =
mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
ArraySet<String> continuePreviousDay = new ArraySet<>();
+ ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundActivity =
+ new ArrayMap<>();
+ ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundService =
+ new ArrayMap<>();
for (IntervalStats stat : mCurrentStats) {
final int pkgCount = stat.packageStats.size();
for (int i = 0; i < pkgCount; i++) {
- UsageStats pkgStats = stat.packageStats.valueAt(i);
- if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
- pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
+ final UsageStats pkgStats = stat.packageStats.valueAt(i);
+ if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+ || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+ if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+ continuePreviousDayForegroundActivity.put(pkgStats.mPackageName,
+ pkgStats.mLastForegroundActivityEventMap);
+ stat.update(pkgStats.mPackageName, null,
+ mDailyExpiryDate.getTimeInMillis() - 1,
+ UsageEvents.Event.END_OF_DAY);
+ }
+ if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+ continuePreviousDayForegroundService.put(pkgStats.mPackageName,
+ pkgStats.mLastForegroundServiceEventMap);
+ stat.update(pkgStats.mPackageName, null,
+ mDailyExpiryDate.getTimeInMillis() - 1,
+ UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+ }
continuePreviousDay.add(pkgStats.mPackageName);
- stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1,
- UsageEvents.Event.END_OF_DAY);
notifyStatsChanged();
}
}
- stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
+ stat.updateConfigurationStats(null,
+ mDailyExpiryDate.getTimeInMillis() - 1);
stat.commitTime(mDailyExpiryDate.getTimeInMillis() - 1);
}
@@ -509,10 +534,27 @@
final int continueCount = continuePreviousDay.size();
for (int i = 0; i < continueCount; i++) {
- String name = continuePreviousDay.valueAt(i);
+ String pkgName = continuePreviousDay.valueAt(i);
final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
for (IntervalStats stat : mCurrentStats) {
- stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+ if (continuePreviousDayForegroundActivity.containsKey(pkgName)) {
+ final ArrayMap<String, Integer> foregroundActivityEventMap =
+ continuePreviousDayForegroundActivity.get(pkgName);
+ final int size = foregroundActivityEventMap.size();
+ for (int j = 0; j < size; j++) {
+ stat.update(pkgName, foregroundActivityEventMap.keyAt(j), beginTime,
+ UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+ }
+ }
+ if (continuePreviousDayForegroundService.containsKey(pkgName)) {
+ final ArrayMap<String, Integer> foregroundServiceEventMap =
+ continuePreviousDayForegroundService.get(pkgName);
+ final int size = foregroundServiceEventMap.size();
+ for (int j = 0; j < size; j++) {
+ stat.update(pkgName, foregroundServiceEventMap.keyAt(j), beginTime,
+ UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE);
+ }
+ }
stat.updateConfigurationStats(previousConfig, beginTime);
notifyStatsChanged();
}
@@ -837,10 +879,18 @@
return "MOVE_TO_BACKGROUND";
case UsageEvents.Event.MOVE_TO_FOREGROUND:
return "MOVE_TO_FOREGROUND";
+ case UsageEvents.Event.FOREGROUND_SERVICE_START:
+ return "FOREGROUND_SERVICE_START";
+ case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+ return "FOREGROUND_SERVICE_STOP";
case UsageEvents.Event.END_OF_DAY:
return "END_OF_DAY";
+ case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
+ return "ROLLOVER_FOREGROUND_SERVICE";
case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
return "CONTINUE_PREVIOUS_DAY";
+ case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
+ return "CONTINUING_FOREGROUND_SERVICE";
case UsageEvents.Event.CONFIGURATION_CHANGE:
return "CONFIGURATION_CHANGE";
case UsageEvents.Event.SYSTEM_INTERACTION:
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index b6ac91d..cef99865 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -21,6 +21,7 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
@@ -322,8 +323,11 @@
/**
* Call can be upgraded to a video call.
* @hide
+ * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+ * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
+ * whether or not video calling is supported.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
/**
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 34603a3..0589cd4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -272,6 +272,9 @@
/**
* Call can be upgraded to a video call.
+ * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+ * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call whether or not
+ * video calling is supported.
*/
public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 9a4ea9e7..2ffad03 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -985,10 +985,10 @@
/**
* Generates a string representation of a capabilities bitmask.
*
- * @param capabilities The capabilities bitmask.
* @return String representation of the capabilities bitmask.
+ * @hide
*/
- private String capabilitiesToString() {
+ public String capabilitiesToString() {
StringBuilder sb = new StringBuilder();
if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
sb.append("SelfManaged ");
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index fa16bfe..9f0bdd7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -15,6 +15,7 @@
package android.telecom;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressAutoDoc;
@@ -36,6 +37,8 @@
import com.android.internal.telecom.ITelecomService;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -413,8 +416,10 @@
* <p>
* The phone number of the call used by Telecom to determine which call should be handed over.
* @hide
+ * @deprecated Use the public handover APIs. See
+ * {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} for more information.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
public static final String EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER";
/**
@@ -528,11 +533,19 @@
public static final char DTMF_CHARACTER_WAIT = ';';
/**
+ * @hide
+ */
+ @IntDef(prefix = { "TTY_MODE_" },
+ value = {TTY_MODE_OFF, TTY_MODE_FULL, TTY_MODE_HCO, TTY_MODE_VCO})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TtyMode {}
+
+ /**
* TTY (teletypewriter) mode is off.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int TTY_MODE_OFF = 0;
/**
@@ -541,6 +554,7 @@
*
* @hide
*/
+ @SystemApi
public static final int TTY_MODE_FULL = 1;
/**
@@ -550,6 +564,7 @@
*
* @hide
*/
+ @SystemApi
public static final int TTY_MODE_HCO = 2;
/**
@@ -559,6 +574,7 @@
*
* @hide
*/
+ @SystemApi
public static final int TTY_MODE_VCO = 3;
/**
@@ -827,8 +843,9 @@
* @return The phone account handle of the current sim call manager.
*
* @hide
+ * @deprecated Use {@link #getSimCallManager()}.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
public PhoneAccountHandle getSimCallManager(int userId) {
try {
if (isServiceConnected()) {
@@ -929,10 +946,12 @@
* Returns a list of {@link PhoneAccountHandle}s including those which have not been enabled
* by the user.
*
+ * @param includeDisabledAccounts When {@code true}, disabled phone accounts will be included,
+ * when {@code false}, only
* @return A list of {@code PhoneAccountHandle} objects.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
public List<PhoneAccountHandle> getCallCapablePhoneAccounts(boolean includeDisabledAccounts) {
try {
if (isServiceConnected()) {
@@ -1155,7 +1174,7 @@
/**
* Used to set the default dialer package.
*
- * @param packageName to set the default dialer to..
+ * @param packageName to set the default dialer to.
*
* @result {@code true} if the default dialer was successfully changed, {@code false} if
* the specified package does not correspond to an installed dialer, or is already
@@ -1166,7 +1185,10 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ android.Manifest.permission.WRITE_SECURE_SETTINGS})
public boolean setDefaultDialer(String packageName) {
try {
if (isServiceConnected()) {
@@ -1179,12 +1201,10 @@
}
/**
- * Used to determine the dialer package that is preloaded on the system partition.
+ * Determines the package name of the system-provided default phone app.
*
* @return package name for the system dialer package or null if no system dialer is preloaded.
- * @hide
*/
- @UnsupportedAppUsage
public String getSystemDialerPackage() {
try {
if (isServiceConnected()) {
@@ -1545,8 +1565,9 @@
* - {@link TelecomManager#TTY_MODE_VCO}
* @hide
*/
- @UnsupportedAppUsage
- public int getCurrentTtyMode() {
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @TtyMode int getCurrentTtyMode() {
try {
if (isServiceConnected()) {
return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName());
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 26e1fb7..f5dff20 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -858,4 +858,4 @@
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
-}
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/RcsManager.java b/telephony/java/android/telephony/rcs/RcsManager.java
similarity index 86%
rename from telephony/java/android/telephony/RcsManager.java
rename to telephony/java/android/telephony/rcs/RcsManager.java
index 00ce03a..0ef4e15 100644
--- a/telephony/java/android/telephony/RcsManager.java
+++ b/telephony/java/android/telephony/rcs/RcsManager.java
@@ -14,18 +14,22 @@
* limitations under the License.
*/
-package android.telephony;
+package android.telephony.rcs;
+import android.annotation.SystemService;
+import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.telephony.Rlog;
-import com.android.internal.telephony.IRcs;
+import com.android.internal.telephony.rcs.IRcs;
/**
* RcsManager is the application interface to RcsProvider and provides access methods to
* RCS related database tables.
* @hide - TODO make this public
*/
+@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
private static final String TAG = "RcsManager";
private static final boolean VDBG = false;
diff --git a/telephony/java/android/telephony/rcs/RcsThread.aidl b/telephony/java/android/telephony/rcs/RcsThread.aidl
new file mode 100644
index 0000000..e2e0da5d
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 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.telephony;
+
+parcelable RcsThread;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/rcs/RcsThread.java b/telephony/java/android/telephony/rcs/RcsThread.java
new file mode 100644
index 0000000..83eb973
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.java
@@ -0,0 +1,75 @@
+/*
+ * 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.telephony.rcs;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.rcs.IRcs;
+
+/**
+ * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
+ * received and events that occured on that thread.
+ * @hide - TODO(sahinc) make this public
+ */
+public class RcsThread implements Parcelable {
+ public static final Creator<RcsThread> CREATOR = new Creator<RcsThread>() {
+ @Override
+ public RcsThread createFromParcel(Parcel in) {
+ return new RcsThread(in);
+ }
+
+ @Override
+ public RcsThread[] newArray(int size) {
+ return new RcsThread[size];
+ }
+ };
+
+ protected RcsThread(Parcel in) {
+ }
+
+ /**
+ * Returns the number of messages in this RCS thread.
+ *
+ * @hide
+ */
+ public int getMessageCount() {
+ try {
+ IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+ if (iRcs != null) {
+ // TODO(sahinc): substitute to the regular thread id once we have database
+ // TODO(sahinc): connection in place
+ return iRcs.getMessageCount(/* rcsThreadId= */ 123);
+ }
+ } catch (RemoteException re) {
+ // TODO(sahinc): Log something meaningful
+ }
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
similarity index 83%
rename from telephony/java/com/android/internal/telephony/IRcs.aidl
rename to telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
index ede8695..4c289ac 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
@@ -14,8 +14,12 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package com.android.internal.telephony.rcs;
interface IRcs {
+ // RcsManager APIs
void deleteThread(int threadId);
+
+ // RcsThread APIs
+ int getMessageCount(int rcsThreadId);
}
\ No newline at end of file
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
new file mode 100644
index 0000000..adc7cab
--- /dev/null
+++ b/tests/RcsTests/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := RcsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
new file mode 100644
index 0000000..a7e7d47
--- /dev/null
+++ b/tests/RcsTests/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.rcs">
+ <application android:label="RCS Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.tests.rcs"/>
+</manifest>
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
new file mode 100644
index 0000000..7f5f03e
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.tests.rcs;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.rcs.RcsManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsManagerTest {
+ //TODO(sahinc): Add meaningful tests once we have more of the implementation in place
+ @Test
+ public void testDeleteThreadDoesntCrash() {
+ RcsManager mRcsManager = new RcsManager();
+ mRcsManager.deleteThread(0);
+ }
+}
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index 8467bee..be74a6d 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -18,10 +18,6 @@
import static junit.framework.Assert.assertEquals;
-import com.android.server.usage.UsageStatsDatabase;
-import com.android.server.usage.UsageStatsDatabase.StatCombiner;
-import com.android.server.usage.IntervalStats;
-
import android.app.usage.EventList;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
@@ -29,10 +25,14 @@
import android.os.SystemClock;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.PerfManualStatusReporter;
-import android.support.test.filters.LargeTest;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
+import com.android.server.usage.IntervalStats;
+import com.android.server.usage.UsageStatsDatabase;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@@ -90,11 +90,13 @@
for (int pkg = 0; pkg < packageCount; pkg++) {
UsageEvents.Event event = new UsageEvents.Event();
event.mPackage = "fake.package.name" + pkg;
+ event.mClass = event.mPackage + ".class1";
event.mTimeStamp = 1;
event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
for (int evt = 0; evt < eventsPerPackage; evt++) {
intervalStats.events.insert(event);
- intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
+ event.mEventType);
}
}
}